Commit Graph

460 Commits

Author SHA1 Message Date
Jeffrey (Dongkyu) Kim 06453dd1ee 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
2026-04-01 09:52:01 +09:00
Jeffrey (Dongkyu) Kim 62a112f859 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
2026-04-01 09:49:47 +09:00
Jeffrey (Dongkyu) Kim e981a81e46 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
2026-04-01 09:39:03 +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 40224b8d03 Merge pull request #40 from NomaDamas/feature/#36
Feature/#36
2026-03-31 21:51:13 +09:00
Jeffrey (Dongkyu) Kim 4cc218a56f 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
2026-03-31 21:47:58 +09:00
Jeffrey (Dongkyu) Kim 68a37cc12b 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
2026-03-31 21:31:15 +09:00
Jeffrey (Dongkyu) Kim 7f71b98b01 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
2026-03-31 21:15:02 +09:00
Jeffrey (Dongkyu) Kim 6386a81409 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)
2026-03-31 20:59:27 +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 8121a7f853 Merge pull request #39 from NomaDamas/feature/#29
Feature/#29
2026-03-31 14:47:47 +09:00
Jeffrey (Dongkyu) Kim bff94efe80 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
2026-03-31 14:24:54 +09:00
Jeffrey (Dongkyu) Kim 033e8c7379 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)
2026-03-31 14:17:02 +09:00
Jeffrey (Dongkyu) Kim 1543713c73 Merge pull request #38 from NomaDamas/feature/#35
Feature/#35
2026-03-31 11:53:41 +09:00
Jeffrey (Dongkyu) Kim 24ca8feb5f 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
2026-03-31 11:48:55 +09:00
Jeffrey (Dongkyu) Kim d62e177a1b 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
2026-03-31 11:18:00 +09:00
Jeffrey (Dongkyu) Kim fbc004af9d 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
2026-03-31 10:25:55 +09:00
Jeffrey (Dongkyu) Kim bd6997d133 Merge pull request #34 from NomaDamas/changeset-release/main
chore: version packages
2026-03-30 22:41:07 +09:00
github-actions[bot] fa2e1bada8 chore: version packages 2026-03-30 13:40:28 +00:00
Jeffrey (Dongkyu) Kim 3255b236f0 Merge pull request #33 from NomaDamas/hotfix/changesets-changelog-release
Fix Changesets release PR generation by enabling package changelogs
2026-03-30 22:31:14 +09:00
Jeffrey (Dongkyu) Kim da8eca15c2 Align Changesets release flow with generated package changelogs
The release workflow uses changesets/action to build the Version Packages PR, and that action reads each changed package's CHANGELOG.md after running changeset version. The repo had changelog generation disabled, so versioning succeeded but the action crashed with ENOENT when it tried to read missing package changelogs.

This enables the default Changesets changelog generator so release PRs can be assembled without manual stub files, while keeping GitHub Releases disabled for npm publishes. The release docs now match that behavior.

Constraint: Keep createGithubReleases false because npm package GitHub releases are still out of scope
Rejected: Add empty CHANGELOG.md files to each package | quick hotfix but leaves PR notes weak and requires manual upkeep for new packages
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If changelog generation is disabled again, replace changesets/action PR generation or restore package changelog files before merging
Tested: npm run version-packages in local verification after enabling changelog generation
Tested: npm run ci
Not-tested: Live GitHub Actions release run on main after merge
2026-03-30 22:27:07 +09:00
Jeffrey (Dongkyu) Kim 13f39d14ff Merge pull request #31 from NomaDamas/dev
Release dev into main with Kakao bar, K League, and Toss Securities
2026-03-30 22:17:24 +09:00
Jeffrey (Dongkyu) Kim ef2c69b81c Replace sops+age encryption with plain dotenv and agent-native credential resolution
Agent environments (OpenClaw, Claude Code, Codex) assume users delegate
credentials to the agent. sops+age added setup friction without real
security benefit since the agent decrypts on every call anyway.

