Commit graph

55 commits

Author SHA1 Message Date
Jeffrey (Dongkyu) Kim
bbba283151 Archive unsupported map skills 2026-06-05 22:24:15 +09:00
Jeffrey (Dongkyu) Kim
e6d7072e93
Feature/#274 (#277)
* Add Seoul Bike live station lookup

Expose narrow Seoul Open Data proxy surfaces for realtime bike availability, station master pages, and coordinate-based nearby lookups while keeping the upstream key server-side. Add a single Python skill entrypoint plus docs so agents can answer last-mile bike and dock availability questions.

Constraint: Issue #274 requires , TDD, three proxy routes, branch feature/#274, and PR to dev.
Rejected: Client-side Seoul OpenAPI key handling | would leak upstream credentials and violate existing proxy patterns.
Confidence: high
Scope-risk: moderate
Directive: Keep these routes read-only; do not add rental/booking mutations or user-key requirements.
Tested: node --test packages/k-skill-proxy/test/server.test.js --test-name-pattern 'seoul bike'; PYTHONPATH=.:scripts python3 -m unittest scripts.test_seoul_bike; local fake-proxy smoke run; PATH="/Users/jeffrey/.pyenv/versions/3.11.9/bin:/Users/jeffrey/.codex/tmp/arg0/codex-arg08RBix6:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/path:/Users/jeffrey/.cmuxterm/omo-bin:/opt/homebrew/share/android-commandlinetools/platform-tools:/opt/homebrew/share/android-commandlinetools/emulator:/opt/homebrew/share/android-commandlinetools/cmdline-tools/latest/bin:/Users/jeffrey/.local/bin:/Users/jeffrey/.bun/bin:/opt/homebrew/opt/node@22/bin:/opt/homebrew/opt/openjdk@21/bin:/opt/homebrew/opt/postgresql@18/bin:/Users/jeffrey/.jenv/shims:/Users/jeffrey/.jenv/bin:/opt/homebrew/opt/imagemagick/bin:/opt/homebrew/Cellar/pyenv-virtualenv/1.4.0/shims:/Users/jeffrey/.pyenv/shims:/opt/homebrew/opt/openssl@3/bin:/Users/jeffrey/.rbenv/shims:/Users/jeffrey/.rbenv/bin:/Users/jeffrey/google-cloud-sdk/bin:/Applications/cmux.app/Contents/Resources/bin:/Users/jeffrey/Library/pnpm:/Users/jeffrey/.nvm/versions/node/v24.13.0/bin:/Users/jeffrey/.cops/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Library/TeX/texbin:/Users/jeffrey/.cargo/bin:/Users/jeffrey/Library/Application Support/JetBrains/Toolbox/scripts:/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin:/Users/jeffrey/xcode-projects/marshroom/cli" npm run ci.
Not-tested: Live hosted Seoul Open Data request with production SEOUL_OPEN_API_KEY.

* Prevent Seoul Bike upstream errors from masquerading as empty availability

Constraint: Seoul Open API can return application-level error JSON with HTTP 200, so proxy routes must inspect RESULT envelopes before caching or normalizing rows.
Rejected: Treating missing rentBikeStatus.row as an empty success | it masks quota/service failures and caches false no-station results.
Confidence: high
Scope-risk: narrow
Directive: Preserve non-cacheable proxy error behavior for Seoul Open API semantic failures across realtime, stations, and nearby routes.
Tested: node --test packages/k-skill-proxy/test/server.test.js --test-name-pattern 'seoul bike'; PYTHONPATH=.:scripts python3 -m unittest scripts.test_seoul_bike; local fake-proxy seoul_bike.py nearby smoke; PATH="/Users/jeffrey/.pyenv/versions/3.11.9/bin:/Users/jeffrey/.codex/tmp/arg0/codex-arg0j0fIum:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/path:/Users/jeffrey/.cmuxterm/omo-bin:/opt/homebrew/share/android-commandlinetools/platform-tools:/opt/homebrew/share/android-commandlinetools/emulator:/opt/homebrew/share/android-commandlinetools/cmdline-tools/latest/bin:/Users/jeffrey/.local/bin:/Users/jeffrey/.bun/bin:/opt/homebrew/opt/node@22/bin:/opt/homebrew/opt/openjdk@21/bin:/opt/homebrew/opt/postgresql@18/bin:/Users/jeffrey/.jenv/shims:/Users/jeffrey/.jenv/bin:/opt/homebrew/opt/imagemagick/bin:/opt/homebrew/Cellar/pyenv-virtualenv/1.4.0/shims:/Users/jeffrey/.pyenv/shims:/opt/homebrew/opt/openssl@3/bin:/Users/jeffrey/.rbenv/shims:/Users/jeffrey/.rbenv/bin:/Users/jeffrey/google-cloud-sdk/bin:/Applications/cmux.app/Contents/Resources/bin:/Users/jeffrey/Library/pnpm:/Users/jeffrey/.nvm/versions/node/v24.13.0/bin:/Users/jeffrey/.cops/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Library/TeX/texbin:/Users/jeffrey/.cargo/bin:/Users/jeffrey/Library/Application Support/JetBrains/Toolbox/scripts:/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin:/Users/jeffrey/xcode-projects/marshroom/cli" npm run ci; architect review APPROVED.
Not-tested: Live Seoul Open API error response from production service.

* Reject ambiguous Seoul Bike integer input

Tighten the public Seoul Bike query boundary so malformed integer strings cannot be partially parsed into valid requests.

Constraint: PR #277 review found parseInt accepted partially numeric query values on Seoul Bike routes.\nRejected: Keep parseInt with bounds checks | bounds still allow misleading values like 10abc and 1.5.\nConfidence: high\nScope-risk: narrow\nDirective: Keep Seoul Bike public query aliases strict; do not reintroduce partial numeric parsing.\nTested: node --test packages/k-skill-proxy/test/server.test.js --test-name-pattern 'seoul bike'; PYTHONPATH=.:scripts python3 -m unittest scripts.test_seoul_bike; explicit app.inject invalid-query smoke; PATH="/Users/jeffrey/.pyenv/versions/3.11.9/bin:/Users/jeffrey/.codex/tmp/arg0/codex-arg0uv50Mt:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/path:/Users/jeffrey/.cmuxterm/omo-bin:/opt/homebrew/share/android-commandlinetools/platform-tools:/opt/homebrew/share/android-commandlinetools/emulator:/opt/homebrew/share/android-commandlinetools/cmdline-tools/latest/bin:/Users/jeffrey/.local/bin:/Users/jeffrey/.bun/bin:/opt/homebrew/opt/node@22/bin:/opt/homebrew/opt/openjdk@21/bin:/opt/homebrew/opt/postgresql@18/bin:/Users/jeffrey/.jenv/shims:/Users/jeffrey/.jenv/bin:/opt/homebrew/opt/imagemagick/bin:/opt/homebrew/Cellar/pyenv-virtualenv/1.4.0/shims:/Users/jeffrey/.pyenv/shims:/opt/homebrew/opt/openssl@3/bin:/Users/jeffrey/.rbenv/shims:/Users/jeffrey/.rbenv/bin:/Users/jeffrey/google-cloud-sdk/bin:/Applications/cmux.app/Contents/Resources/bin:/Users/jeffrey/Library/pnpm:/Users/jeffrey/.nvm/versions/node/v24.13.0/bin:/Users/jeffrey/.cops/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Library/TeX/texbin:/Users/jeffrey/.cargo/bin:/Users/jeffrey/Library/Application Support/JetBrains/Toolbox/scripts:/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin:/Users/jeffrey/xcode-projects/marshroom/cli" npm run ci\nNot-tested: live hosted Seoul Open API traffic

* Protect hosted Seoul Bike proxy secrets

Sanitize Seoul Bike upstream fetch and parse failures before they can reach the global error handler, and reject blank nearby coordinates before JavaScript can coerce them to zero.\n\nConstraint: PR #277 round-3 review found server-side Seoul Open API keys could leak through exception messages containing keyed upstream URLs.\nRejected: Letting the global error handler format Seoul Bike upstream exceptions | it echoes exception messages and can expose the hosted proxy API key.\nConfidence: high\nScope-risk: narrow\nDirective: Keep server-side API-key-bearing upstream URLs out of client-visible error messages and logs for hosted no-user-key routes.\nTested: node --test packages/k-skill-proxy/test/server.test.js --test-name-pattern 'seoul bike'; PYTHONPATH=.:scripts python3 -m unittest scripts.test_seoul_bike; explicit app.inject smoke for sanitized Seoul Bike failures and blank coordinates; local fake-proxy seoul-bike nearby smoke; PATH="/Users/jeffrey/.pyenv/versions/3.11.9/bin:/Users/jeffrey/.codex/tmp/arg0/codex-arg0mxZmWx:/opt/homebrew/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/path:/Users/jeffrey/.cmuxterm/omo-bin:/opt/homebrew/share/android-commandlinetools/platform-tools:/opt/homebrew/share/android-commandlinetools/emulator:/opt/homebrew/share/android-commandlinetools/cmdline-tools/latest/bin:/Users/jeffrey/.local/bin:/Users/jeffrey/.bun/bin:/opt/homebrew/opt/node@22/bin:/opt/homebrew/opt/openjdk@21/bin:/opt/homebrew/opt/postgresql@18/bin:/Users/jeffrey/.jenv/shims:/Users/jeffrey/.jenv/bin:/opt/homebrew/opt/imagemagick/bin:/opt/homebrew/Cellar/pyenv-virtualenv/1.4.0/shims:/Users/jeffrey/.pyenv/shims:/opt/homebrew/opt/openssl@3/bin:/Users/jeffrey/.rbenv/shims:/Users/jeffrey/.rbenv/bin:/Users/jeffrey/google-cloud-sdk/bin:/Applications/cmux.app/Contents/Resources/bin:/Users/jeffrey/Library/pnpm:/Users/jeffrey/.nvm/versions/node/v24.13.0/bin:/Users/jeffrey/.cops/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/Library/TeX/texbin:/Users/jeffrey/.cargo/bin:/Users/jeffrey/Library/Application Support/JetBrains/Toolbox/scripts:/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin:/Users/jeffrey/xcode-projects/marshroom/cli" npm run ci.\nNot-tested: Live Seoul Open API network failure from production Cloud Run.
2026-05-22 13:54:36 +09:00
lee-ji-hong
ca5aefd990 Add Ohou today deal skill 2026-05-18 15:40:18 +09:00
hmmhmmhm/
e5b4465630
영화관 검색 스킬 추가 (#260)
* Add korean cinema search skill

* Document playDate for cinema skill
2026-05-18 11:42:40 +09:00
Jeffrey (Dongkyu) Kim
d11c7d37bf Add court-auction-notice-search skill and package (#167)
Implement Workflow A (매각공고 → 사건/물건 펼치기) and Workflow B
(사건번호 직조회) MVP for the official 대법원경매정보 site
courtauction.go.kr. The package exposes searchSaleNotices,
getSaleNoticeDetail, getCaseByCaseNumber, and getCourtCodes plus a
court-auction-notice-search CLI mirror. Direct HTTP transport is the
default with a Playwright fallback (rebrowser-playwright /
playwright-core, dynamic import) for blocked/5xx situations.

Anti-bot guardrails: minimum 2s + jitter between calls, 10-call
session budget, immediate BLOCKED throw on data.ipcheck === false, and
no automatic retry to avoid extending the site's IP block. Fixtures
were captured from live courtauction.go.kr endpoints during discovery
and live smoke tests verify each public API end-to-end.

Workflow C (자유 조건검색), Workflow D (일별/월별 캘린더), 매각물건
사진/PDF, and 동산 경매는 follow-up issues로 분리됨.
2026-04-29 16:36:55 +09:00
Jeffrey (Dongkyu) Kim
dac6e7b742 Add safe IROS registry certificate guidance
Issue #175 needs a 등기부등본 skill grounded in the challengekim reference implementation while preserving user control over IROS login, authentication, and payment. Add a docs-first skill with regression coverage that locks the upstream credit, safety boundaries, and repository documentation wiring.

Constraint: Original author link must be mentioned in documentation.\nConstraint: IROS login, certificate authentication, and card payment must remain user-controlled.\nRejected: Add a packaged automation wrapper | no dependency or executable implementation was required and credential/payment flows are high-risk.\nConfidence: high\nScope-risk: narrow\nDirective: Do not remove the challengekim upstream credit or weaken the manual login/payment boundary without a new review.\nTested: node --test --test-name-pattern='iros-registry-automation' scripts/skill-docs.test.js; ./scripts/validate-skills.sh; npm run ci\nNot-tested: Live IROS smoke with real login/payment, intentionally not run without user credentials and payment authority
2026-04-28 14:25:36 +09:00
Jeffrey (Dongkyu) Kim
dadc5f4ffa Add rhwp-edit and rhwp-advanced skills with k-skill-rhwp CLI
Splits HWP handling into three focused skills per issue #155:

- hwp (kept): kordoc-based read/convert (Markdown, JSON, diffing, form
  fields, Markdown->HWPX). Description narrowed to 'read-only' to make
  the routing policy explicit.
- rhwp-edit (new): HWP binary editing via new k-skill-rhwp npm package
  that wraps the @rhwp/core WASM bindings as CLI subcommands: info,
  list-paragraphs, search, insert-text, delete-text, replace-all,
  create-table, set-cell-text, create-blank, and render.
- rhwp-advanced (new): guidance for the upstream Rust rhwp CLI
  (export-svg --debug-overlay, dump, dump-pages, ir-diff, thumbnail,
  convert) for layout debugging, IR inspection, version comparison,
  and read-only-document unlocking.

The new k-skill-rhwp package under packages/ ships a Node.js 18+ CLI
and library that round-trips HWP 5.x documents entirely in-process; no
Rust toolchain is required. It auto-installs the WASM-required
globalThis.measureTextWidth shim for headless Node, and all editing
subcommands always write to a distinct output path so the source file
is never mutated. HWPX save remains disabled per the upstream rhwp
#196 data-safety gate; HWPX input is accepted but output is written as
HWP 5.x.

Includes 24 node:test cases covering init, round-trip insertText,
replaceAll, createTable + setCellText, deleteText, searchText,
listParagraphs, renderPage (SVG/HTML), and full CLI arg-parse +
end-to-end round-trip through the CLI layer.

Wires README feature table (3 rows for hwp / rhwp-edit / rhwp-advanced),
docs/install.md optional-install list, docs/roadmap.md (marks HWP
advanced editing as shipped while keeping Windows/security-module
automation out of scope), docs/sources.md (adds rhwp upstream, CLI
source, @rhwp/core, @rhwp/editor, and rhwp #196 references), and the
root pack:dry-run script. Adds a Changesets entry for k-skill-rhwp
minor.

Closes #155.
2026-04-22 12:45:13 +09:00
Jeffrey (Dongkyu) Kim
617a025931 Add lh-notice-search skill and /v1/lh-notice/{search,detail} proxy routes
Wraps the official data.go.kr LH (Korea Land & Housing Corporation) 청약
공고 Open API (B552555/lhLeaseNoticeInfo1/*) so agents can look up LH
임대/분양/주거복지/토지/상가 공고 by region, status, category, keyword,
and notice ID without asking users for a ServiceKey. Reuses the shared
DATA_GO_KR_API_KEY the proxy already manages; users see '불필요'.

Adapter handles both the LH-specific [CMN, dsList] JSON envelope and the
standard data.go.kr <OpenAPI_ServiceResponse> XML error envelope; refuses
to cache failure responses so transient upstream errors self-heal.

Closes #145.
2026-04-22 10:58:03 +09:00
Jeffrey (Dongkyu) Kim
d0c014e38b Document korean-privacy-terms skill across repo docs 2026-04-20 12:06:57 +09:00
Jeffrey (Dongkyu) Kim
303374aaa6 Refactor Coupang skill to retention MCP layer 2026-04-18 22:18:51 +09:00
Jeffrey (Dongkyu) Kim
7c0bfa4c93
Feature/#129 (#131)
* Add official KBL results support so basketball queries use live league data

Issue #129 needs a read-only skill and reusable package for KBL schedules, results, and standings. The implementation follows the existing sports package pattern and uses the league's live JSON APIs after verifying they respond successfully in real requests.

Constraint: Must use official KBL JSON surfaces before considering scraping
Constraint: Packaging changes must pass npm run ci and include docs plus Changesets updates
Rejected: Browser scraping first | official api.kbl.or.kr endpoints are live and simpler to maintain
Rejected: Reuse KBO/K League package shapes verbatim | KBL payload and team/status fields differ materially
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep seasonGrade=1 as the default KBL path unless future docs/tests explicitly widen to D-League flows
Tested: npm run ci; npm run lint --workspace kbl-results; npm test --workspace kbl-results; live getKBLSummary("2026-04-01", { team: "KCC", includeStandings: true })
Not-tested: Historical standings snapshots for past seasons via alternative KBL endpoints

* Prevent optional standings lookups from over-fetching the KBL API

The new kbl-results summary helper exposes includeStandings=false, so the
regression suite now proves that path stays schedule-only and never calls
the standings endpoint when the caller opts out.

Constraint: The KBL package should preserve the caller's no-standings contract
Rejected: Rely on manual inspection of the helper options | a targeted test is cheaper and safer
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep includeStandings=false side-effect free unless the public API contract changes explicitly
Tested: npm test --workspace kbl-results; npm run lint --workspace kbl-results
Not-tested: Full-repo CI before stacking this commit onto the rebased branch
2026-04-18 11:20:42 +09:00
minsing-jin
006acbd631
Add Korean scholarship search skill and reporting workflow (#116)
* Add nationwide scholarship search skill workflow

* Rename scholarship skill to 장학금 주세요 쮜에발

* Fix scholarship skill validation in CI

* Trigger GitHub PR diff refresh after dev rebase on main

* Fix scholarship helper status handling and test coverage

* Use KST as scholarship helper default date basis

* Rename scholarship skill display name

---------

Co-authored-by: Jeffrey (Dongkyu) Kim <vkehfdl1@gmail.com>
2026-04-16 14:58:58 +09:00
Jeffrey (Dongkyu) Kim
cd1c2d1503
Merge pull request #123 from NomaDamas/feature/#117
Feature/#117
2026-04-16 13:35:13 +09:00
Jeffrey (Dongkyu) Kim
34a1dbf80c
Merge pull request #122 from NomaDamas/feature/#120
Feature/#120
2026-04-16 13:18:28 +09:00
Jeffrey (Dongkyu) Kim
91d01eeec1 Help users find nearby public restrooms from Korean location queries
This adds a new public-restroom-nearby skill and reusable package that resolves a user-provided location, narrows the official 공중화장실정보 dataset by region when possible, and ranks nearby restroom results with opening-time hints and map links.

Constraint: Must use free official/open surfaces without introducing new dependencies
Constraint: Must follow TDD and keep release/docs metadata aligned in the same change
Rejected: Add a proxy route first | direct official CSV access already works and keeps scope narrower
Rejected: Use nationwide-only ranking without regional narrowing | too much noisy data for dense urban anchors
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If Kakao place-panel or localdata CSV schema changes, update parser fixtures before broad logic changes
Tested: npm run ci; live smoke via searchNearbyPublicRestroomsByLocationQuery('광화문', { limit: 3 }); architect review APPROVED
Not-tested: Non-Seoul live smoke across every regional orgCode
2026-04-16 11:42:42 +09:00
Jeffrey (Dongkyu) Kim
b56df8551d Add a guided Hola Poke Yeoksam skill without widening repo scope
Issue #120 only needs a repository skill payload, discoverability docs,
and regression coverage. This change adds the new skill, wires it into
existing docs surfaces, and locks the remote-MCP-only contract in tests
so future edits keep the phone-only event flow and verbatim message
relay behavior.

Constraint: The upstream Hola Poke flow lives on a remote MCP server, so this repo should not add proxy/runtime code
Constraint: Tests must be written before refining the new docs/skill wording
Rejected: Add local package or proxy support for Hola Poke | would over-scope a docs-only skill addition
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep this skill limited to 올라포케 역삼점 and treat the MCP response message as the event source of truth
Tested: node --test scripts/skill-docs.test.js --test-name-pattern='hola-poke-yeoksam'
Tested: npm run ci
Tested: Live MCP initialize/tools/list/get_menu/get_shop_info/enter_event(phone_format) smoke checks against https://hola-poke-yeoksam-skill.onrender.com/mcp
Not-tested: Successful live event entry with a real phone number
2026-04-16 11:17:17 +09:00
Jeffrey (Dongkyu) Kim
43e8625986 Add a repeatable GeekNews lookup path without unofficial APIs
Issue #108 needs a dedicated read-only skill that can browse,
search, and inspect GeekNews posts using the public feed alone.
The implementation adds a fixture-backed Atom helper, skill/docs
surfaces, and install/README wiring, then verifies the helper
against the live GeekNews feed.

Constraint: Must stay RSS-first and avoid new dependencies or unofficial APIs
Constraint: Skill development requires syncing the skill into ~/.claude/skills and ~/.agents/skills during verification
Rejected: Fetch article pages directly for v1 | expands scope beyond the approved RSS-driven workflow
Rejected: Use XML parser modules | current python3 environment has expat issues, so regex + HTML parsing is safer here
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the root helper and geeknews-search/scripts copy behaviorally identical because the installed skill must remain self-contained
Tested: PYTHONPATH=.:scripts python3 -m unittest scripts.test_geeknews_search; node --test scripts/skill-docs.test.js; python3 scripts/geeknews_search.py list --limit 3; python3 scripts/geeknews_search.py search --query Claude --limit 3; python3 scripts/geeknews_search.py detail --id 28439; npm run ci
Not-tested: Non-default feed mirrors or future Atom schema changes beyond the current public GeekNews feed shape
Related: Issue #108
2026-04-13 00:16:35 +09:00
Jeffrey (Dongkyu) Kim
4ce29ae009 Add a supported Market Kurly price-lookup skill
Implement a reusable Market Kurly workspace package plus a repo skill/doc set
that uses the unauthenticated Kurly search and goods-page surfaces.
The change keeps the scope read-only, adds regression coverage, updates
release/docs metadata, and records the new publishable package through
Changesets.

Constraint: Must rely on unauthenticated public web surfaces instead of login/session flows
Constraint: Release workflow requires Changesets for publishable Node packages
Rejected: Docs-only skill | issue approval called for real lookup helpers and live verification
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Kurly endpoints are web-internal surfaces; verify schema behavior before extending fields or adding action flows
Tested: npm run ci; live node smoke for countProducts/searchProducts/getProductDetail on 2026-04-09
Not-tested: Pagination beyond page 1; long-term stability of Kurly internal response schema
2026-04-09 14:51:30 +09:00
Jeffrey (Dongkyu) Kim
b2d0e364b8 Sync feature/#65 with dev so PR #87 can be reviewed again
Merged origin/dev into feature/#65, resolved the package.json and docs-test conflicts by keeping the Korean character count helper coverage while also preserving the newer MFDS safety skill wiring from dev. This keeps the branch reviewable without dropping either side's verification surface.

Constraint: PR #87 had to be updated from dev without regressing either shipped korean-character-count checks or newer dev-only MFDS coverage
Rejected: Re-resolve by favoring one side of the conflict wholesale | would silently drop verified test coverage from the other branch
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If package.json test wiring changes again, keep both the korean-character-count and MFDS helper suites in the root scripts unless the underlying features are intentionally removed
Tested: node --test scripts/skill-docs.test.js scripts/test_korean_character_count.js; node scripts/korean_character_count.js --text '가나다' --format json; node scripts/korean_character_count.js --file <tmpfile> --profile neis --format text; printf '한\r\n나' | node scripts/korean_character_count.js --stdin --format json; npm test; npm run ci
Not-tested: Live authenticated MFDS API success path still depends on external API key state
2026-04-09 00:28:31 +09:00
Jeffrey (Dongkyu) Kim
b2eedd827b Standardize Korean text counts for form-limited writing
Issue #65 needs deterministic Korean character, line, and byte counting for self-intros and similar forms, so this adds a bundled helper plus skill/docs/tests around a fixed grapheme/UTF-8 contract with an explicit NEIS compatibility profile.

Constraint: Must avoid LLM estimation and keep results deterministic across repeated runs
Constraint: No new dependencies; rely on Node 18+ Intl.Segmenter and Buffer.byteLength
Rejected: Per-request ad hoc scripts only | contract drift would make repeated counts inconsistent
Rejected: Legacy encoding heuristics as the default | modern UTF-8 contract is safer unless the target explicitly says otherwise
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep  and  profile semantics in sync with docs/tests before changing counting rules
Tested: node --test scripts/skill-docs.test.js scripts/test_korean_character_count.js; helper smoke via text/file/stdin; npm test; npm run ci; LSP diagnostics on changed JS files
Not-tested: Proprietary site-specific counters beyond the documented default/NEIS contracts
2026-04-08 22:55:31 +09:00
Jeffrey (Dongkyu) Kim
5793381517 Ship interview-first MFDS safety skills for drugs and food
The approved issue narrowed scope to two public-health skills: one for
official MFDS drug safety lookups and one for food safety / recall
lookups. This change adds both skills, bundles runnable Python helpers,
locks the docs and helper behavior with TDD regressions, and updates
repo docs so the interview-first safety flow is installed and verified
with the rest of k-skill.

Constraint: User-approved scope requires mandatory symptom follow-up before answering and forbids direct diagnosis
Constraint: Live MFDS data.go.kr success paths depend on upstream key approval/status; local verification on 2026-04-08 surfaced HTTP 403 with the available key
Rejected: Single generic health skill | weaker safety boundaries and less explicit user routing
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep red-flag escalation and interview-first wording intact unless official clinical scope is expanded deliberately
Tested: python3 scripts/mfds_drug_safety.py --help; python3 scripts/mfds_drug_safety.py interview --question '타이레놀이랑 판콜 같이 먹어도 되나요?' --symptoms '두드러기와 어지러움'; python3 scripts/mfds_food_safety.py --help; python3 scripts/mfds_food_safety.py interview --question '이 김밥 먹어도 되나요?' --symptoms '복통과 설사'; python3 scripts/mfds_food_safety.py search --query '대장균' --sample-recalls --limit 1; PYTHONPATH=.:scripts python3 -m unittest scripts.test_mfds_drug_safety scripts.test_mfds_food_safety; node --test scripts/skill-docs.test.js; npm run ci
Not-tested: Successful authenticated MFDS live data.go.kr lookup path with a fully approved service key
2026-04-08 22:23:14 +09:00
Jeffrey (Dongkyu) Kim
bb79fa5813 Enable session-bound Hi-Pass receipt workflows without promising unattended login
Issue #79 was approved specifically as a logged-in-session-only automation surface, so the change adds a new hipass-receipt skill/package that focuses on query building, usage-history parsing, receipt payload assembly, and session-expiry detection. The docs now make manual login, session expiry, and official flow limits explicit while wiring the new skill into install/setup/source surfaces.

Constraint: Hi-Pass uses short-lived server sessions and multi-step login flows that are not safe to reimplement as raw HTTP automation
Rejected: Unattended cookie/session reuse bot | server session expires and redirects back to login
Rejected: Docs-only skill with no helper package | would not provide runnable, testable behavior for payload parsing and session detection
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep this feature scoped to logged-in browser sessions; do not promise credential automation or long-lived session recovery without new evidence from the official site
Tested: npm run ci
Tested: CLI fixture-demo and chrome-command smoke runs
Tested: Live inspectHipassPage smoke against /comm/lginpg.do and /usepculr/InitUsePculrTabSearch.do
Not-tested: Authenticated live receipt popup opening with a real Hi-Pass account/session
2026-04-07 19:44:43 +09:00
Jeffrey (Dongkyu) Kim
b8ea339446
Feature/#58 (#70)
* Add an official KIPRIS patent-search skill for Korean IP lookups

Issue #58 adds a bundled stdlib Python helper plus install/setup/docs coverage
for KIPRIS Plus keyword search and application-number detail lookup. The
implementation keeps auth explicit via KIPRIS_PLUS_API_KEY -> ServiceKey and
locks the repo contract with doc/install and regression tests.

Constraint: KIPRIS Plus requires a per-user ServiceKey and no valid key was available for live success-path runs
Constraint: No new dependencies allowed for bundled skill helpers
Rejected: Add a new npm/python workspace | docs+helper pattern already fits repo and keeps install payload lighter
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep the helper aligned with official KIPRIS Plus XML fields and ServiceKey naming before widening the skill surface
Tested: python3 scripts/patent_search.py --help; python3 scripts/patent_search.py --query '배터리' --service-key dummy; python3 scripts/patent_search.py --application-number 1020240001234 --service-key dummy; PYTHONPATH=.:scripts python3 -m unittest scripts.test_patent_search; node --test scripts/skill-docs.test.js; npm run lint; npm run typecheck; npm test
Not-tested: Successful live KIPRIS search with a valid production ServiceKey
Related: #58

* Accept copied KIPRIS portal keys without request corruption

KIPRIS Plus users commonly paste the percent-encoded ServiceKey shown by the
portal. The helper now normalizes that key once before query serialization,
adds regression coverage for explicit and env-driven inputs, and clarifies the
documentation so copied portal keys remain valid instead of being double-
encoded on the wire.

Constraint: KIPRIS Plus still expects the standard ServiceKey query parameter contract
Rejected: Preserve raw percent signs during urlencode only for ServiceKey | more brittle than normalizing once at the boundary
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep ServiceKey normalization at the input boundary so future request-building changes do not reintroduce double-encoding
Tested: python3 scripts/patent_search.py --help; python3 scripts/patent_search.py --query '배터리' --service-key dummy; python3 scripts/patent_search.py --application-number 1020240001234 --service-key dummy; PYTHONPATH=.:scripts python3 -m unittest scripts.test_patent_search; node --test scripts/skill-docs.test.js; npm run lint; npm run typecheck; npm test
Not-tested: Live KIPRIS Plus lookup with a real KIPRIS_PLUS_API_KEY

* Record fresh verification for the approved KIPRIS key fix

The approved ServiceKey normalization fix is already present on feature/#58, so no further code edits were necessary. This empty follow-up commit records the requested rerun verification and keeps PR #70 moving without reopening a settled implementation path.

Constraint: Existing branch head already contains the approved code and docs fix
Rejected: Invent an extra code/doc change just to produce a non-empty diff | unnecessary risk after approval
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Do not change ServiceKey handling again without reproducing the percent-encoded portal-key path
Tested: python3 scripts/patent_search.py --help; python3 scripts/patent_search.py --query '배터리' --service-key dummy; python3 scripts/patent_search.py --application-number 1020240001234 --service-key dummy; PYTHONPATH=.:scripts python3 -m unittest scripts.test_patent_search; node --test scripts/skill-docs.test.js; npm run lint; npm run typecheck; npm test
Not-tested: Live KIPRIS request with a real KIPRIS_PLUS_API_KEY

* Record fresh Issue #58 verification without reopening the approved fix

The approved KIPRIS ServiceKey normalization change was already present on
feature/#58, so this follow-up records a fresh verification point for the
existing implementation instead of reopening the code path.

Constraint: User requested commit/push + PR follow-up on the existing issue branch
Rejected: Reopen the already-approved implementation | no new blocker or code defect remained
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If this helper changes again, preserve support for percent-encoded portal keys and keep the URL serialization regression coverage intact
Tested: patent helper smoke commands, patent/doc regression tests, lint, typecheck, full npm test suite, encoded-key reproduction, architect review
Not-tested: Live KIPRIS success path with a real KIPRIS_PLUS_API_KEY

* fix: decode percent-encoded ServiceKey in build_search_params and build_detail_params

The low-level helper functions still double-encoded percent-encoded
KIPRIS portal keys when callers bypassed resolve_service_key(). Apply
unquote() at the param-builder boundary so copied portal keys work
regardless of call path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: trigger GitHub merge-status recalculation

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 18:30:03 +09:00
Jeffrey (Dongkyu) Kim
d5034daaaf
Feature/#57 (#69)
* Hide KMA forecast keys behind the public proxy

Add a Korea weather skill plus a new k-skill-proxy route for the
KMA short-term forecast API. The route accepts grid coordinates or
lat/lon, defaults to the latest safe base time, and keeps the user
workflow keyless while the proxy owns the upstream credential.

Constraint: KMA short-term forecast requires a service key and 5km grid parameters
Constraint: Must keep the client flow dependency-free and free of user API issuance
Rejected: Direct client-side KMA calls | would force end users to issue and store their own keys
Rejected: Add a third-party geocoder dependency | unnecessary for v1 when lat/lon-to-grid conversion is enough
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep future KMA integrations on explicit allowlisted proxy routes and avoid documenting upstream keys for clients
Tested: npm run ci; local HTTP smoke test for /v1/korea-weather/forecast with mocked upstream fetch; npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json
Not-tested: Live KMA upstream call with a production service key

* Reject invalid weather coordinates before proxying

The korea-weather forecast route already normalized valid lat/lon requests, but
out-of-range inputs could still project to NaN grid values and consume upstream
quota. This change rejects invalid latitude/longitude pairs at the boundary and
locks the behavior with a regression that proves invalid coordinates never
reach fetch.

Constraint: Public proxy endpoints must reject malformed caller input before upstream calls
Rejected: Allow upstream KMA failures to handle invalid coordinates | wastes quota and returns opaque errors
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep coordinate validation local to query normalization so cache keys and upstream URLs only see finite grid values
Tested: node --test packages/k-skill-proxy/test/server.test.js; local app.inject smoke for /v1/korea-weather/forecast with mocked fetch; npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json; npm run ci
Not-tested: Live KMA upstream behavior for invalid coordinates (intentionally blocked before proxying)

* Protect proxied public-data API keys with HTTPS transport

The new korea-weather route already hid the KMA service key behind the proxy, but
it was still forwarding that key over plaintext HTTP. Switching the shared
data.go.kr proxy base URL to HTTPS keeps the existing request contract intact
while closing the transport exposure. Regression coverage now locks the weather
route and direct KMA proxy helper to HTTPS so the downgrade does not regress.

Constraint: The follow-up had to stay minimal on the existing PR branch
Rejected: Add a KMA-only base URL constant | unnecessary divergence from the shared data.go.kr transport setting
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep proxied upstreams on HTTPS whenever the provider supports it, especially when operator-managed keys are injected server-side
Tested: node --test packages/k-skill-proxy/test/server.test.js; local buildServer().inject smoke with mocked fetch; npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json; npm run ci
Not-tested: Live network call to KMA upstream with a real service key

* Merge dev into main: new skills & proxy enhancements (#72)

* Remove client-side Seoul subway key setup

Route Seoul subway arrival lookups through k-skill-proxy so the
hosted proxy owns the Seoul Open Data upstream key and end users
only need the proxy base URL. Add proxy route coverage, update
skill/docs guidance, and align setup materials with the hosted
proxy flow used for fine dust.

Constraint: Must keep the proxy public, read-only, and dependency-free
Constraint: Must satisfy TDD-first verification and ship on feature/#35 targeting dev
Rejected: Add a separate client helper package | unnecessary extra layer for a single proxy route
Rejected: Keep SEOUL_OPEN_API_KEY as an end-user requirement | defeats the issue goal
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep the Seoul subway proxy surface limited to station-arrival passthrough unless tests/docs expand the contract
Tested: npm run ci; local proxy runtime on 127.0.0.1:4120 for /health and /v1/seoul-subway/arrival on 2026-03-31 with an invalid upstream key
Not-tested: Live success response with a valid Seoul Open API key
Related: #35

* Prevent broken Seoul subway proxy defaults before hosted rollout

The Seoul subway proxy endpoint code is present locally, but the hosted public route is not live yet. This change turns the user-facing subway docs back into an explicit proxy configuration flow, replaces the misleading hosted default in setup examples, and keeps subway proxy examples on self-host/local URLs until rollout is verified.

Constraint: Hosted k-skill-proxy.nomadamas.org/v1/seoul-subway/arrival is not live yet
Rejected: Keep the hosted Seoul subway URL as the default path | would send default users to a 404 route
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Do not restore a hosted Seoul subway default until the public proxy route is deployed and smoke-verified
Tested: node --test scripts/skill-docs.test.js; npm run ci; local proxy smoke on 127.0.0.1:4120 with stubbed Seoul upstream (GET /health, GET /v1/seoul-subway/arrival?stationName=강남)
Not-tested: Live hosted proxy smoke after deployment

* Reduce Seoul subway proxy upstream pressure with request caching

The public subway arrival route already normalized caller input but still re-fetched the Seoul upstream for every identical poll. This change adds a short-TTL cache keyed from the normalized subway query, annotates JSON responses with cache metadata, and locks the repeated-read collapse with a regression that proves alias/default normalization still reuses the cached result.

Constraint: The endpoint must stay public/no-auth while protecting a shared server-side SEOUL_OPEN_API_KEY from unnecessary repeated upstream hits
Rejected: Add a new shared cache abstraction for proxy metadata | unnecessary for this narrow fix and would enlarge the diff
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep subway cache keys tied to normalizeSeoulSubwayQuery output so alias/default query forms continue collapsing to one upstream request
Tested: node --test packages/k-skill-proxy/test/server.test.js
Tested: npm run ci
Tested: Local proxy runtime on 127.0.0.1:4120 with SEOUL_OPEN_API_KEY=test-seoul-key and stubbed fetch for /health plus repeated /v1/seoul-subway/arrival requests
Not-tested: Live hosted proxy rollout state

* Document OpenClaw support in the public compatibility list

The approved scope for issue #29 was narrowed to README support messaging,
so this change adds OpenClaw/ClawHub to the supported-client line and locks
that wording with a regression test in the docs suite.

Constraint: Issue #29 was approved as a README-only compatibility/docs change
Rejected: Broader install-doc updates | out of approved scope for this issue
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep OpenClaw support wording aligned with the supported-client README line and its docs regression test
Tested: Focused Node docs regression, npm run lint, npm run typecheck, npm run build, npm test
Not-tested: Live OpenClaw or ClawHub install flow (issue scope was documentation-only)

* Protect README client-support claims from ClawHub regressions

The README already advertises OpenClaw/ClawHub, but the docs
regression only matched OpenClaw. Tighten the assertion to the
exact supported-client fragment so a future edit cannot silently
remove ClawHub while keeping the issue verification command stable.

Constraint: PR #39 already publishes a verification command keyed to the current test name
Rejected: Rename the test to mention ClawHub explicitly | would drift from the published verification command
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep this regression synchronized with the README supported-client line whenever that copy changes
Tested: node --test scripts/skill-docs.test.js --test-name-pattern 'README advertises OpenClaw among the supported coding agents'
Tested: npm run lint
Tested: npm run typecheck
Tested: npm run build
Tested: npm test
Tested: lsp diagnostics for scripts/skill-docs.test.js (0 errors)
Not-tested: N/A

* Make Coupang shopper research usable without pretending scraping is stable

Coupang blocks unattended shopper queries in this environment, so the new package focuses on the durable pieces we can ship honestly: official URL builders, browser-captured HTML parsers, and explicit automation probes. The docs and skill now explain the seller-API limitation, the verified anti-bot behavior, and the browser-capture fallback expected by callers.

Constraint: No general shopper Open API surfaced in Coupang's official developer docs

Constraint: Headless/direct retrieval is anti-bot blocked in verified local probes

Rejected: Bundle a scraping bypass or hidden browser dependency | violates repo policy and would over-claim reliability

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Keep probe/docs behavior aligned with fresh live verification before claiming unattended Coupang access works

Tested: npm run ci; live probeAutomation(query=생수) with direct fetch + Playwright-core browserFetchHtml; LSP diagnostics on changed JS/test files

Not-tested: Headed/manual browser sessions with a human-authenticated Coupang context

* Keep the Coupang workspace installable and its entrypoint honest

Review follow-up found two contract gaps in the first issue #36 rollout: fresh installs were missing the new workspace link in package-lock, and the package README documented parser helpers that were not exported from the package entrypoint. Refreshing the lockfile and re-exporting the parsers keeps npm ci and consumer imports aligned with the published API.

Constraint: npm ci must succeed from a clean checkout
Rejected: Narrow the README API list to only client helpers | would hide useful parsers that the package already ships and tests
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When adding a new workspace, refresh package-lock and verify the package entrypoint matches README public API claims
Tested: npm run ci; workspace coupang-product-search tests; LSP diagnostics on coupang-product-search JS/test files
Not-tested: published npm install from registry (local pack dry-run only)

* Keep Coupang anti-bot docs honest as probe results drift

A same-day PR rerun showed the published mobile probe snapshot was already stale, so the follow-up locks the 403/access-denied mobile path with regression coverage and softens the docs/skill contract to describe blocked outcome classes instead of one frozen signature. The published guidance now also explains that browser results only appear when browserFetchHtml is injected, matching what a clean checkout can actually reproduce.

Constraint: Coupang anti-bot responses vary by edge/challenge between reruns on the same day
Rejected: Freeze one exact mobile probe snapshot | same-day reruns already diverged
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Refresh Coupang anti-bot docs only with same-day live probe evidence, and prefer blocked outcome classes over a single exact signature when reruns disagree
Tested: npm run lint; npm run typecheck; npm test; npm run ci; live probeAutomation("생수") with direct fetch + Playwright-core browser fetch
Not-tested: Non-Chrome Playwright-core executables

* Keep the Coupang skill honest about clean-checkout browser probes

The approved follow-up already documented that clean-checkout probeAutomation runs leave browser unset unless a browser fetcher is injected, but the skill text itself had not made that null contract explicit. This commit adds a regression test that locks the browser-null wording across the published docs surfaces and updates the skill so the stated behavior matches the package implementation and clean-checkout reality.

Constraint: probeAutomation() only populates browser when browserFetchHtml is supplied by the caller
Rejected: Leave the skill wording implicit and rely on README examples alone | the skill could drift away from the shipped package contract again
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the README, feature doc, and skill aligned whenever the probeAutomation browser contract changes
Tested: node --test packages/coupang-product-search/test/index.test.js; npm run lint; npm run typecheck; npm test; npm run ci; live probeAutomation("생수") with direct fetch + Playwright-core browser fetch; codex exec review --uncommitted
Not-tested: Alternative browser engines beyond local Google Chrome for the manual browserFetchHtml probe

* Keep Coupang browser probe docs aligned with manual verification paths

The approved PR #40 follow-up still had one wording gap: the skill said when browser results appear, but it did not explicitly say those populated results come from an injected manual/external browserFetchHtml path. This change locks that contract with a failing regression first, then updates the skill text to match the already-shipped README/feature-doc guidance and runtime behavior.

Constraint: clean-checkout probeAutomation() must keep browser null unless browserFetchHtml is supplied
Rejected: change runtime browser probe behavior | approved follow-up was docs/test only and runtime contract is already correct
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: keep Coupang probe docs aligned with the shipped browserFetchHtml injection contract; do not imply built-in browser probing in clean checkouts
Tested: node --test packages/coupang-product-search/test/index.test.js; npm run lint; npm run typecheck; npm test; npm run ci; live probeAutomation("생수") with direct fetch + Playwright-core browser fetch; lsp diagnostics on changed files; architect review approved
Not-tested: alternate browser engines beyond local Google Chrome + playwright-core manual runner

* Route Korean law lookups through korean-law-mcp

Add a documentation-first korean-law-search skill and lock the repo docs around the rule that Korean law queries must go through korean-law-mcp rather than a new in-repo package.

The change updates install/setup/security guidance, publishes the new feature doc, and adds regression tests so future edits keep the LAW_OC + korean-law-mcp contract intact.

Constraint: Issue #41 requires korean-law-mcp for every Korean law lookup
Constraint: Must not add a new npm or python package in this repository
Rejected: Add a repo-local law package | violates the no-new-package requirement and duplicates upstream MCP work
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep Korean law lookup guidance pinned to korean-law-mcp unless issue requirements explicitly change
Tested: node --test scripts/skill-docs.test.js
Tested: npm install -g korean-law-mcp && korean-law list && korean-law help search_law
Tested: npm run ci
Tested: npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json
Not-tested: live search_law/get_law_text against a real LAW_OC credential

* Clarify Korean law setup modes to avoid credential confusion

A review found the new korean-law-search docs treated LAW_OC as an unconditional prerequisite even though the upstream remote MCP endpoint is configured separately from the local CLI/server path. This update makes the docs and regression tests mode-specific: local CLI/MCP uses LAW_OC, while the remote endpoint stays a korean-law-mcp-only url fallback without a user-supplied credential.

Constraint: Upstream korean-law-mcp uses LAW_OC on the local CLI/server path while the documented remote MCP endpoint is configured with url only
Rejected: Keep LAW_OC mandatory for every korean-law-mcp mode | contradicts upstream docs and reviewer evidence
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep README/setup/skill docs and regression tests aligned on the local-vs-remote korean-law-mcp contract
Tested: node --test scripts/skill-docs.test.js; npm install -g korean-law-mcp && korean-law list && korean-law help search_law; npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json; npm run ci; lsp_diagnostics scripts/skill-docs.test.js
Not-tested: Live remote MCP endpoint connection against https://korean-law-mcp.fly.dev/mcp

* Record issue #41 follow-up after approved verification

The approved korean-law-search change was already present on feature/#41, so this follow-up records a fresh verification pass and updates the PR without introducing unnecessary code churn.

Constraint: Existing branch already contained the approved implementation
Rejected: Touch repo files without need | would create noise without improving behavior
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the korean-law-mcp-only + mode-specific LAW_OC contract aligned with upstream docs before changing these surfaces again
Tested: node --test scripts/skill-docs.test.js; npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json; npm install -g korean-law-mcp && korean-law list && korean-law help search_law; npm run ci
Not-tested: Live korean-law queries that require a real LAW_OC or remote endpoint session

* Keep the Korean law feature diff merge-ready

Verification uncovered trailing whitespace in the new korean-law feature guide when checking the branch diff. I added a regression to the skill docs suite and removed the whitespace so the approved documentation contract stays clean and reviewable.

Constraint: Preserve the existing korean-law-mcp + mode-specific LAW_OC contract without widening scope
Rejected: Leave the whitespace issue as-is | git diff --check stayed dirty on the branch
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep docs/features/korean-law-search.md free of trailing whitespace so diff hygiene stays enforced by the regression
Tested: node --test scripts/skill-docs.test.js; npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json; npm install -g korean-law-mcp && korean-law list && korean-law help search_law; npm run ci; git diff --check
Not-tested: Live credentialed LAW_OC search execution against the upstream API

* Keep Korean law skill guidance aligned with supported lookups

The approved issue #41 feature already worked, but the shipped skill text still under-described ordinance and interpretation lookups compared with the documented capability set. This follow-up tightens the skill copy and locks that contract with a doc regression so the branch stays merge-ready without changing the underlying korean-law-mcp routing rules.

Constraint: Must preserve the existing korean-law-mcp-only and mode-specific LAW_OC setup contract
Rejected: Leave the skill wording as-is | drift from the documented lookup surface would remain
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the skill examples and doc regression aligned whenever supported korean-law-mcp search surfaces change
Tested: node --test scripts/skill-docs.test.js
Not-tested: live LAW_OC-backed upstream API queries

* Keep Korean law completion guidance in sync with enforced lookups

The previous follow-up aligned the main skill examples, but the done-criteria text still left interpretation and ordinance routing implicit. This commit makes the completion checklist explicit and extends the doc regression so future edits cannot silently drop those lookup paths.

Constraint: Must stay within the existing issue #41 korean-law-mcp-only contract
Rejected: Leave the done checklist implicit | reviewers and future edits could drift from the enforced lookup set
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When the supported Korean-law lookup set changes, update the done checklist and regression together
Tested: node --test scripts/skill-docs.test.js
Not-tested: full CI before commit

* Enable repeatable used-car price lookups from a rental-company source

Issue #46 required surveying major Korean rental companies before implementation and then choosing the easiest stable provider. SK렌터카 다이렉트 exposes 타고BUY inventory in public Next.js page data, so the feature stays dependency-free while still supporting live repeated lookups and documented provider rationale.

Constraint: Must compare major Korean rental companies before implementation
Constraint: Must verify 10+ live lookups against a real provider surface
Rejected: 롯데오토옥션 as v1 provider | public list contract was unstable and legacy .do flows returned inconsistent or 404 pages
Rejected: 레드캡렌터카 as v1 provider | no public used-car inventory or API surface was found
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep the v1 provider read-only and inventory-snapshot-based unless a stable documented public API is confirmed
Tested: npm run ci
Tested: Live 10-query run against https://www.skdirect.co.kr/tb at 2026-04-02T07:22:46Z
Tested: LSP diagnostics on affected files
Not-tested: Seller-specific detail drilldowns or non-SK providers
Related: #46

* Keep used-car-price-search releasable after merge

Review feedback found that the new used-car workspace would not ship because it lacked a changeset, and the fallback install docs still omitted the runtime package. This follow-up adds regression coverage first, then restores both release and install-path coverage with the smallest possible diff.

Constraint: New publishable workspaces must be wired through Changesets to reach npm release automation
Constraint: Fallback install docs must list runtime packages users need when skill files are present but global packages are missing
Rejected: Fix only the changeset gap | would leave the documented fallback install path incomplete
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep used-car-price-search in both the fallback global install example and a Changesets entry whenever release wiring changes
Tested: node --test scripts/skill-docs.test.js; npx changeset status; live 10-query used-car run against SK direct at 2026-04-02T07:38:44.949Z; npm run ci; LSP diagnostics on used-car package files and scripts/skill-docs.test.js; architect verification
Not-tested: No additional live provider permutations beyond the verified 10-query smoke run

* Keep used-car verification docs resilient to live inventory churn

A fresh rerun showed the SK direct inventory total continues to move during the day, so the feature doc now records the verified smoke-run timestamp without freezing a brittle exact count. The regression suite was updated first so the docs stay variability-aware and diff-clean in future follow-ups.

Constraint: Live SK direct inventory totals change over time even when the parsing contract stays stable
Rejected: Keep documenting a fixed total from one smoke run | it immediately drifted and made the docs stale
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the used-car live verification note timestamped and variability-aware instead of pinning an exact inventory total
Tested: node --test scripts/skill-docs.test.js; git diff --check; npm run ci; npx changeset status; live 10-query run against https://www.skdirect.co.kr/tb at 2026-04-02T07:59:41.391Z; LSP diagnostics on scripts/skill-docs.test.js; architect verification
Not-tested: No additional content changes outside the used-car feature doc

* Keep used-car query summaries honest when results are limited

The review found that query-level stats were being computed from the
post-limit slice, so common searches like 아반떼 under-reported both
match counts and price ranges. This change locks the regression first,
then computes the full filtered set before slicing only the returned
items.

Constraint: PR #48 must preserve the existing API shape while fixing the review-blocking stats bug
Rejected: Expanding the response with separate limited/full summary fields | unnecessary API churn for a targeted bug fix
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Query-level summary and matchedCount must stay derived from the full filtered set, not the display limit slice
Tested: npm test --workspace used-car-price-search; npm run ci; git diff --check; npx changeset status; live SK direct smoke run on 2026-04-02T08:23:59Z; LSP diagnostics on used-car-price-search source and test files; architect verification APPROVED
Not-tested: limit=0 semantics remain unchanged and still coerce to the default limit
Related: PR #48

* Keep korean-law-search available during upstream outages (#45)

Issue #44 adds Beopmang as the documented fallback when the primary korean-law-mcp path is unavailable, and locks the new routing into the doc regression suite so future edits do not silently revert the policy.

Constraint: Existing guidance must still prefer korean-law-mcp and keep LAW_OC scoped to the local CLI/MCP path
Rejected: Add a repo-local Beopmang client package | issue only requires fallback registration, not a new implementation surface
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the primary-first rule intact; Beopmang is an outage fallback, not the default path
Tested: node --test scripts/skill-docs.test.js; npm run ci; korean-law list; python3 live Beopmang search smoke for 관세법
Not-tested: Live Beopmang MCP handshake from a GUI MCP client

* Replace coupang scraping package with coupang-mcp server integration

Drop the browser-based scraping package (packages/coupang-product-search)
and switch to the uju777/coupang-mcp MCP server for all Coupang product
searches. This removes the anti-bot workaround complexity and provides
8 ready-to-use tools via MCP Streamable HTTP with no API key required.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add disclaimer to used-car-price-search README

Clarify that the package queries SK렌터카 타고BUY public data with
no affiliation or sponsorship, and that ad/partnership inquiries
are welcome.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Refactor used-car-price-search into provider-based architecture

SK 타고BUY 전용 로직을 src/providers/sk-tagobuy.js로 분리하고,
공급자를 수평 확장할 수 있는 registry 구조로 전환한다.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Ship LCK analytics inside k-skill's managed release flow

Adapt jerjangmin's upstream lck-analytics skill/package into a new
workspace and skill pack, wire docs/install/release surfaces, and add
regression fixtures/tests plus script smoke coverage so the feature is
verifiable before publish.

Constraint: Upstream package is not published to npm yet
Constraint: Must preserve attribution to original source and author in shipped docs
Rejected: Keep the upstream lck-results install wording in k-skill | conflicts with repo workspace/package naming
Rejected: Ship only the npm package without the local skill scripts | issue explicitly requested the skill as well
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep Changesets as the only version-bump path for lck-analytics; do not hand-edit versions for release
Tested: node --test packages/lck-analytics/test/index.test.js scripts/skill-docs.test.js
Tested: npm run lint --workspace lck-analytics
Tested: npm test --workspace lck-analytics
Tested: live getLckSummary('2026-04-01', { team: '한화', includeStandings: true })
Tested: node lck-analytics/scripts/sync-oracle.js --csv lck-analytics/samples/oracle-lck-sample.csv --cache .tmp/lck-cache && node lck-analytics/scripts/build-match-report.js --date 2026-04-01 --team 한화 --cache .tmp/lck-cache && node lck-analytics/scripts/analyze-live-game.js --game game-1 --window packages/lck-analytics/test/fixtures/live-window-game-1.json --details packages/lck-analytics/test/fixtures/live-details-game-1.json --cache .tmp/lck-cache
Tested: npm run ci
Tested: npx tsc --noEmit --project /Users/jeffrey/Projects/k-skill/tsconfig.json
Not-tested: Riot live feed behavior for arbitrary future game ids outside the fixture-backed smoke path

* Enable policy-aware Korean spell checking from the official Nara surface

Add a skill guide and Python helper that use the approved old_speller HTML flow, chunk long text conservatively, and report original/suggestion/reason deltas. The docs also record the public-site limits, Cloudflare behavior, and non-commercial usage policy so agents do not overreach the free surface.

Constraint: Public site is HTML-only and may return 403 to non-browser clients
Constraint: Must not add new dependencies or high-volume crawling behavior
Rejected: Node fetch client | Cloudflare returned 403 in this environment
Rejected: Paid API integration | no public contract or credentials were available for this task
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep usage low-rate and non-commercial unless supplier-approved API terms are added
Tested: npm run lint
Tested: npm run typecheck
Tested: npm test
Tested: npm run build
Tested: python3 scripts/korean_spell_check.py --text '아버지가방에들어가신다.' --format json
Tested: python3 scripts/korean_spell_check.py --text $'아버지가방에들어가신다.\n\n아버지가방에들어가신다.' --max-chars 15 --format json
Not-tested: Paid API/order flow
Not-tested: High-volume commercial workloads
Not-tested: Non-UTF-8 file inputs

* Preserve korean spell-check layout in corrected output

The Nara payload can collapse paragraph separators into normalized page text, so the helper now maps corrections back onto the original chunk before rebuilding corrected_text. The CLI also rejects non-positive --max-chars values, and regression tests cover both the layout-preservation path and invalid argument handling.

Constraint: Nara result pages can normalize blank lines and sentence spacing before exposing errInfo offsets
Rejected: Narrow docs away from file/Markdown proofreading | preserving original chunk separators keeps the documented workflow intact
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep multiline separator preservation tied to the original chunk whenever a suggestion only changes whitespace across collapsed boundaries
Tested: python3 -m unittest scripts.test_korean_spell_check; npm run lint; npm run typecheck; npm test; npm run build; python3 scripts/korean_spell_check.py --text '아버지가방에들어가신다.' --format json; python3 scripts/korean_spell_check.py --text $'아버지가방에들어가신다.\n\n아버지가방에들어가신다.' --max-chars 15 --format json; python3 scripts/korean_spell_check.py --text $'아버지가방에들어가신다.\n\n왠지 않되요.' --format json; python3 scripts/korean_spell_check.py --text 테스트 --max-chars 0 --format json
Not-tested: Live multi-page Nara payloads with separator-sensitive corrections across multiple returned pages

* Preserve file-proofreading layout in Korean spell check output

The spell-check helper now keeps exact blank-line runs and paragraph
indentation when chunking and reassembling file-style input, while still
allowing the official service's spacing corrections to flow through.
Regression coverage now locks the collapsed-layout, triple-blank-line,
and cross-boundary spacing cases that triggered the PR review.

Constraint: Official Nara/PNU payloads can collapse layout and sometimes merge corrections across preserved paragraph boundaries
Rejected: Narrow docs away from file-level proofreading | the existing feature scope explicitly supports file and Markdown checks
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Preserve exact layout tokens only at original newline boundaries; do not reintroduce global strip/join normalization without real file-mode verification
Tested: npm run lint; npm run typecheck; npm test; npm run build; python3 scripts/korean_spell_check.py --text '아버지가방에들어가신다.' --format json; python3 scripts/korean_spell_check.py --text $'아버지가방에들어가신다.\n\n아버지가방에들어가신다.' --max-chars 15 --format json; python3 scripts/korean_spell_check.py --file <tmpfile> --format json; python3 scripts/korean_spell_check.py --text 테스트 --max-chars 0 --format json
Not-tested: Live upstream behavior for extremely long leading/trailing-whitespace-only files
Related: PR #60

* Keep layout-preserving chunk splits from tripping on separator-boundary fixes

The follow-up layout preservation pass renamed the working unit variable, but one separator-length guard still referenced the old paragraph name. This commit finishes the refactor so exact-boundary paragraph chunks keep the preserved-separator logic reachable and the new regression coverage stays green.

Constraint: Must preserve the existing feature/#47 branch and PR #60 flow while fixing the approved review follow-up
Rejected: Revert the layout-preserving chunking refactor | would discard the verified file-layout fix and its regressions
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep chunk reassembly lossless; new chunking changes should continue to round-trip original separators byte-for-byte
Tested: npm run lint; npm run typecheck; npm test; npm run build; python3 scripts/korean_spell_check.py --text '아버지가방에들어가신다.' --format json; python3 scripts/korean_spell_check.py --text $'아버지가방에들어가신다.\n\n아버지가방에들어가신다.' --max-chars 15 --format json; python3 scripts/korean_spell_check.py --file <tempfile-with-triple-blank-lines> --format json; python3 scripts/korean_spell_check.py --text 테스트 --max-chars 0 --format json (expected argument error)
Not-tested: Live multi-page service responses beyond the local smoke cases

* Preserve spell-check chunk separators when units overflow

The file-layout follow-up already preserved blank runs and indentation,
but the overlong-unit path still checked the wrong variable when
extracting a trailing separator. That could strand separators in
a standalone chunk and break exact reassembly for tight max-char
limits.

This commit fixes the separator extraction guard and locks the
behavior with a regression that proves chunk concatenation still
matches the original text when an overlong paragraph is followed
by a blank-line separator.

Constraint: File-mode reconstruction must preserve exact layout while chunking long input
Rejected: Broader chunking rewrite | existing structure only needed the overflow guard corrected
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep split_text_into_chunks chunk concatenation identical to the original input for layout-sensitive file checks
Tested: npm run lint; npm run typecheck; npm test; npm run build; python3 scripts/korean_spell_check.py --text '아버지가방에들어가신다.' --format json; python3 scripts/korean_spell_check.py --text $'아버지가방에들어가신다.\n\n아버지가방에들어가신다.' --max-chars 15 --format json; python3 scripts/korean_spell_check.py --text 테스트 --max-chars 0 --format json; manual --file smoke with triple blank lines and indentation
Not-tested: Live-service failure modes such as Cloudflare/browser challenges

* Prevent clean spell-check chunks from crashing mixed file runs

The Nara/PNU surface can return a plain 'no issues found' HTML page
without the embedded result payload when a chunk is already clean.
Chunked file and markdown runs could hit that response on earlier
chunks, raise a ValueError, and never reach later chunks that still
needed corrections. Treat the no-issues page as an empty result set
and lock the behavior with narrow regression coverage.

Constraint: Upstream no-issue responses omit the JavaScript payload entirely and can split the status message across HTML whitespace
Rejected: Fabricate a synthetic result page | empty-page handling already preserves the original clean chunk
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep empty-result detection aligned with the upstream no-issues message unless the service publishes a structured empty payload contract
Tested: python3 -m unittest scripts.test_korean_spell_check
Tested: npm run lint
Tested: npm run typecheck
Tested: npm test
Tested: npm run build
Tested: python3 scripts/korean_spell_check.py --text '아버지가방에들어가신다.' --format json
Tested: python3 scripts/korean_spell_check.py --text $'아버지가방에들어가신다.\n\n아버지가방에들어가신다.' --max-chars 15 --format json
Tested: python3 scripts/korean_spell_check.py --text 테스트 --max-chars 0 --format json
Tested: python3 scripts/korean_spell_check.py --file <tmpfile> --format json
Tested: python3 scripts/korean_spell_check.py --file <tmpfile> --max-chars 18 --format json
Not-tested: Other upstream empty-result templates beyond the current no-issues HTML wording

* Make Joseon Sillok lookups reproducible from the official site

Add a joseon-sillok-search skill and a Python helper that scrape the
official Joseon Annals search/detail pages. The helper normalizes
king/year metadata, fetches detail excerpts, and locks the repository
docs plus regression coverage around the shipped workflow.

Constraint: v1 must stay on official public HTML surfaces only
Constraint: Must avoid adding new dependencies for a simple scraping helper
Constraint: Shell connectivity to sillok.history.go.kr became intermittent during final live reruns
Rejected: Ship a new npm workspace | repo skill/docs pattern is enough for v1
Rejected: Add BeautifulSoup or another parser dependency | unnecessary for the bounded HTML patterns
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: Keep year filtering Gregorian and derived from official regnal metadata unless the upstream site exposes a better structured contract
Tested: npm run ci
Tested: Earlier live POST/detail probes against search/searchResultList.do and /id/kda_12512030_002 during implementation
Tested: Live official article inspection for kda_12512030_002 via the public site
Not-tested: Final end-to-end CLI live run after the last refactor, because the shell hit transient TCP timeouts to sillok.history.go.kr
Related: #59

* Prevent sillok follow-up fixes from missing filtered results or weakening trust

This follow-up addresses the blocking PR review items on the Joseon Sillok helper. The search loop now derives total pages from the first live page size so king/year filtering can reach later pages, TLS verification stays enabled on both requests and urllib paths, detail parsing accepts the live classification brackets, and repo docs stop linking to missing Korean spell-check assets on this branch.

Constraint: Must preserve the existing joseon-sillok-search surface and avoid new dependencies
Rejected: Keep verify=False behind an implicit fallback | still weakens authenticity for the default path
Rejected: Infer pagination from the hardcoded 50-row default | misses valid later-page matches when the site serves smaller pages
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If the official site changes page size or pagination markup again, update the first-page pagination regression before altering search_sillok pagination math
Tested: PYTHONPATH=.:scripts python3 -m unittest scripts.test_sillok_search
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: python3 scripts/sillok_search.py --query '훈민정음' --king 세종 --year 1443 --limit 1 --timeout 20
Tested: python3 - <<'PY' ... fetch_detail_page(..., article_id='kda_12512030_002', timeout=20) ... PY
Not-tested: Successful live sillok.history.go.kr responses in this environment (POST and detail GET both timed out at 20s)
Related: PR #62

* Make joseon-sillok-search installs work outside the repo

The skill installer only ships the skill directory, so the sillok helper has to live inside that payload. This moves the authoritative helper into joseon-sillok-search/scripts/, keeps the repo-root script as a thin shim for tests and docs, and trims footer metadata from parsed article bodies so excerpts match the published examples.

Constraint: skills add exposes only the installed skill payload, not repo-root helpers

Rejected: Keep the helper only under scripts/ | installed skill commands fail after copy-only installs

Confidence: high

Scope-risk: narrow

Directive: Keep the repo-root sillok wrapper thin and update the bundled helper first when behavior changes

Tested: PYTHONPATH=.:scripts python3 -m unittest scripts.test_sillok_search

Tested: node --test scripts/skill-docs.test.js

Tested: temp installed-skill smoke run of python3 scripts/sillok_search.py --help plus footer-cleaning parse_detail_page check

Tested: npm run ci

Not-tested: live sillok.history.go.kr shell requests still hit connect timeouts in this environment

* Restore the sillok CLI's verified stdlib transport fallback

The helper already shipped a stdlib urllib opener that can reach the
official search endpoint in environments where requests/urllib3 aborts.
This change keeps that opener available even when requests imports
successfully and falls back to it on retryable requests transport
failures. Added regression coverage for opener availability and the
requests-to-urllib fallback so the default CLI path matches the live
verified behavior.

Constraint: Official sillok detail GETs can still time out transiently in this environment
Constraint: Keep TLS verification enabled and preserve the documented CLI entrypoints
Rejected: Force urllib for every request | keep the existing requests fast path when it succeeds
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Preserve the stdlib fallback tests whenever the transport layer changes
Tested: PYTHONPATH=.:scripts python3 -m unittest scripts.test_sillok_search
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: live forced-fallback probe against searchResultList.do with requests.post patched to OSError(22)
Not-tested: full live CLI completion through the detail GET in this environment

* Document the approved real-estate MCP skill without vendoring upstream

Issue #53 is intentionally doc-only, so this change adds the
real-estate-search skill, feature guide, setup/security notes,
and regression coverage around the upstream real-estate-mcp
integration instead of importing server code.

The new docs keep the original MCP link, cover Codex/Claude
registration, and spell out the self-host + Cloudflare Tunnel +
launchd path for environments where no fixed hosted endpoint is
available.

Constraint: Must use tae0y/real-estate-mcp without copying its source into this repository
Constraint: Must include the original MCP link and a stable self-host fallback when no hosted endpoint is available
Rejected: Vendor the upstream MCP source | issue explicitly requires skill docs only
Rejected: Assume a public hosted MCP endpoint exists | upstream docs did not publish one
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep this integration doc-only; do not add a workspace or vendored server without revisiting issue #53 constraints
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: upstream bootstrap smoke (`uv sync`, `uv run real-estate-mcp --help`, HTTP initialize on 127.0.0.1:8017)
Not-tested: live property data queries with a valid DATA_GO_KR_API_KEY

* Prevent misleading real-estate self-host instructions

Tighten the real-estate skill docs so the launchd fallback stays operational
and the Onbid bid-result tools are described with the same WIP caveat the
upstream project still publishes.

Constraint: Upstream Docker compose already uses restart: unless-stopped while `docker compose ... up -d` daemonizes immediately
Rejected: Keep a separate server LaunchAgent with RunAtLoad + KeepAlive | launchd would restart-loop on the exiting compose command
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Mirror upstream capability caveats in k-skill docs and do not wrap daemonized server commands in launchd KeepAlive jobs
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: uv sync
Tested: uv run real-estate-mcp --help
Tested: DATA_GO_KR_API_KEY=dummy uv run real-estate-mcp --transport http --host 127.0.0.1 --port 8017
Tested: curl initialize on http://127.0.0.1:8017/mcp returned protocolVersion 2024-11-05
Not-tested: Live 거래 조회 with a real DATA_GO_KR_API_KEY

* Keep install docs from reintroducing broken launchd guidance

The install guide had drifted from the real-estate skill and feature docs and still implied that macOS launchd should auto-run both the server and tunnel. This narrows the guidance back to tunnel-only launchd ownership and extends regression coverage so docs/install.md cannot silently reintroduce the server-side loop wording.

Constraint: Upstream docker compose already uses restart: unless-stopped
Constraint: Review-round-2 scope is limited to docs and regression coverage
Rejected: Leave docs/install.md under a generic launchd presence check | it missed the exact server/터널 regression
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep docs/install.md aligned with the detailed real-estate feature guide when self-host guidance changes
Tested: node --test scripts/skill-docs.test.js; npm run ci; fresh-clone upstream smoke with uv sync, uv run real-estate-mcp --help, and HTTP initialize on 127.0.0.1:8017/mcp
Not-tested: None

* Allow Han River water-level lookups without user API keys

The proxy now resolves HRFCO water-level stations via waterlevel/info and
fetches the latest 10-minute measurement via waterlevel/list, exposing a
public summary route plus a hosted skill/docs path.

Constraint: HRFCO requires a ServiceKey and station-code-based latest lookup
Rejected: Raw passthrough only | forces users to manage upstream details and misses the approved no-key UX
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep this route summary-only and public; expand rainfall/dam/bo/fldfct in separate issues
Tested: npm run ci; local server smoke test with HRFCO sample key against /v1/han-river/water-level; tsc diagnostics on packages/k-skill-proxy/src/server.js and src/hrfco.js
Not-tested: Hosted production proxy rollout

* Expose official nearby fuel prices for location-based gas station lookups

Add the first cheap-gas-nearby skill/package pair so nearby gas-price
queries can resolve a user-supplied location, translate it into Opinet's
KATEC search contract, and return the cheapest nearby stations with
address and facility detail. The docs and setup surfaces now advertise
the new skill and its Opinet API key requirement.

Constraint: Nearby fuel prices must come from the official KNOC Opinet API when available
Constraint: No new external dependencies were allowed for coordinate conversion or location resolution
Rejected: Map-only gas price scraping | official Opinet Open API exists and is the preferred source
Rejected: Require lat/lng input only | poorer UX than supporting landmark/station queries through anchor resolution
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep `OPINET_API_KEY` as the only supported official-price credential unless the repo adopts an Opinet proxy later
Tested: npm run ci; node --test packages/cheap-gas-nearby/test/index.test.js; offline fixture smoke via searchCheapGasStationsByLocationQuery('서울역', ...)
Not-tested: Live Opinet API call with a real `OPINET_API_KEY` (no non-placeholder key was configured locally)
Related: #54

* Explain Blue Ribbon premium gating instead of failing opaquely

Blue Ribbon's nearby endpoint now returns PREMIUM_REQUIRED for public
requests, so the package now upgrades that response into a stable domain
error and updates user-facing docs to describe the degraded nearby state.
Regression tests cover both location-query and coordinate-query entrypoints
while keeping the existing happy path intact.

Constraint: Must not attempt to bypass Blue Ribbon premium access controls
Constraint: Package releases must use Changesets metadata
Rejected: Silently return empty results on PREMIUM_REQUIRED | would hide the upstream contract change from callers
Rejected: Keep generic 403 error and docs unchanged | leaves the main failure mode opaque and misleading
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If Blue Ribbon reopens a public nearby surface later, update the docs and replace the premium_required remap only after fresh live verification
Tested: npm test --workspace blue-ribbon-nearby; npm run lint --workspace blue-ribbon-nearby; npm run ci; live node repro now returns premium_required metadata
Not-tested: Official premium-authenticated nearby flow, because no approved premium credentials are available

* Reduce duplicate premium-required test assertions

The implementation diff was already verified, so this follow-up keeps the
new regression coverage easier to read by sharing one assertion helper
instead of repeating the same predicate twice.

Constraint: Must preserve the verified PREMIUM_REQUIRED regression coverage exactly
Rejected: Leave duplicated inline predicates in both tests | repeats the same contract and adds noise to future edits
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep location-query and coordinate-query regressions aligned when the premium_required error contract changes
Tested: npm test --workspace blue-ribbon-nearby; npm run lint --workspace blue-ribbon-nearby; npm run ci
Not-tested: Additional live Blue Ribbon requests beyond the previously verified premium_required repro

* Document an Olive Young search skill around the upstream daiso CLI

Issue #61 asked for an Olive Young lookup workflow without vendoring the upstream daiso-mcp server into k-skill, so this change adds a docs-only skill, threads it through repository docs, and locks the guidance with regression assertions.

The new guidance prefers CLI-first verification (`npx daiso`) and a clone fallback (`git clone https://github.com/hmmhmmhm/daiso-mcp.git`) instead of requiring direct Claude Code MCP installation. The existing daiso-product-search skill remains untouched.

Constraint: Must mention the original https://github.com/hmmhmmhm/daiso-mcp repo
Constraint: Must avoid changing the existing daiso-product-search skill
Constraint: Must prefer upstream CLI/package usage over direct Claude Code MCP installation
Rejected: Vendor upstream Olive Young code into k-skill | contradicts the minimal-addition design request
Rejected: Make Claude Code MCP setup the default path | issue explicitly asked for CLI-first usage
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the Olive Young docs aligned with upstream `daiso` CLI behavior and note public endpoint instability when live verification shows it
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: 2026-04-05 live /tmp/daiso-mcp CLI checks for health, /api/oliveyoung/stores, /api/oliveyoung/products, /api/oliveyoung/inventory
Not-tested: Authenticated/private Olive Young flows or ordering/payment paths

* Keep Han River docs honest until hosted rollout lands

The local HRFCO proxy route already works, but the deployed public proxy still
lacks /v1/han-river/water-level as of 2026-04-05. This follow-up changes the
user-facing docs to require a self-hosted or deployment-verified proxy URL,
keeps the intended hosted path documented as rollout-pending, and locks that
caveat with a regression test.

Constraint: Hosted k-skill-proxy deployment still returns 404 for /v1/han-river/water-level on 2026-04-05
Rejected: Keep advertising the hosted route as the default live path | current deployment is not live yet
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Restore hosted-default wording only after the public proxy route and HRFCO configuration are verified live
Tested: node --test scripts/skill-docs.test.js; npm run ci; local mocked smoke via node packages/k-skill-proxy/src/server.js + GET /v1/han-river/water-level?stationName=한강대교
Not-tested: Live hosted k-skill-proxy behavior after deployment

* Keep cheap gas lookups from failing on recoverable Kakao and input issues

The lookup now walks ranked Kakao anchor candidates until one returns usable coordinates, and it rejects invalid limit inputs instead of silently collapsing non-empty results into an empty list. The regression suite now locks both review repros plus the null-coordinate normalization edge case that surfaced while implementing the fallback.

Constraint: Kakao place panels can be partially populated or return 404 for otherwise valid search candidates
Rejected: Default invalid limit/detailLimit values silently | still masks caller bugs and can look like no results nearby
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep anchor resolution tolerant of unusable Kakao panels before failing the whole lookup
Tested: node --test packages/cheap-gas-nearby/test/index.test.js; npm run ci; offline fixture smoke for searchCheapGasStationsByLocationQuery('서울역', ...)
Not-tested: Live Opinet/Kakao network path without a real OPINET_API_KEY

* Keep Olive Young install guidance aligned with live retry behavior

Issue #61's initial branch already shipped the olive-young-search skill/docs set, but the install guide did not have a regression lock for the public endpoint instability note captured during live verification. This follow-up adds that test first and updates the install quickstart so retry-or-clone fallback guidance stays in sync with the verified daiso CLI workflow.

Constraint: Must keep the follow-up scoped to the approved issue #61 docs behavior
Constraint: Public olive-young endpoint can intermittently return 5xx/503 during live verification
Rejected: Re-open the broader feature docs set | the existing branch already covered the main feature scope
Rejected: Leave the retry guidance untested in install docs | risk of future doc drift across surfaces
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If live olive-young verification changes again, update install docs and the regression together so retry/fallback guidance stays honest
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: cd /tmp/daiso-mcp && npx daiso health
Tested: cd /tmp/daiso-mcp && npx daiso get /api/oliveyoung/stores --keyword 명동 --limit 3 --json
Tested: cd /tmp/daiso-mcp && npx daiso get /api/oliveyoung/products --keyword 선크림 --size 3 --json
Tested: cd /tmp/daiso-mcp && npx daiso get /api/oliveyoung/inventory --keyword 선크림 --storeKeyword 명동 --size 2 --json
Not-tested: Authenticated Olive Young flows or sustained-rate retry behavior beyond the documented smoke checks

* Preserve ranked Kakao anchor fallbacks after panel failures

The resolver already retried later Kakao panels, but after the best panel failed it
walked the remaining candidates in raw HTML order. Centralizing the full
anchor ranking in parse.js keeps fallback iteration aligned with the
existing scoring rules and locks the review repro with a regression test
for 강남역 ordering.

Constraint: Kakao place panels can 404 or omit coordinates even when later ranked candidates are usable
Rejected: Re-rank only after a failed panel | duplicates scoring logic and drifts from selectAnchorCandidate
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep resolveAnchor fallback order tied to the shared anchor scoring logic rather than raw Kakao result order
Tested: node --test packages/cheap-gas-nearby/test/index.test.js; npm run ci; offline fixture smoke for searchCheapGasStationsByLocationQuery('서울역', ...); lsp diagnostics on affected files
Not-tested: Live Kakao/Opinet network calls with a non-placeholder OPINET_API_KEY

* Clarify that Blue Ribbon coordinate lookups fail the same way

The premium gate now affects both location-query and coordinate-entry nearby flows. Record that parity in the skill and docs so the live 2026-04-05 repro evidence stays aligned with the shipped public contract.

Constraint: /restaurants/map remains premium-gated for public requests as of 2026-04-05
Rejected: Add more code changes without a behavior gap | would add churn after the approved fix already landed
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the docs/examples aligned with live repro evidence whenever Blue Ribbon changes nearby access behavior
Tested: npm test --workspace blue-ribbon-nearby; npm run lint --workspace blue-ribbon-nearby; npm run ci; live node repro for location + coordinates premium_required contract
Not-tested: New upstream success-path live nearby payloads, because public access is still premium-gated

* Document a runnable Olive Young clone fallback

The follow-up review found that clone-local `npx daiso` commands do not run from a built `hmmhmmhm/daiso-mcp` checkout because the generated bin file is not executable. This updates the olive-young skill and docs to use the verified `node dist/bin.js ...` path for clone fallback, and locks that behavior with regression tests while keeping the public CLI-first path unchanged.\n\nConstraint: Upstream clone checkouts can fail with `Permission denied` when invoked through clone-local `npx daiso`\nConstraint: Keep the existing daiso-product-search skill untouched\nRejected: Leave install docs unchanged | PR body and docs would keep a broken clone fallback path\nRejected: Vendor or patch upstream daiso-mcp inside k-skill | issue explicitly requires documenting upstream flow instead\nConfidence: high\nScope-risk: narrow\nReversibility: clean\nDirective: Keep clone-fallback docs and PR verification commands aligned with the actually runnable local invocation\nTested: node --test scripts/skill-docs.test.js\nTested: npm run ci\nTested: cd /tmp/daiso-mcp && npm install && npm run build && node dist/bin.js health\nTested: cd /tmp/daiso-mcp && node dist/bin.js get /api/oliveyoung/stores --keyword 명동 --limit 3 --json\nTested: cd /tmp/daiso-mcp && node dist/bin.js get /api/oliveyoung/products --keyword 선크림 --size 3 --json\nTested: cd /tmp/daiso-mcp && node dist/bin.js get /api/oliveyoung/inventory --keyword 선크림 --storeKeyword 명동 --size 2 --json\nNot-tested: Public npx endpoint stability beyond the verified smoke-test window

* Record fresh verification for the approved cheap-gas follow-up

The ranked Kakao fallback-order and invalid-limit fixes are already present on feature/#54, so no further code edits were necessary. This empty follow-up commit records the requested rerun verification for PR #67 before posting the implementation update.\n\nConstraint: Existing branch head already contains the approved cheap-gas-nearby follow-up\nRejected: Invent another code/doc change just to force a non-empty diff | unnecessary risk after approval\nConfidence: high\nScope-risk: narrow\nReversibility: clean\nDirective: Keep Kakao anchor fallback iteration tied to the shared ranking helper and preserve finite-number validation for limit inputs\nTested: node --test packages/cheap-gas-nearby/test/index.test.js; npm run ci; offline fixture smoke for searchCheapGasStationsByLocationQuery('서울역', ...); lsp diagnostics on affected files\nNot-tested: Live Kakao/Opinet network calls with a non-placeholder OPINET_API_KEY

* Record verified delivery for approved cheap-gas-nearby rollout

The approved Issue #54 implementation was already present on feature/#54 when this follow-up began, so this checkpoint records fresh verification evidence and keeps PR #67 moving without introducing extra code churn.

Constraint: Existing approved fixes were already on the branch and the follow-up still required a pushed update plus implementation comment
Rejected: Add additional code or docs churn | approved scope was already satisfied and green locally
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Preserve the Kakao fallback-order and invalid-count regression coverage unless equivalent runtime repros replace it
Tested: node --test packages/cheap-gas-nearby/test/index.test.js; offline fixture smoke for searchCheapGasStationsByLocationQuery('서울역', ...); npm run ci; LSP diagnostics on affected cheap-gas-nearby files
Not-tested: Live Kakao/Opinet network path without a non-placeholder OPINET_API_KEY

* Keep Blue Ribbon premium-gate remapping explicitly bounded

The issue #63 fix already remaps PREMIUM_REQUIRED for nearby lookups. This follow-up adds a regression that proves non-premium /restaurants/map failures still surface as generic request errors, and clarifies that boundary in the package and feature docs.

Constraint: PR #68 already carries the shipped behavior change and must stay aligned with current live premium-gated upstream behavior
Rejected: Broaden domain remapping to all 403 nearby errors | would hide distinct upstream failure modes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep only PREMIUM_REQUIRED on /restaurants/map mapped to premium_required unless a new verified upstream contract is documented
Tested: npm test --workspace blue-ribbon-nearby; npm run lint --workspace blue-ribbon-nearby; npm run ci; live node repro for location+coordinate nearby lookups on 2026-04-06; LSP diagnostics on src/test
Not-tested: Alternative non-premium upstream status codes beyond the mocked 403 ACCESS_DENIED path

* Keep Olive Young clone fallback docs runnable from a fresh clone

Round 3 review found that the inline fallback shorthand skipped `cd daiso-mcp`,
which made `npm install` run outside the cloned upstream repo even though the
fenced examples were already correct. This tightens the two published shorthand
snippets and adds regression coverage so both docs surfaces reject the broken
chain in future edits.

Constraint: Existing node dist/bin.js clone fallback examples were already verified and had to stay aligned
Constraint: The follow-up had to stay scoped to docs/test coverage without touching the existing daiso-product-search skill
Rejected: Convert the shorthand to prose only | the review specifically requested a runnable inline form or an explicit removal
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep inline clone fallback snippets synchronized with the fenced node dist/bin.js examples and require `cd daiso-mcp` before install/build
Tested: node --test scripts/skill-docs.test.js; npm run ci; cd /tmp/daiso-mcp && npm install && npm run build; cd /tmp/daiso-mcp && node dist/bin.js health; cd /tmp/daiso-mcp && node dist/bin.js get /api/oliveyoung/stores --keyword 명동 --limit 3 --json; cd /tmp/daiso-mcp && node dist/bin.js get /api/oliveyoung/products --keyword 선크림 --size 3 --json; cd /tmp/daiso-mcp && node dist/bin.js get /api/oliveyoung/inventory --keyword 선크림 --storeKeyword 명동 --size 2 --json
Not-tested: Public npx path in this follow-up round (previous PR verification already covered it)
Related: PR #71

* Bundle korean-spell-check script inside skill directory for packageless installs

The Python helper lived only in the repo-root scripts/ folder, so
`skills add` never shipped it. Move the real implementation into
korean-spell-check/scripts/ (mirroring joseon-sillok-search) and
replace the root copy with a thin re-export wrapper so lint/test
still resolve from the repo root.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Exclude .claude directory from skill validation to fix CI in worktrees

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* real-estate-search: MCP self-host → k-skill-proxy HTTP 전환

사용자가 직접 real-estate-mcp를 clone/self-host하는 대신
k-skill-proxy에 MOLIT 실거래가 API route를 추가해서
다른 스킬(한강수위, 미세먼지 등)과 동일한 패턴으로 사용 가능하게 함.

- GET /v1/real-estate/region-code — 지역코드 검색
- GET /v1/real-estate/:assetType/:dealType — 9개 거래 유형 조회
- molit.js: XML 파싱, 필드 정규화, 취소거래 필터링, 요약통계
- region-lookup.js: 284개 법정동 5자리 코드 토큰 매칭
- SKILL.md/docs를 HTTP proxy 기반으로 전면 재작성
- DATA_GO_KR_API_KEY를 사용자 필수항목에서 프록시 운영자 전용으로 이동

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* cheap-gas-nearby: proxy 경유로 전환 + 프로덕션 배포 구조 문서화

- cheap-gas-nearby: OPINET_API_KEY 없이 k-skill-proxy 경유로 동작하도록 변경
  - fetchAroundStations/fetchDetailById에 proxy fallback 추가
  - SKILL.md, feature doc에서 사용자 API key 요구 제거
- AGENTS.md, CLAUDE.md: proxy 개발/배포 워크플로우 문서화
- docs/features/k-skill-proxy.md: opinet route 추가, 프로덕션 자동 배포 구조 설명

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* blue-ribbon-nearby: proxy 경유로 전환 + 프리미엄 세션 프록시 라우트

Blue Ribbon /restaurants/map이 프리미엄 전용으로 전환되어,
k-skill-proxy에 BLUE_RIBBON_SESSION_ID 기반 프록시 라우트를 추가하고
blue-ribbon-nearby 패키지가 기본적으로 프록시를 경유하도록 변경.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: version packages (#74)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix(ci): remove changeset assertion that breaks CI after version bump (#78)

The used-car-price-search changeset assertion fails after `changeset version`
consumes .changeset/*.md files, breaking both CI and Release workflows on main.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-07 04:35:50 +09:00
Jeffrey (Dongkyu) Kim
8169d1d443
Merge pull request #77 from NomaDamas/feature/#76
Feature/#76
2026-04-06 21:09:02 +09:00
Jeffrey (Dongkyu) Kim
6270ec64b3 Shield Korean stock lookups behind the proxy so users avoid KRX key setup
Use the local k-skill proxy as the public integration surface for Korea Exchange stock data. The new skill/docs flow starts with stock search, then narrows into base-info and trade-info lookups, while the proxy injects KRX credentials server-side only.

Constraint: KRX_API_KEY must remain server-side under the repo's free read-only proxy policy
Rejected: Expose upstream korea-stock-mcp setup to end users | would force user-issued KRX keys and a heavier install path
Confidence: high
Scope-risk: moderate
Directive: Keep Korean stock access proxy-first and read-only; do not move KRX_API_KEY into client setup docs
Tested: node --test packages/k-skill-proxy/test/server.test.js scripts/skill-docs.test.js; npm run ci; local proxy smoke on port 4120 (/health 200, /v1/korean-stock/search 503 without KRX_API_KEY)
Not-tested: Live upstream success path with a real local KRX_API_KEY
2026-04-06 20:06:08 +09:00
Jeffrey (Dongkyu) Kim
afe5d33885 Document a bunjang-cli workflow for Bunjang marketplace lookups
Issue #73 adds a new root skill plus matching repository docs/tests so agents can guide 번개장터 searches, detail reads, optional login-gated favorites/chats, and bulk export flows without vendoring upstream code.

Constraint: Reuse upstream bunjang-cli instead of adding a new crawler or package wrapper
Constraint: favorite/chat flows require a headful TTY login and cannot be fully smoke-tested non-interactively
Rejected: Add a local workspace/package wrapper | docs-only skill scope does not justify new abstraction
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the skill CLI-first and treat favorite/chat/purchase as optional login flows unless a live authenticated session is intentionally available
Tested: npm run ci
Tested: npx --yes bunjang-cli --help
Tested: npx --yes bunjang-cli --json auth status
Tested: npx --yes bunjang-cli --json search "아이폰" --max-items 1
Tested: npx --yes bunjang-cli --json item get 354957625
Tested: bunjang-cli JSON/AI export smoke runs with --with-detail/--output and --ai --output
Not-tested: Authenticated favorite/chat round-trip in a logged-in interactive browser session
2026-04-06 19:13:31 +09:00
Jeffrey (Dongkyu) Kim
35602d0d7b Merge remote-tracking branch 'origin/dev' into feature/#52
# Conflicts:
#	docs/install.md
#	package.json
#	scripts/skill-docs.test.js
2026-04-06 16:04:22 +09:00
Jeffrey (Dongkyu) Kim
22ff61b714 Restore PR #67 reviewability after syncing feature/#54 with dev
Merged origin/dev into feature/#54 and resolved the documentation/test conflicts by keeping both the cheap-gas-nearby Opinet guidance and the newer han-river/olive-young rollout docs from dev. The merged docs and regression suite now cover both feature lanes so the branch can be re-reviewed without dropping either set of release notes or setup requirements.

Constraint: PR head had to absorb dev without merging the PR itself
Rejected: Favor one side of the conflicted docs/tests | would silently drop shipped guidance from the other branch
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep shared setup/install/security docs additive when multiple feature branches introduce new skills concurrently
Tested: npm run ci; node --test packages/cheap-gas-nearby/test/index.test.js; offline fixture smoke for searchCheapGasStationsByLocationQuery('서울역')
Not-tested: Live Opinet/API-key-backed network verification
2026-04-06 01:07:47 +09:00
Jeffrey (Dongkyu) Kim
58ee85d1f3
Merge pull request #71 from NomaDamas/feature/#61
Feature/#61
2026-04-06 01:03:28 +09:00
Jeffrey (Dongkyu) Kim
f4eafae78a Document an Olive Young search skill around the upstream daiso CLI
Issue #61 asked for an Olive Young lookup workflow without vendoring the upstream daiso-mcp server into k-skill, so this change adds a docs-only skill, threads it through repository docs, and locks the guidance with regression assertions.

The new guidance prefers CLI-first verification (`npx daiso`) and a clone fallback (`git clone https://github.com/hmmhmmhm/daiso-mcp.git`) instead of requiring direct Claude Code MCP installation. The existing daiso-product-search skill remains untouched.

Constraint: Must mention the original https://github.com/hmmhmmhm/daiso-mcp repo
Constraint: Must avoid changing the existing daiso-product-search skill
Constraint: Must prefer upstream CLI/package usage over direct Claude Code MCP installation
Rejected: Vendor upstream Olive Young code into k-skill | contradicts the minimal-addition design request
Rejected: Make Claude Code MCP setup the default path | issue explicitly asked for CLI-first usage
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the Olive Young docs aligned with upstream `daiso` CLI behavior and note public endpoint instability when live verification shows it
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: 2026-04-05 live /tmp/daiso-mcp CLI checks for health, /api/oliveyoung/stores, /api/oliveyoung/products, /api/oliveyoung/inventory
Not-tested: Authenticated/private Olive Young flows or ordering/payment paths
2026-04-05 20:58:36 +09:00
Jeffrey (Dongkyu) Kim
397d0eea84 Expose official nearby fuel prices for location-based gas station lookups
Add the first cheap-gas-nearby skill/package pair so nearby gas-price
queries can resolve a user-supplied location, translate it into Opinet's
KATEC search contract, and return the cheapest nearby stations with
address and facility detail. The docs and setup surfaces now advertise
the new skill and its Opinet API key requirement.

Constraint: Nearby fuel prices must come from the official KNOC Opinet API when available
Constraint: No new external dependencies were allowed for coordinate conversion or location resolution
Rejected: Map-only gas price scraping | official Opinet Open API exists and is the preferred source
Rejected: Require lat/lng input only | poorer UX than supporting landmark/station queries through anchor resolution
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep `OPINET_API_KEY` as the only supported official-price credential unless the repo adopts an Opinet proxy later
Tested: npm run ci; node --test packages/cheap-gas-nearby/test/index.test.js; offline fixture smoke via searchCheapGasStationsByLocationQuery('서울역', ...)
Not-tested: Live Opinet API call with a real `OPINET_API_KEY` (no non-placeholder key was configured locally)
Related: #54
2026-04-05 19:46:09 +09:00
Jeffrey (Dongkyu) Kim
afd7c6a996 Allow Han River water-level lookups without user API keys
The proxy now resolves HRFCO water-level stations via waterlevel/info and
fetches the latest 10-minute measurement via waterlevel/list, exposing a
public summary route plus a hosted skill/docs path.

Constraint: HRFCO requires a ServiceKey and station-code-based latest lookup
Rejected: Raw passthrough only | forces users to manage upstream details and misses the approved no-key UX
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep this route summary-only and public; expand rainfall/dam/bo/fldfct in separate issues
Tested: npm run ci; local server smoke test with HRFCO sample key against /v1/han-river/water-level; tsc diagnostics on packages/k-skill-proxy/src/server.js and src/hrfco.js
Not-tested: Hosted production proxy rollout
2026-04-05 19:26:06 +09:00
Jeffrey (Dongkyu) Kim
81c81cb5da Document the approved real-estate MCP skill without vendoring upstream
Issue #53 is intentionally doc-only, so this change adds the
real-estate-search skill, feature guide, setup/security notes,
and regression coverage around the upstream real-estate-mcp
integration instead of importing server code.

The new docs keep the original MCP link, cover Codex/Claude
registration, and spell out the self-host + Cloudflare Tunnel +
launchd path for environments where no fixed hosted endpoint is
available.

Constraint: Must use tae0y/real-estate-mcp without copying its source into this repository
Constraint: Must include the original MCP link and a stable self-host fallback when no hosted endpoint is available
Rejected: Vendor the upstream MCP source | issue explicitly requires skill docs only
Rejected: Assume a public hosted MCP endpoint exists | upstream docs did not publish one
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep this integration doc-only; do not add a workspace or vendored server without revisiting issue #53 constraints
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: upstream bootstrap smoke (`uv sync`, `uv run real-estate-mcp --help`, HTTP initialize on 127.0.0.1:8017)
Not-tested: live property data queries with a valid DATA_GO_KR_API_KEY
2026-04-05 14:10:45 +09:00
Jeffrey (Dongkyu) Kim
d09b41a12f Make Joseon Sillok lookups reproducible from the official site
Add a joseon-sillok-search skill and a Python helper that scrape the
official Joseon Annals search/detail pages. The helper normalizes
king/year metadata, fetches detail excerpts, and locks the repository
docs plus regression coverage around the shipped workflow.

Constraint: v1 must stay on official public HTML surfaces only
Constraint: Must avoid adding new dependencies for a simple scraping helper
Constraint: Shell connectivity to sillok.history.go.kr became intermittent during final live reruns
Rejected: Ship a new npm workspace | repo skill/docs pattern is enough for v1
Rejected: Add BeautifulSoup or another parser dependency | unnecessary for the bounded HTML patterns
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: Keep year filtering Gregorian and derived from official regnal metadata unless the upstream site exposes a better structured contract
Tested: npm run ci
Tested: Earlier live POST/detail probes against search/searchResultList.do and /id/kda_12512030_002 during implementation
Tested: Live official article inspection for kda_12512030_002 via the public site
Not-tested: Final end-to-end CLI live run after the last refactor, because the shell hit transient TCP timeouts to sillok.history.go.kr
Related: #59
2026-04-03 23:34:43 +09:00
Jeffrey (Dongkyu) Kim
9fad8ae045 Ship LCK analytics inside k-skill's managed release flow
Adapt jerjangmin's upstream lck-analytics skill/package into a new
workspace and skill pack, wire docs/install/release surfaces, and add
regression fixtures/tests plus script smoke coverage so the feature is
verifiable before publish.

Constraint: Upstream package is not published to npm yet
Constraint: Must preserve attribution to original source and author in shipped docs
Rejected: Keep the upstream lck-results install wording in k-skill | conflicts with repo workspace/package naming
Rejected: Ship only the npm package without the local skill scripts | issue explicitly requested the skill as well
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep Changesets as the only version-bump path for lck-analytics; do not hand-edit versions for release
Tested: node --test packages/lck-analytics/test/index.test.js scripts/skill-docs.test.js
Tested: npm run lint --workspace lck-analytics
Tested: npm test --workspace lck-analytics
Tested: live getLckSummary('2026-04-01', { team: '한화', includeStandings: true })
Tested: node lck-analytics/scripts/sync-oracle.js --csv lck-analytics/samples/oracle-lck-sample.csv --cache .tmp/lck-cache && node lck-analytics/scripts/build-match-report.js --date 2026-04-01 --team 한화 --cache .tmp/lck-cache && node lck-analytics/scripts/analyze-live-game.js --game game-1 --window packages/lck-analytics/test/fixtures/live-window-game-1.json --details packages/lck-analytics/test/fixtures/live-details-game-1.json --cache .tmp/lck-cache
Tested: npm run ci
Tested: npx tsc --noEmit --project /Users/jeffrey/Projects/k-skill/tsconfig.json
Not-tested: Riot live feed behavior for arbitrary future game ids outside the fixture-backed smoke path
2026-04-03 18:05:14 +09:00
Jeffrey (Dongkyu) Kim
af58195abc Replace coupang scraping package with coupang-mcp server integration
Drop the browser-based scraping package (packages/coupang-product-search)
and switch to the uju777/coupang-mcp MCP server for all Coupang product
searches. This removes the anti-bot workaround complexity and provides
8 ready-to-use tools via MCP Streamable HTTP with no API key required.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 23:34:55 +09:00
Jeffrey (Dongkyu) Kim
3bc3762195 Enable repeatable used-car price lookups from a rental-company source
Issue #46 required surveying major Korean rental companies before implementation and then choosing the easiest stable provider. SK렌터카 다이렉트 exposes 타고BUY inventory in public Next.js page data, so the feature stays dependency-free while still supporting live repeated lookups and documented provider rationale.

Constraint: Must compare major Korean rental companies before implementation
Constraint: Must verify 10+ live lookups against a real provider surface
Rejected: 롯데오토옥션 as v1 provider | public list contract was unstable and legacy .do flows returned inconsistent or 404 pages
Rejected: 레드캡렌터카 as v1 provider | no public used-car inventory or API surface was found
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep the v1 provider read-only and inventory-snapshot-based unless a stable documented public API is confirmed
Tested: npm run ci
Tested: Live 10-query run against https://www.skdirect.co.kr/tb at 2026-04-02T07:22:46Z
Tested: LSP diagnostics on affected files
Not-tested: Seller-specific detail drilldowns or non-SK providers
Related: #46
2026-04-02 16:26:04 +09:00
Jeffrey (Dongkyu) Kim
d6411f6311 Route Korean law lookups through korean-law-mcp
Add a documentation-first korean-law-search skill and lock the repo docs around the rule that Korean law queries must go through korean-law-mcp rather than a new in-repo package.

The change updates install/setup/security guidance, publishes the new feature doc, and adds regression tests so future edits keep the LAW_OC + korean-law-mcp contract intact.

Constraint: Issue #41 requires korean-law-mcp for every Korean law lookup
Constraint: Must not add a new npm or python package in this repository
Rejected: Add a repo-local law package | violates the no-new-package requirement and duplicates upstream MCP work
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep Korean law lookup guidance pinned to korean-law-mcp unless issue requirements explicitly change
Tested: node --test scripts/skill-docs.test.js
Tested: npm install -g korean-law-mcp && korean-law list && korean-law help search_law
Tested: npm run ci
Tested: npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json
Not-tested: live search_law/get_law_text against a real LAW_OC credential
2026-04-01 09:14:55 +09:00
Jeffrey (Dongkyu) Kim
46fef0f873 Make Coupang shopper research usable without pretending scraping is stable
Coupang blocks unattended shopper queries in this environment, so the new package focuses on the durable pieces we can ship honestly: official URL builders, browser-captured HTML parsers, and explicit automation probes. The docs and skill now explain the seller-API limitation, the verified anti-bot behavior, and the browser-capture fallback expected by callers.

Constraint: No general shopper Open API surfaced in Coupang's official developer docs

Constraint: Headless/direct retrieval is anti-bot blocked in verified local probes

Rejected: Bundle a scraping bypass or hidden browser dependency | violates repo policy and would over-claim reliability

Confidence: high

Scope-risk: moderate

Reversibility: clean

Directive: Keep probe/docs behavior aligned with fresh live verification before claiming unattended Coupang access works

Tested: npm run ci; live probeAutomation(query=생수) with direct fetch + Playwright-core browserFetchHtml; LSP diagnostics on changed JS/test files

Not-tested: Headed/manual browser sessions with a human-authenticated Coupang context
2026-03-31 20:57:11 +09:00
Jeffrey (Dongkyu) Kim
2700e426a9 Add a safe Toss Securities lookup surface without trading mutations
Wrap the upstream tossinvest-cli binary behind a small read-only Node package,
add the matching skill/docs wiring, and lock the behavior with regression tests plus
publish/release metadata so the new workspace stays release-ready.

Constraint: Issue #25 required using JungHoonGhae/tossinvest-cli rather than reimplementing Toss APIs directly
Constraint: The public package surface must stay read-only and avoid wrapping trading mutations
Rejected: Direct HTTP client against unofficial Toss endpoints | issue explicitly required the upstream CLI and would widen maintenance risk
Rejected: Skill docs only with no package wrapper | repo convention is to ship reusable package + docs + release wiring together
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep toss-securities limited to read-only tossctl commands unless a future issue explicitly approves trading flows and adds stronger safeguards
Tested: npm run ci; brew tap JungHoonGhae/tossinvest-cli && brew install tossctl && tossctl version; node smoke calling packages/toss-securities/src/index.js getQuote('TSLA'); lsp diagnostics on affected files
Not-tested: Authenticated account/portfolio/order-history commands against a real Toss session
2026-03-30 11:25:43 +09:00
Jeffrey (Dongkyu) Kim
011aa0e90a Keep the K League feature branch mergeable after dev advanced
Merged dev into feature/#23 and resolved the overlapping root workspace
packaging and skill-doc coverage so the branch now carries both the
new kakao-bar-nearby work from dev and the kleague-results work from
this PR without dropping either surface.

Constraint: Root pack/test wiring must cover every publishable workspace
Rejected: Keep only the PR-side root script/docs updates | would discard newer dev branch coverage for kakao-bar-nearby
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: When adding a new workspace package, update root pack:dry-run coverage and skill-doc regressions in the same change to reduce future merge churn
Tested: npm run ci
Tested: node --input-type=module live smoke for getKLeagueSummary('2026-03-22', { leagueId: 'K리그1', team: 'FC서울', includeStandings: true })
Tested: node --input-type=module live smoke for getMatchResults('2026-03-22', { leagueId: 'K리그2' })
Not-tested: Remote GitHub Actions rerun after pushing the merge-resolution commit
2026-03-29 17:27:06 +09:00
Jeffrey (Dongkyu) Kim
83d5f26b39 Add an official K League results client and skill
The K League site already exposes JSON schedule and standings endpoints, so this change wraps those official surfaces in a reusable workspace package and wires the new skill/docs flow into the repo.

The implementation keeps the fetch/parse boundary small, locks normalization with fixtures and regression tests, and documents the publish follow-up needed for the new npm package. Korean-language request headers are pinned so live payloads keep the expected team names and result labels.

Constraint: Must use official K League surfaces instead of adding scraping or third-party dependencies
Rejected: HTML scraping from schedule pages | official JSON endpoints already provide schedule and standings data
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep the accept-language header pinned to Korean unless team alias normalization is expanded for English payloads
Tested: npm run ci; live getKLeagueSummary('2026-03-22', { leagueId: 'K리그1', team: 'FC서울', includeStandings: true }); live getMatchResults('2026-03-22', { leagueId: 'K리그2' })
Not-tested: Live in-progress/postponed match statuses beyond the fixture-covered finished-game path
2026-03-29 15:57:15 +09:00
Jeffrey (Dongkyu) Kim
25b1d3b328 Let agents find open nearby bars from Korean map data
Kakao Map mobile search results and place panels provide enough public data to turn station/neighborhood queries into nearby bar summaries with live open status, menu hints, seating hints, and phone numbers. This adds a reusable workspace package plus docs/skill wiring, while keeping the flow keyless and grounded in TDD + live smoke verification.

Constraint: Must avoid paid/authenticated Kakao APIs and new dependencies
Constraint: Nearby bar results must use current live panel/open-hour data
Rejected: Kakao Local REST API | requires app key/setup and breaks the no-auth posture
Rejected: Naver Map scraping | public responses were more rate-limited in testing
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: If Kakao changes panel3/search HTML contracts, verify headers and anchor-selection heuristics before expanding fallback logic
Tested: node --test packages/kakao-bar-nearby/test/index.test.js
Tested: node --test scripts/skill-docs.test.js
Tested: lsp diagnostics on affected files (0 errors)
Tested: live smoke searchNearbyBarsByLocationQuery('사당') on 2026-03-29
Tested: npm run ci
Not-tested: Precise distance calculation when Kakao station panels omit coordinates
2026-03-29 15:34:31 +09:00
Jeffrey (Dongkyu) Kim
a9a59e3655 Keep PR #21 mergeable against the updated dev branch
Merged the latest dev branch into feature/#17 and resolved the overlapping install/test updates by preserving both the fine-dust additions from this branch and the newer Daiso workspace coverage from dev.

Constraint: Base branch dev advanced after PR #21 was opened
Rejected: Rebase and rewrite the feature branch history | a merge update restores mergeability with less risk
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When install docs or regression suites diverge across branches, keep both shipped skill entries and broaden shared assertions instead of dropping one side
Tested: npm run ci
Not-tested: Remote push / GitHub UI mergeability refresh
2026-03-28 09:25:20 +09:00
Jeffrey (Dongkyu) Kim
326a707cb6 Keep PR #19 mergeable while preserving both npm package releases
Merged origin/dev into feature/#15 and resolved the shared docs, package script, and skill regression conflicts so the Daiso work and the Blue Ribbon work can ship together. The resolution keeps both publishable workspaces in the dry-run packaging check and aligns install/source docs plus regression coverage with the combined branch state.

Constraint: PR #19 targets dev and GitHub marked it CONFLICTING against origin/dev
Constraint: Release and packaging changes must continue to pass npm run ci after conflict resolution
Rejected: Dropping the Blue Ribbon additions during merge resolution | would lose newer dev branch work
Rejected: Keeping only one workspace in pack:dry-run | would leave the other publishable package unverified
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If another publishable workspace is added, extend both package.json pack:dry-run and scripts/skill-docs.test.js together
Tested: npm install; npm run ci
Not-tested: GitHub mergeability refresh after push
2026-03-27 22:19:48 +09:00
Jeffrey (Dongkyu) Kim
8c86d54b1f Add local air-quality lookup so k-skill covers location-based dust checks
Issue #17 approved an Air Korea two-API flow with a region fallback, so this change adds a new fine-dust skill, wires it into the repo docs/setup surfaces, and includes a runnable helper plus fixtures/tests for repeatable verification.

Constraint: Must use the approved official Air Korea APIs and secure secret registration flow
Rejected: Use an unofficial air-quality API | issue follow-up explicitly approved the Air Korea two-API flow
Rejected: Require coordinates only | issue discussion required a practical fallback when precise location is unavailable
Confidence: high
Scope-risk: moderate
Directive: Keep the helper and docs aligned with Air Korea endpoint names and fallback order if the official API contract changes
Tested: npm run ci; python3 scripts/fine_dust.py report --station-file scripts/fixtures/fine-dust-stations.json --measurement-file scripts/fixtures/fine-dust-measurements.json --lat 37.5665 --lon 126.9780; python3 scripts/fine_dust.py report --station-file scripts/fixtures/fine-dust-stations.json --measurement-file scripts/fixtures/fine-dust-measurements.json --region-hint '서울 강남구'; python3 scripts/fine_dust.py --help; missing-secret error path without AIR_KOREA_OPEN_API_KEY
Not-tested: Live Air Korea API calls with a real AIR_KOREA_OPEN_API_KEY
2026-03-27 22:06:19 +09:00
Jeffrey (Dongkyu) Kim
2352856826 Enable official Daiso store stock lookups before visiting a branch
Added a new Daiso skill and reusable workspace package around the
official Daiso Mall store search, product search, and pickup-stock
surfaces. The implementation stays stock-first because the official
surface clearly exposes store inventory but I could not verify any
official aisle/location endpoint for in-store placement.

Constraint: Must rely on official Daiso Mall surfaces before considering scraping
Constraint: Tests-first implementation and full repo CI must stay green
Rejected: Playwright-first scraping flow | official SearchGoods and selStrPkupStck endpoints were sufficient
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If Daiso exposes an official in-store location endpoint later, extend this package instead of inferring shelf locations
Tested: node --test scripts/skill-docs.test.js
Tested: node --test packages/daiso-product-search/test/index.test.js
Tested: npm test
Tested: npm run ci
Tested: live smoke for searchStores/searchProducts/getStorePickupStock/lookupStoreProductAvailability against Daiso Mall on 2026-03-27
Not-tested: Logged-in-only variants beyond anonymous official search/store/stock surfaces
2026-03-27 18:53:53 +09:00
Jeffrey (Dongkyu) Kim
4121e086eb Make nearby Blue Ribbon searches reusable and location-first
Issue #16 adds a new location-first Blue Ribbon skill, documents that 맛집 requests should route here by default, and ships a reusable npm workspace client over the official Blue Ribbon zone/search surfaces.

The package now parses official zone links, matches user-provided location text or coordinates, and queries the nearby JSON endpoint while filtering to certified ribbon venues only. Repo docs, install guidance, release metadata, and regression coverage were updated together so the new skill can ship cleanly.

Constraint: Must ask the user for current location before nearby search
Constraint: Blue Ribbon nearby calls require browser-like headers and official zone/search parameters
Rejected: Auto-detect user geolocation | violates the issue requirement to ask first
Rejected: Generic web search scraping without a reusable package | weaker reuse and less aligned with official Blue Ribbon surfaces
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep certified-ribbon filtering pinned to RIBBON_ONE/TWO/THREE unless the official Blue Ribbon contract changes
Tested: npm run ci; live smoke with searchNearbyByLocationQuery('광화문', { distanceMeters: 1000, limit: 5 })
Not-tested: Ambiguous location strings that require conversational disambiguation beyond current zone heuristics
2026-03-27 18:20:05 +09:00
Jeffrey (Dongkyu) Kim
3c6a7d2e51 Keep parcel-tracking guidance aligned with the verified carrier flows
The delivery-tracking skill already existed on feature/#4, but the
CJ example still documented a naive Python HTTP path. This follow-up
switches the documented CJ flow to the verified curl+cookie+_csrf
sequence, then tightens the surrounding docs so the shipped scope and
future carrier-extension story stay consistent.

Constraint: CJ tracking-detail rejects naive direct HTTP calls without preserved session state
Constraint: Must keep the existing feature/#4 PR against dev accurate without widening scope
Rejected: Keep the urllib-only CJ example | live smoke test returned 403 and contradicted the docs
Confidence: high
Scope-risk: narrow
Directive: Re-run live carrier smoke tests before changing documented transport steps for CJ or 우체국
Tested: npm run ci; live CJ curl+cookie+_csrf verification for 1234567890; live 우체국 curl verification for 1234567890123
Not-tested: Real non-placeholder customer waybills
2026-03-27 00:35:54 +09:00