New model: skills declare required env var names; how they are supplied
is up to the agent (own vault, shell env, or ~/.config/k-skill/secrets.env
as the default fallback with 0600 permissions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:12:04 +09:00
Jeffrey (Dongkyu) Kim 249b56e2b1 Keep npm release automation from crashing before publish
Recent main-branch release workflow runs were failing before the Version Packages
PR could be created because changesets/action tried to read per-package
CHANGELOG.md files that do not exist in this repo. The repo deliberately
keeps `.changeset/config.json` on `changelog: false`, so disable
`createGithubReleases` to match that model and stop the action from
expecting generated changelog files.

Constraint: Repository package releases intentionally run with `.changeset/config.json` set to `changelog: false`
Constraint: Existing GitHub Actions runs on 2026-03-25, 2026-03-26, and 2026-03-28 failed with ENOENT on missing package CHANGELOG.md files
Rejected: Add per-package CHANGELOG.md generation | unnecessary extra release surface for a repo that intentionally skips changelog files
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If you later enable Changesets changelog generation, revisit `createGithubReleases` together with package CHANGELOG.md expectations
Tested: npm run ci; npx changeset status; gh run view failed release logs for runs 23547709848, 23602324893, 23687336625
Not-tested: Live post-fix GitHub Actions release run on main
2026-03-30 21:58:06 +09:00
Jeffrey (Dongkyu) Kim 3c4be51975 Avoid per-package bootstrap work for new npm package releases
Switch the npm release workflow to use the repository NPM_TOKEN so first
publishes and subsequent Changesets releases can run from GitHub Actions
without package-by-package trusted publisher setup. Add the missing
kakao-bar-nearby changeset so every current public workspace package is in
the release plan once this lands on main.

Constraint: npm trusted publisher setup requires each package to already exist on the registry
Constraint: This repository is expected to add more public npm packages over time
Rejected: Per-package trusted publishers only | too much first-publish operational overhead for each new package
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep NPM_TOKEN scoped to package publish/write needs and preserve Changesets as the single source of release intent
Tested: npm run ci; npx changeset status; npm view checks for current public workspace package publish state
Not-tested: Live GitHub Actions publish against npm registry with the newly stored token
2026-03-30 21:35:56 +09:00
Jeffrey (Dongkyu) Kim 41278b1c62 Merge pull request #30 from NomaDamas/feature/#25
Feature/#25
2026-03-30 12:04:22 +09:00
Jeffrey (Dongkyu) Kim 327ca7d89a Record the verified toss-securities follow-up delivery
The approved implementation for issue #25 was already present on feature/#25, so this commit records the fresh verification pass and PR follow-up delivery without changing the reviewed code.

Constraint: Existing approved workspace/docs/tests/lockfile diff was already pushed on feature/#25
Rejected: Touch source or docs again after approval | unnecessary merge risk with no product delta
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If a future follow-up only needs verification/reporting, prefer delivery metadata over reopening the approved code diff
Tested: npm ci --dry-run; npm run ci; brew tap JungHoonGhae/tossinvest-cli && brew install tossctl && tossctl version; node smoke getQuote('TSLA'); LSP diagnostics
Not-tested: Additional code changes beyond the already-approved PR diff
2026-03-30 11:50:34 +09:00
Jeffrey (Dongkyu) Kim 8322f60da0 Keep npm ci green for the toss-securities workspace
The toss-securities workspace was added without a root lockfile entry, so clean installs failed before CI could reach the otherwise-green test suite. This change adds a regression test that pins the required workspace/link metadata and regenerates the root package-lock so npm ci stays reproducible.

Constraint: GitHub Actions runs npm ci before npm run ci
Rejected: Rely on a manual lockfile refresh only | would allow the CI blocker to regress silently
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When adding a workspace, refresh package-lock.json and extend scripts/skill-docs.test.js to pin the required lockfile metadata
Tested: node --test scripts/skill-docs.test.js; npm ci --dry-run; npm run ci; brew tap JungHoonGhae/tossinvest-cli && brew install tossctl && tossctl version; node smoke via packages/toss-securities/src/index.js getQuote('TSLA'); LSP diagnostics on scripts/skill-docs.test.js and packages/toss-securities/src/index.js
Not-tested: No new runtime behavior beyond lockfile metadata refresh
2026-03-30 11:38:00 +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 aa51d2cbab Merge pull request #27 from NomaDamas/feature/#23
Feature/#23
2026-03-29 17:32:55 +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 998203cff3 Merge pull request #26 from NomaDamas/feature/#20
Feature/#20
2026-03-29 17:20:03 +09:00
Jeffrey (Dongkyu) Kim 51402dbd29 Keep Kakao smoke docs aligned with verified live output
The station-anchor fixes changed the documented sadang smoke snapshot, so this follow-up pins both published examples to the current 2026-03-29 live result and adds regression coverage to stop the docs from drifting again.

Constraint: Release/package docs must stay aligned with shipped live-smoke evidence
Rejected: Update only the markdown snapshots | would leave no regression guard against future drift
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When live Kakao smoke outputs change, update both the feature doc and package README together and keep the shared doc-regression assertion in sync
Tested: node --test packages/kakao-bar-nearby/test/index.test.js; node --test scripts/skill-docs.test.js; npm ci; npm run ci; live searchNearbyBarsByLocationQuery('사당', { limit: 3, panelLimit: 8 }) on 2026-03-29
Not-tested: Fresh-worktree clone after this doc-only follow-up
2026-03-29 17:05:17 +09:00
Jeffrey (Dongkyu) Kim d40e362cef Keep Kakao station searches anchored to public places
Station-like Kakao queries were still falling through malformed subway panels to the first usable business result, which skewed every downstream distance calculation. This change keeps area queries on usable landmark anchors, restricts station-like fallthroughs to anchor-like prefix matches, and adds regressions for both the area-query and station-query paths.

Constraint: Kakao subway panels can return only subway_station_id without summary coordinates
Constraint: Must preserve live nearby-bar lookups for area queries like 사당 while avoiding unrelated business anchors
Rejected: Accept any usable fallback with coordinates | still measures from unrelated businesses
Rejected: Throw for all station-like fallback misses | would regress live area-query usability when landmark anchors are already good
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If Kakao introduces new public-place categories, extend the anchor-like allowlist before relaxing the station-query prefix guard
Tested: node --test packages/kakao-bar-nearby/test/index.test.js
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: live searchNearbyBarsByLocationQuery('사당', { limit: 3, panelLimit: 5 }) on 2026-03-29
Tested: live searchNearbyBarsByLocationQuery('사당역', { limit: 3, panelLimit: 5 }) on 2026-03-29
Not-tested: Other non-역 Kakao location aliases that may need new anchor-category allowlist entries
2026-03-29 16:43:27 +09:00
Jeffrey (Dongkyu) Kim c784a77454 Reject impossible K League schedule dates before querying
The kleague-results API previously accepted regex-shaped but impossible calendar dates and treated them like empty-result queries. This change adds a regression test first, then rejects invalid YYYY-MM-DD strings during normalization so bad input never reaches the fetch layer.

Constraint: Public API contract says date must be a valid Date or YYYY-MM-DD string
Rejected: Let upstream return zero matches | hides invalid input as a valid no-results response
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep string-date validation in normalizeDateInput before any schedule fetch
Tested: node --test packages/kleague-results/test/index.test.js; npm run ci; live smoke getKLeagueSummary(2026-03-22, K리그1, FC서울, standings); live smoke getMatchResults(2026-03-22, K리그2); invalid-date smoke getMatchResults(2026-13-40); LSP diagnostics on changed files; architect verification
Not-tested: Additional leap-year and month-end invalid-date permutations
2026-03-29 16:22:38 +09:00
Jeffrey (Dongkyu) Kim dc9afab5a7 Keep Kakao nearby bar lookups grounded on usable place anchors
A malformed Kakao subway panel can return only a subway_station_id, which previously short-circuited anchor resolution and left distance calculations null. This change locks that regression with a failing-first test, skips unusable anchor panels until a real place panel is found, and refreshes the root lockfile so clean workspace installs include kakao-bar-nearby.

Constraint: Kakao subway panels can omit summary.confirm_id and summary.point while still returning HTTP 200
Constraint: Workspace package metadata must stay in the root lockfile for npm ci to succeed in fresh checkouts
Rejected: Accept station-category fallbacks without coordinates | keeps distanceMeters null for live 사당 lookups
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Do not treat Kakao panel responses as valid anchors unless they expose real coordinates and a place URL source
Tested: node --test packages/kakao-bar-nearby/test/index.test.js; node --test scripts/skill-docs.test.js; npm ci; npm run ci; live searchNearbyBarsByLocationQuery('사당') smoke on 2026-03-29
Not-tested: Broader Kakao schema drift outside the malformed subway_station_id panel shape
2026-03-29 16:16:36 +09:00
Jeffrey (Dongkyu) Kim 01915d8032 Make the package README example runnable
The initial package README used top-level await inside a CommonJS example. This follow-up keeps the documented install/use flow aligned with Node defaults by wrapping the sample in an async IIFE.

Constraint: README example should run as pasted under the package's CommonJS entrypoint
Rejected: Switching the example to ESM only | package docs still center the CommonJS require path
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep package README examples executable without assuming top-level await in CommonJS
Tested: npm run ci
Not-tested: Alternate package-manager docs rendering
2026-03-29 16:00:04 +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 91ec9615fc Merge pull request #22 from NomaDamas/dev
Release dev into main with the current Korea skill set
2026-03-28 23:32:54 +09:00
Jeffrey (Dongkyu) Kim 8b36634e28 Stop guessing districts and require exact station retries for ambiguous fine-dust lookups
The fine-dust proxy now resolves natural-language region hints through
city-level station lists and only returns a report when a single station
can be justified. When the hint is ambiguous, the proxy returns a small
candidate list so callers can retry with an exact station name instead
of silently guessing.

The skill guidance was updated to match that runtime contract: region
hint first, then retry with stationName when candidate_stations are
returned. Coordinate-centric guidance was removed from the primary skill
surface so the default path stays lightweight and consistent with the
live proxy behavior.

Constraint: The current AirKorea key can access city-level and station-level measurement APIs but station-info lookups may still return 403
Constraint: Free-API proxy responses must stay safe to expose publicly, so ambiguous locations should not be auto-guessed
Rejected: Auto-pick the first city-level station for unmatched district hints | hides ambiguity and returns misleading air-quality data
Rejected: Keep coordinate-first language in the primary skill | no coordinate source exists in the default user flow
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Preserve the ambiguous_location contract; if you improve matching later, prefer evidence-backed narrowing over silent fallback guesses
Tested: node --test scripts/skill-docs.test.js; npm run test --workspace k-skill-proxy; python3 -m unittest discover -s scripts -p test_fine_dust.py; live curl for ambiguous regionHint=광주 광산구 and exact stationName=우산동(광주)
Not-tested: Broader region alias quality outside the manually checked examples
2026-03-28 23:28:12 +09:00
Jeffrey (Dongkyu) Kim a3ef6ffac6 Make the fine-dust proxy easier to consume than the upstream APIs
The fine-dust lane now treats the public proxy as the default surface,
keeps a simple summarized report endpoint, and also exposes a narrow
AirKorea passthrough shape so callers can reuse upstream query patterns
without carrying service keys on the client side.

The skill instructions were trimmed down so the default path is obvious,
region-name guidance stays visible, and detailed implementation notes
move into feature docs instead of bloating the primary skill surface.

Constraint: Free-API proxy endpoints are intentionally public and must avoid embedding upstream secrets in the repo
Constraint: AirKorea station-info access can return 403 even when measurement access succeeds, so the report path needs a measurement-only fallback
Rejected: Keep proxy auth via shared token | contradicts the intended public free-API proxy policy
Rejected: Force all callers onto the summary endpoint only | passthrough compatibility is useful for direct HTTP consumers
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep the proxy allowlist narrow; if new upstream routes are exposed, document them explicitly rather than turning this into a generic open proxy
Tested: node --test scripts/skill-docs.test.js; npm run test --workspace k-skill-proxy; python3 -m unittest discover -s scripts -p test_fine_dust.py; live curls against /health, /v1/fine-dust/report, and /B552584/ArpltnInforInqireSvc/getMsrstnAcctoRltmMesureDnsty
Not-tested: Fresh reboot validation of PM2/cloudflared persistence after the latest code-only changes
2026-03-28 17:14:18 +09:00
Jeffrey (Dongkyu) Kim 96242e6220 Keep development-time skill testing on home-directory installs
Document the repository rule that active skill development should sync into the user's home-level Claude and agents skill directories before testing.

This prevents accidental repo-local .claude/.agents directories and preserves the existing global-testing workflow, including ~/.agents/skills symlink setups.

Constraint: The user's development workflow depends on home-directory global skill installs
Rejected: Repo-local .claude/.agents mirrors | caused incorrect local state and does not match the intended test surface
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When testing this repo's skills, sync ~/.claude/skills and ~/.agents/skills first and do not create repo-local install folders unless explicitly requested
Tested: git diff review of AGENTS.md rule change; verified home-directory skill sync targets during the same session
Not-tested: No automated repo test suite run because the change is instruction-only
2026-03-28 14:27:37 +09:00
Jeffrey (Dongkyu) Kim 2391f7707d Merge pull request #21 from NomaDamas/feature/#17
Feature/#17
2026-03-28 11:55:40 +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 9ef274c3b7 Honor documented fine-dust fallback semantics
The fine-dust helper still broke the documented station-name path
when the station lookup API returned no rows, and it guessed a
KHAI label from PM10 whenever the upstream API omitted khaiGrade.
This change locks both behaviors with regressions, resolves station
selection to a direct measurement lookup when only the station name
is usable, and reports 정보없음 when the source omits the KHAI field.
The docs now match the implemented fallback and missing-field behavior.

Constraint: Keep the fix compatible with existing fetch_station_payload callers and PR #21 scope
Rejected: Recompute KHAI from other pollutant fields | official formula/data inputs are not implemented in this helper
Rejected: Fail hard when station lookup is empty despite --station-name | contradicts the documented direct station-name fallback
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Do not synthesize 통합대기등급 from PM10/PM2.5 surrogates unless the official KHAI formula and inputs are implemented end-to-end
Tested: python3 scripts/test_fine_dust.py; 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; env -u AIR_KOREA_OPEN_API_KEY python3 scripts/fine_dust.py report --lat 37.5665 --lon 126.9780; python3 -m py_compile scripts/fine_dust.py scripts/test_fine_dust.py
Not-tested: Live Air Korea API responses with a real service key
2026-03-27 22:58:01 +09:00
Jeffrey (Dongkyu) Kim 5d455ac799 Merge pull request #19 from NomaDamas/feature/#15
Feature/#15
2026-03-27 22:53:08 +09:00
Jeffrey (Dongkyu) Kim 1e13cc10e1 Keep PR #19 CI stable without user Python site-packages
The validate job was failing because the KTX helper regression suite imported optional runtime dependencies directly from the module top level. GitHub Actions does not inherit the local user site-packages that made those imports succeed on the workstation, so the test suite died before it could exercise the helper logic.

This change makes the helper import-safe in minimal environments by deferring requests usage, providing lightweight fallbacks for optional Korail/Crypto imports during unit tests, and surfacing an explicit install command when the real runtime dependencies are actually needed. The docs now list pycryptodome alongside korail2, and the regression suite forces PYTHONNOUSERSITE=1 so CI keeps exercising the dependency-light path instead of accidentally relying on a developer machine.

Constraint: PR #19 must keep npm run ci green on GitHub Actions without assuming user-level Python packages
Constraint: The KTX helper still needs the real korail2 and pycryptodome packages for live reservation flows
Rejected: Installing ad-hoc Python packages in the CI workflow | hides the import-safety regression instead of fixing the helper/test contract
Rejected: Removing the Python regression suite from skill-docs coverage | would lose the guard on the train_id reservation flow
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the KTX helper importable under PYTHONNOUSERSITE=1 and document every required runtime package in both the skill and install docs
Tested: PYTHONNOUSERSITE=1 python3 -m unittest discover -s scripts -p test_ktx_booking.py
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Not-tested: GitHub Actions validate rerun after push
2026-03-27 22:51:33 +09:00
Jeffrey (Dongkyu) Kim 3237d9dc2f Report fallback provenance honestly after nearby lookup misses
The CLI previously inferred lookup provenance only from whether lat/lon
were supplied, which overstated precision when the Air Korea nearby
station lookup returned no rows and the command had to fall back to the
region/station search path. Carry the resolved lookup source through the
station-fetch step so rendered reports distinguish true coordinate hits
from fallback results, and lock that behavior with a JSON CLI regression.

Constraint: Keep the existing fetch_station_payload interface stable for current tests and callers
Rejected: Recompute provenance inside build_report from args alone | cannot observe live nearby-empty fallback outcome
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If station lookup adds more branches, keep report provenance wired from the resolved fetch path rather than inferring from raw inputs
Tested: PYTHONPATH=scripts python3 -m unittest scripts.test_fine_dust.FineDustTests.test_cli_json_report_marks_region_fallback_when_nearby_lookup_is_empty; python3 scripts/test_fine_dust.py; 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; env -u AIR_KOREA_OPEN_API_KEY python3 scripts/fine_dust.py report --lat 37.5665 --lon 126.9780
Not-tested: Live Air Korea network responses with a real API key in this environment
2026-03-27 22:44:04 +09:00
Jeffrey (Dongkyu) Kim 1453448947 Honor Air Korea's TM-coordinate contract for nearby station lookup
PR #21 review found the live location path was sending raw WGS84 latitude/longitude into getNearbyMsrstnList. This updates the helper to convert WGS84 inputs into Air Korea's central-origin TM coordinates without adding a new dependency, adds regression coverage for the live request path plus fallback behavior, and aligns the published skill/docs examples with tmX/tmY usage.

Constraint: Air Korea nearby-station lookup requires TM coordinates and this repo should not add new runtime dependencies for a helper script
Rejected: Add pyproj/proj4 as a dependency | unnecessary dependency footprint for a deterministic coordinate transform
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep getNearbyMsrstnList on TM inputs only; if the upstream coordinate contract changes, verify against the official Air Korea docs before editing request params again
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; env -u AIR_KOREA_OPEN_API_KEY python3 scripts/fine_dust.py report --lat 37.5665 --lon 126.9780; python3 -m py_compile scripts/fine_dust.py scripts/test_fine_dust.py
Not-tested: Live Air Korea API call with a real service key on this branch
2026-03-27 22:28:24 +09:00