mirror of
https://github.com/NomaDamas/k-skill.git
synced 2026-09-14 16:37:18 +08:00
dev
454 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4ba9876a57 |
feat: 국가데이터처 KOSIS 통계 조회(kosis-stats) 스킬 추가 (#216)
* feat: 국가데이터처 KOSIS 통계 조회(kosis-stats) 스킬 추가 KOSIS Open API 4개 endpoint(statisticsSearch / statisticsData getMeta / statisticsParameterData / statisticsBigData) read-only 호출을 단일 Python helper로 묶었다. 인증키는 KSKILL_KOSIS_API_KEY 환경변수(또는 기본 secrets.env)로 사용자별 발급한다 — proxy 미사용. - kosis-stats/SKILL.md, scripts/run_kosis_stats.py: stdlib only, search/meta/data/bigdata 서브커맨드, --json/--text/--dry-run - kosis-stats/references/kosis-openapi-guide.md: 인증키 발급, 호출 한도 (분당 1000건/40k cells), 에러 코드, HTTPS 전용 정책 정리 - kosis-stats/tests/: stdlib unittest 36개, mock 기반 (네트워크 X) + KSKILL_KOSIS_API_KEY 가 있을 때만 도는 라이브 smoke 1개 - docs/features/kosis-stats.md, README, install/setup/security-and-secrets/ sources, examples/secrets.env.example, package.json lint/test 등록 * fix(kosis-stats): 사용자 시나리오 e2e 검증 기반 UX 보강 4개 sonnet 서브에이전트 병렬 시나리오(단일수치/시계열/지역비교/실패회복) 검증에서 발견된 P1/P2 UX 부족함 보강. 4개 회복 시나리오 친절도 평균 2.75 → 4.5 (S4c 코드 20 막힘 P1 해결). - ERROR_CODE_HINTS: 코드 20/21/30/31 모두 next-step 명령 예시 포함 (코드 20은 ITM 메타 우선 안내 — 실제 표 다수에서 OBJ 비어 있음) - render_search_text: Next 액션 흐름 안내 추가 - render_meta_text: 빈 결과 시 다른 --meta-type 시도 안내 - render_data_text: 빈 결과 시 필터/meta 재확인 안내, 새 [summary] 라인(rows/period/unit, UNIT_NM 누락 명시) - SKILL.md Workflow: 코드 20 회복 절차, 행정구역 코드(시도 2자리/시군구 5자리) 관례 명시 - SKILL.md Failure modes: 코드 20 추가, meta 30 분기, UNIT_NM 누락 처리, 코드 20/31 회복 시나리오 예시 - docs/features/kosis-stats.md "흔한 문제 해결"에 코드 20 회복 절차 추가 - tests: 8개 회귀 테스트 추가 (hint 키워드/render 메시지/[summary] 라인) * fix(kosis-stats): drop xls bigdata format and detect json error envelope in non-json formats Reviewer follow-up on PR #216: - Removes `xls` from bigdata --format choices. KOSIS returns xls as a binary Excel payload, but the helper streams text-only output, which would corrupt the file. json/sdmx/csv (text) remain supported. - Detects KOSIS `{err, errMsg}` envelopes even when --format is csv/sdmx, so non-json bigdata responses surface auth/limit errors instead of printing a misleading error envelope as raw success output. - Updates SKILL.md, references/kosis-openapi-guide.md, and docs/features/kosis-stats.md so the advertised contract matches the helper's actual capabilities. - Adds 3 unit tests: xls rejection, json error envelope detection in csv mode, and clean csv passthrough when no error envelope is present. --------- Co-authored-by: Jeffrey (Dongkyu) Kim <vkehfdl1@gmail.com> |
||
|
|
4e5abf0861 |
Feature/#212 (#214)
* Help donors choose verified recipients by place and cause Add a read-only donation-place search skill and npm helper that ranks Korean donation recipients by user-provided location/category while keeping final verification on official 1365 and recipient pages. The implementation avoids proxy routes because the chosen verification surface is public and does not require an API key. Constraint: Issue #212 requested 기부처 조회 recommendations by place and category under TDD with a PR to dev. Constraint: k-skill free API proxy policy allows proxying only when upstream requires API keys; 1365 verification links are public. Rejected: Screen-scraping 1365 result pages | headless requests were slow/unstable and would be brittle for a recommendation helper. Rejected: Treating general-purpose charities as matches for every requested category | architect review found it could return off-category results, so matching now requires explicit category tags. Confidence: high Scope-risk: narrow Directive: Do not add automatic donation/payment submission; keep this skill read-only and require official-page verification before final donation decisions. Tested: npm test --workspace donation-place-search Tested: node smoke invocation of recommendDonationPlaces + formatDonationRecommendationReport for 서울 마포구/동물 Tested: npm run lint --workspace donation-place-search Tested: npm run typecheck Tested: npm run ci Tested: architect verification approved after off-category regression fix Not-tested: Live 1365 search result scraping; intentionally not used because the skill returns official verification links instead. Co-authored-by: OmX <omx@oh-my-codex.dev> * Keep donation recommendations on requested intent Prioritize specific donation category keywords before broad general donation terms, and make item-level 1365 links candidate-specific while preserving the broad result search link. Constraint: PR #214 review required TDD fixes for category normalization and per-candidate 1365 link semantics. Rejected: Rewording item URLs as broad portal searches | the issue explicitly asks for candidate-specific verification links. Confidence: high Scope-risk: narrow Directive: Keep item officialSearchUrl candidate-specific; use result officialSearchUrl for broad latest portal searches. Tested: npm test --workspace donation-place-search; node smoke invocation; npm run lint --workspace donation-place-search; npm run typecheck; npm run ci; code-reviewer APPROVE; architect CLEAR. Not-tested: Live 1365 HTTP availability, because the workflow only builds official read-only search links and prior review documented headless 1365 timeouts. * Harden donation skill follow-up guarantees Constraint: PR #214 review follow-up required TDD, empty category defaults, README discoverability, and release-pack coverage without pinning package versions.\nRejected: Static pack dry-run allowlist | it already missed a publishable workspace and would drift again.\nConfidence: high\nScope-risk: narrow\nDirective: Keep pack dry-run coverage dynamic over publishable workspaces; do not assert workspace package versions in tests.\nTested: npm test --workspace donation-place-search; node smoke for empty category URL/recommend/report; npm run lint --workspace donation-place-search; npm run typecheck; npm run ci; git diff --check; code-reviewer APPROVE; architect CLEAR.\nNot-tested: Live 1365 portal filtering semantics, by design; links remain read-only verification entry points. * Clarify donation verification links Reject misleading 1365 URL contracts and keep item search categories aligned with the candidate that is being recommended. Constraint: PR #214 round-3 review required TDD fixes for multi-category candidate links, clean install docs, and evidence-safe 1365 wording. Rejected: Keep broad first-request category on every item URL | It mislabels later-category candidates in multi-category requests. Rejected: Preserve public baseUrl override | It conflicts with the official 1365 helper contract. Confidence: high Scope-risk: narrow Directive: Keep 1365 URLs framed as best-effort verification assists unless browser-observed 1365 search parameters are documented. Tested: npm test --workspace donation-place-search; node --test --test-name-pattern 'donation-place-search' scripts/skill-docs.test.js; npm run lint --workspace donation-place-search; npm run typecheck; npm run ci; node smoke for multi-category URLs, malformed limits, baseUrl rejection, and empty category. Not-tested: Live 1365 parameter behavior; headless HTTP remains documented as unreliable. Co-authored-by: OmX <omx@oh-my-codex.dev> --------- Co-authored-by: OmX <omx@oh-my-codex.dev> |
||
|
|
af55f58cb4 |
Feature/#207: Restore actionable Daiso pickup answer via selPkupStr fallback (#215)
* Restore actionable Daiso pickup answer when store pickup stock is blocked Adds a public selPkupStr-backed getStorePickupEligibility() helper plus a new pickupEligibility field on lookupStoreProductAvailability(). When selStrPkupStck still returns 401/403 Unauthorized as in #207, the package now reports whether the selected store is registered as a pickup-capable store for the product (pickupEligible: true|false|null), instead of only returning blocked/unknown. Closes #207 * Make scope limits explicit in skill description and feature doc Clarify across three high-traffic surfaces that this skill no longer returns exact per-store stock quantities while the official Daiso selStrPkupStck endpoint stays Unauthorized: only pickup eligibility (yes/no) is reported in that state. - daiso-product-search/SKILL.md frontmatter description rewritten so coding agents see the limit before triggering the skill - daiso-product-search/SKILL.md adds explicit Scope and limits section plus reworked When to use / When not to use examples - docs/features/daiso-product-search.md adds a new "이 기능으로 할 수 없는 일" section listing the quantity gap - root README.md row clarifies the skill answers pickup eligibility, not exact per-store quantities, while the upstream block holds * Prevent under-scoped Daiso pickup negatives Return an explicit insufficient-coverage eligibility state when selPkupStr search input cannot prove absence, and require pkupYn=Y for positive eligibility. This preserves the actionable fallback while avoiding false negatives from broad or missing store keywords. Constraint: Existing PR #215 already added selPkupStr fallback; this follow-up is limited to review-requested correctness fixes. Rejected: Treating a missing first-page match as definitive false | broad or unkeyed selPkupStr searches can miss the target store. Confidence: high Scope-risk: narrow Directive: Do not claim pickup ineligibility unless the searched selPkupStr coverage is sufficient to prove absence. Tested: npm test --workspace daiso-product-search; npm run lint --workspace daiso-product-search; npm run ci; live Daiso smoke for 10224, missing keyword, and negative 99999. Not-tested: Exhaustive multi-page live pagination across all Daiso store keywords. Co-authored-by: OmX <omx@oh-my-codex.dev> * Keep Daiso pickup fallback shape actionable Stabilize blocked pickupEligibility responses with matchedStore:null and keep optional online-stock failures from preventing the selPkupStr pickup-eligibility fallback. This preserves the core store/product/pickup answer even when reference-only online stock is unavailable. Constraint: Issue #207 requires an actionable pickup answer when the pickup-stock endpoint is blocked, and PR review required stable public response shape. Rejected: Letting optional online stock reject the end-to-end helper | it can defeat the new actionable fallback even though online stock is reference-only. Confidence: high Scope-risk: narrow Directive: Keep quantity-bearing pickupStock separate from quantity-free pickupEligibility, and do not let optional enrichments block core pickup fallback results. Tested: npm test --workspace daiso-product-search; npm run lint --workspace daiso-product-search; npm run ci; live Daiso smoke for 10224, missing keyword, negative 99999, and end-to-end lookup. Not-tested: Exhaustive live multi-page selPkupStr pagination across every store keyword. --------- Co-authored-by: OmX <omx@oh-my-codex.dev> |
||
|
|
f527515932 |
Enable property search by free auction conditions (#213)
Add Workflow C for court-auction-notice-search with direct PGJ151 property search payload mapping, representative frozen code tables, CLI/docs coverage, and normalized item rows. Constraint: Issue #184 requires Workflow C region/usage/price/date/area/flbd filters and release automation requires a Changeset. Rejected: Proxy route | courtauction.go.kr property search is a public site endpoint and does not require an API key. Confidence: high Scope-risk: moderate Directive: Keep code-table lookups fail-open and avoid tests that pin package versions or changeset file presence. Tested: npm test --workspace court-auction-notice-search; npm run lint --workspace court-auction-notice-search; npm run ci Not-tested: Live courtauction.go.kr property search, to avoid unnecessary upstream calls and potential anti-bot blocking. |
||
|
|
dc9a765e2a |
Feature/#205 (#210)
* Align proxy defaults for hosted Korean routes Constraint: Issue #205 requires unset or empty KSKILL_PROXY_BASE_URL to use the hosted proxy consistently while preserving explicit proxy overrides and server-side upstream keys.\nRejected: Keeping Seoul subway and Korea weather as self-host-only routes | it preserves the documented inconsistency and blocks zero-config usage.\nConfidence: high\nScope-risk: narrow\nDirective: Keep client docs pointing to hosted proxy defaults unless a route is intentionally removed from hosted service.\nTested: node --test scripts/skill-docs.test.js; npm run ci; hosted smoke curls for /v1/seoul-subway/arrival and /v1/korea-weather/forecast; architect verification approved.\nNot-tested: Private self-host proxy deployment. * Preserve hosted proxy fallback in setup guidance Make self-host proxy examples inactive by default so client setup no longer blocks the hosted proxy resolver contract for Seoul subway and Korea weather skills. Constraint: PR #210 review required unset and empty KSKILL_PROXY_BASE_URL to fall back to https://k-skill-proxy.nomadamas.org while preserving explicit self-host overrides.\nRejected: Keep active https://your-proxy.example.com placeholder | It creates a non-empty override and prevents hosted fallback for users copying the default secrets file.\nConfidence: high\nScope-risk: narrow\nDirective: Keep upstream API keys documented as proxy-operator/server-side only; do not reintroduce active client-side proxy placeholders for hosted-default flows.\nTested: node --test scripts/skill-docs.test.js; npm run ci; hosted smoke checks for /v1/seoul-subway/arrival?stationName=강남 and /v1/korea-weather/forecast?lat=37.5665&lon=126.9780; resolver smoke for unset, empty, and custom KSKILL_PROXY_BASE_URL; git diff --check; Ralph architect verification CLEAR.\nNot-tested: none * Clarify proxy guide override boundary Document the hosted-client default in the proxy guide while keeping the self-host placeholder as an explicitly scoped override, so users do not mistake it for required setup. Constraint: Issue #205 review round 2 left a WATCH concern on docs/features/k-skill-proxy.md client env-var wording. Rejected: Leave the proxy guide unchanged | It preserved ambiguity between hosted-client defaults and self-host/operator overrides. Rejected: Sentence-exact regression assertions | They were too brittle after code review; semantic assertions preserve wording flexibility while locking the policy. Confidence: high Scope-risk: narrow Directive: Keep KSKILL_PROXY_BASE_URL examples inactive or clearly scoped unless documenting a self-host/alternate-proxy override. Tested: node --test scripts/skill-docs.test.js; npm run ci; resolver smoke for unset empty and custom KSKILL_PROXY_BASE_URL; hosted Seoul subway and Korea weather smokes; git diff --check; code-reviewer APPROVE; architect CLEAR Not-tested: none * Keep proxy guide examples on the hosted-default path Constraint: PR #210 issue #205 follow-up requires KSKILL_PROXY_BASE_URL unset/empty to resolve to hosted while preserving explicit self-host overrides.\nRejected: Labeling the existing 127.0.0.1 examples as operator-only | it would leave the general usage section less aligned with the hosted-client default.\nConfidence: high\nScope-risk: narrow\nDirective: Keep Seoul subway and Korea weather user-facing examples on the resolver pattern unless the section is explicitly scoped to local operator smoke tests.\nTested: node --test scripts/skill-docs.test.js; npm run ci; resolver smoke for unset empty custom KSKILL_PROXY_BASE_URL; hosted Seoul subway and Korea weather smoke; architect verification CLEAR.\nNot-tested: None. |
||
|
|
e87330874b | Feature/#207 (#209) | ||
|
|
2ff51db5d2 |
feat: 개별공시지가(gongsijiga-search) 스킬 추가 (#200)
* chore: version packages * Merge dev into main (#197) * fix(toss-securities): clarify session expiry and quote 403 handling * Clarify toss empty-output session expiry Portfolio and watchlist reads can exit successfully with empty payloads when the stored Toss session has expired. The empty-output path now verifies the session before JSON parsing and only promotes confirmed invalid auth doctor data into TossSessionExpiredError. Constraint: Scope is limited to toss-securities issue #126 follow-up on PR #192 Rejected: Treat auth doctor execution failures as expired sessions | unsupported or failing doctor output is inconclusive without parsed session.valid=false Confidence: high Scope-risk: narrow Directive: Keep empty-result session expiry classification tied to explicit auth doctor confirmation Tested: npm run test --workspace toss-securities; npm run lint --workspace toss-securities; npm run ci; manual mock tossctl blank stdout invalid/inconclusive doctor checks * Avoid false session-expiry labels for validation errors The toss wrapper now treats bare validation_error text as an upstream command failure instead of a session-expired signal. Structured auth doctor JSON remains the source of truth for empty portfolio/watchlist invalid-session promotion, while known stored-session-invalid stderr still maps to TossSessionExpiredError.\n\nConstraint: PR #192 follow-up must stay scoped to issue #126 toss-securities behavior.\nRejected: Keep validation_error in the global regex | it mislabels auth doctor transport failures and quote 403 validation errors as session expiry.\nConfidence: high\nScope-risk: narrow\nDirective: Do not broaden the free-text session classifier without regressions for auth doctor and quote upstream validation failures.\nTested: npm run lint --workspace toss-securities; npm run test --workspace toss-securities; npm run ci; manual mock tossctl validation_error checks; architect verification CLEAR\nNot-tested: Live tossctl network/auth session against real Toss upstream * Align court auction lookup with monthly site search (#196) The court auction notice page posts a YYYYMM search key from its 조회 button and returns a month of rows. Keep day inputs as a compatibility filter over the monthly response and normalize the current nested detail payload shape. Constraint: courtauction.go.kr has no public API and blocks bursty automated calls. Rejected: querying every day independently | the upstream search surface is month-based and day calls return false empty results. Confidence: high Scope-risk: narrow Directive: Preserve the site-observed YYYYMM notice search contract unless the PGJ143M01 XHR changes again. Tested: npm --workspace packages/court-auction-notice-search test; npm run ci; live 서울중앙지방법원 2026-05 notice/detail smoke lookup. Not-tested: PR CI after push. Co-authored-by: OmX <omx@oh-my-codex.dev> * Guide crawler skills toward reusable discovery (#195) * chore: version packages * Guide crawler skills toward reusable discovery Constraint: User requested insane-search-style guidance for future crawling k-skills without unrelated implementation changes. Rejected: Adding crawler code or a standalone template | too broad for a docs guidance change and risks dependency creep. Confidence: high Scope-risk: narrow Directive: Keep site-specific access details inside individual skills after a site-agnostic discovery pass. Tested: npm run ci Not-tested: Live crawler behavior; documentation-only change. * Clarify crawler skill discovery guidance Constraint: Crawling k-skills need site-dependent recipes, but should derive them through a reusable discovery pass. Rejected: Leaving guidance only in docs/adding-a-skill.md | AGENTS.md and CLAUDE.md also guide future agents. Confidence: high Scope-risk: narrow Directive: Use site-agnostic discovery to find, then explicitly package, the target site's stable access path. Tested: npm run ci Not-tested: Live crawler behavior; documentation-only change. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Ground corporate registration guidance in official form sources Keep the consulting skill focused on draft/checklist support while pointing users to current IROS and law.go.kr form sources for submission-ready artifacts. Constraint: official registry forms can change outside the repository and must be re-downloaded at use time Rejected: committing copied official HWP/HWPX/PDF forms | they would become stale and risk misleading users Confidence: high Scope-risk: narrow Directive: do not treat Markdown templates as substitutes for official registry submission forms Tested: npm test * Ground incorporation drafting in real HWP forms Bundle official court incorporation forms plus public startup incorporation attachments, and make rhwp-filled HWP outputs the default drafting path for the corporate-registration skill. Replace the listed-company articles reference with a startup-suitable Ministry of Justice stock-company form and record source manifests for bundled binaries. Constraint: user requires actual sourced HWP templates, not generated placeholder binaries. Rejected: markdown-only drafting | it cannot produce submission-shaped Korean registry forms. Rejected: listed-company standard articles as the default reference | it is mismatched for typical startup incorporation. Confidence: high Scope-risk: moderate Directive: keep bundled HWP forms source-backed, sanitized, and edited only through copied working files. Tested: node --test scripts/skill-docs.test.js; npm run lint; k-skill-rhwp info on bundled HWP files; kordoc conversion spot checks. Not-tested: manual opening every HWP in Hancom Office and live registry submission. Co-authored-by: OmX <omx@oh-my-codex.dev> * Streamline corporate registration forms workflow Prioritize saved HWP forms for ordinary stock-company promoter incorporations, make required court-registry receipts and director identity certificates explicit, and remove the redundant markdown articles template so the skill stays HWP-first. Constraint: 법원등기소 기준 체크리스트 must include fee receipts, director seal/signature certificates, and resident-record documents. Rejected: Keeping a separate markdown articles template | duplicated the stored HWP articles workflow and encouraged non-HWP drafting. Confidence: high Scope-risk: narrow Directive: Keep corporate-registration-consulting focused on stored HWP form copies and explicit issued-document checklists. Tested: node --test --test-name-pattern 'corporate-registration-consulting' scripts/skill-docs.test.js; node --check scripts/skill-docs.test.js; ./scripts/validate-skills.sh; git diff --check Not-tested: Full npm run ci was not run because this is a skill documentation/template refactor, not release or package automation. --------- Co-authored-by: galvaomica <galvaomica@galvaomicaui-MacBookAir.local> Co-authored-by: OmX <omx@oh-my-codex.dev> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: version packages (#198) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * feat(realtyprice): add address parsing and sido code mapping Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(realtyprice): use string sido codes for consistency with upstream API * feat(realtyprice): add response normalization and buildResponse Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(realtyprice): add upstream cascade fetch functions with timeout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(realtyprice): add lookupGongsijiga orchestrator with region matching Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(realtyprice): add simple in-memory cache with TTL Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(proxy): register GET /realtyprice route with caching Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add gongsijiga-search SKILL.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: add changeset for gongsijiga-search Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(realtyprice): align with actual realtyprice.kr API response format - Response wraps data in model.list (not bjdList/gsiList) - Field names are code/name (not bjd_cd/bjd_nm) - bun2 empty → send "0000" (not empty string) - eupmyeondong matching: try full string match first (API returns combined "면 리" names like "청계면 청천리") Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(gongsijiga-search): align /realtyprice route with v1 API convention - Change route from /realtyprice to /v1/realtyprice for consistency with other proxy endpoints. - Add realtypriceConfigured flag to /health upstreams. - Normalize address cache key by collapsing multiple whitespaces. - Update SKILL.md and README.md to reflect the new v1 path. * feat(gongsijiga-search): add Sejong special-city support - parseAddress: allow 3-token minimum for Sejong (no sigungu) and set sigungu to empty string. - lookupGongsijiga: skip sigungu lookup for Sejong (sidoCode 29), use fixed sggCode 36110. - Add Sejong parseAddress and lookupGongsijiga test cases. - Update SKILL.md with Sejong address format examples. * refactor(gongsijiga-search): split realtyprice.kr lookup into standalone package realtyprice.kr is a fully public endpoint that needs no API key, so per the new k-skill-proxy inclusion rule (proxy is for keyed upstreams only) the helper now ships as `gongsijiga-search` and is invoked directly from the user's machine. - new workspace package packages/gongsijiga-search/ following the blue-ribbon-nearby/coupang-product-search convention (publishConfig, files, repository, keywords) - remove /v1/realtyprice route, realtyprice.js, realtyprice.test.js, and the realtypriceConfigured health flag from k-skill-proxy - document the inclusion rule in AGENTS.md and CLAUDE.md so future skills default to direct calls when no key is required - advertise the new skill in README.md, docs/install.md, and add docs/features/gongsijiga-search.md - drop the hardcoded toss-securities lockfile version assertion that pinned a workspace version (would block changesets version-packages) and document the anti-pattern in AGENTS.md / CLAUDE.md - changesets: refresh the proxy refactor message and add a patch changeset so the new gongsijiga-search package gets published --------- Co-authored-by: Jeffrey (Dongkyu) Kim <vkehfdl1@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: galvaomica <galvaomica@galvaomicaui-MacBookAir.local> Co-authored-by: OmX <omx@oh-my-codex.dev> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
32162e4cd7 |
Add korean-transit-route skill (#201)
* Add korean-transit-route skill * Apply review fixes to korean-transit-route skill - Add Done when and Failure modes sections to align with SKILL.md template - Fix Python geocode example to use with-statement for urlopen - Add korean-transit-route to README.md skill table and feature list - Add docs/features/korean-transit-route.md guide --------- Co-authored-by: Jeffrey (Dongkyu) Kim <vkehfdl1@gmail.com> |
||
|
|
d7aca1bcbe |
Merge dev into main (#197)
* fix(toss-securities): clarify session expiry and quote 403 handling * Clarify toss empty-output session expiry Portfolio and watchlist reads can exit successfully with empty payloads when the stored Toss session has expired. The empty-output path now verifies the session before JSON parsing and only promotes confirmed invalid auth doctor data into TossSessionExpiredError. Constraint: Scope is limited to toss-securities issue #126 follow-up on PR #192 Rejected: Treat auth doctor execution failures as expired sessions | unsupported or failing doctor output is inconclusive without parsed session.valid=false Confidence: high Scope-risk: narrow Directive: Keep empty-result session expiry classification tied to explicit auth doctor confirmation Tested: npm run test --workspace toss-securities; npm run lint --workspace toss-securities; npm run ci; manual mock tossctl blank stdout invalid/inconclusive doctor checks * Avoid false session-expiry labels for validation errors The toss wrapper now treats bare validation_error text as an upstream command failure instead of a session-expired signal. Structured auth doctor JSON remains the source of truth for empty portfolio/watchlist invalid-session promotion, while known stored-session-invalid stderr still maps to TossSessionExpiredError.\n\nConstraint: PR #192 follow-up must stay scoped to issue #126 toss-securities behavior.\nRejected: Keep validation_error in the global regex | it mislabels auth doctor transport failures and quote 403 validation errors as session expiry.\nConfidence: high\nScope-risk: narrow\nDirective: Do not broaden the free-text session classifier without regressions for auth doctor and quote upstream validation failures.\nTested: npm run lint --workspace toss-securities; npm run test --workspace toss-securities; npm run ci; manual mock tossctl validation_error checks; architect verification CLEAR\nNot-tested: Live tossctl network/auth session against real Toss upstream * Align court auction lookup with monthly site search (#196) The court auction notice page posts a YYYYMM search key from its 조회 button and returns a month of rows. Keep day inputs as a compatibility filter over the monthly response and normalize the current nested detail payload shape. Constraint: courtauction.go.kr has no public API and blocks bursty automated calls. Rejected: querying every day independently | the upstream search surface is month-based and day calls return false empty results. Confidence: high Scope-risk: narrow Directive: Preserve the site-observed YYYYMM notice search contract unless the PGJ143M01 XHR changes again. Tested: npm --workspace packages/court-auction-notice-search test; npm run ci; live 서울중앙지방법원 2026-05 notice/detail smoke lookup. Not-tested: PR CI after push. Co-authored-by: OmX <omx@oh-my-codex.dev> * Guide crawler skills toward reusable discovery (#195) * chore: version packages * Guide crawler skills toward reusable discovery Constraint: User requested insane-search-style guidance for future crawling k-skills without unrelated implementation changes. Rejected: Adding crawler code or a standalone template | too broad for a docs guidance change and risks dependency creep. Confidence: high Scope-risk: narrow Directive: Keep site-specific access details inside individual skills after a site-agnostic discovery pass. Tested: npm run ci Not-tested: Live crawler behavior; documentation-only change. * Clarify crawler skill discovery guidance Constraint: Crawling k-skills need site-dependent recipes, but should derive them through a reusable discovery pass. Rejected: Leaving guidance only in docs/adding-a-skill.md | AGENTS.md and CLAUDE.md also guide future agents. Confidence: high Scope-risk: narrow Directive: Use site-agnostic discovery to find, then explicitly package, the target site's stable access path. Tested: npm run ci Not-tested: Live crawler behavior; documentation-only change. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Ground corporate registration guidance in official form sources Keep the consulting skill focused on draft/checklist support while pointing users to current IROS and law.go.kr form sources for submission-ready artifacts. Constraint: official registry forms can change outside the repository and must be re-downloaded at use time Rejected: committing copied official HWP/HWPX/PDF forms | they would become stale and risk misleading users Confidence: high Scope-risk: narrow Directive: do not treat Markdown templates as substitutes for official registry submission forms Tested: npm test * Ground incorporation drafting in real HWP forms Bundle official court incorporation forms plus public startup incorporation attachments, and make rhwp-filled HWP outputs the default drafting path for the corporate-registration skill. Replace the listed-company articles reference with a startup-suitable Ministry of Justice stock-company form and record source manifests for bundled binaries. Constraint: user requires actual sourced HWP templates, not generated placeholder binaries. Rejected: markdown-only drafting | it cannot produce submission-shaped Korean registry forms. Rejected: listed-company standard articles as the default reference | it is mismatched for typical startup incorporation. Confidence: high Scope-risk: moderate Directive: keep bundled HWP forms source-backed, sanitized, and edited only through copied working files. Tested: node --test scripts/skill-docs.test.js; npm run lint; k-skill-rhwp info on bundled HWP files; kordoc conversion spot checks. Not-tested: manual opening every HWP in Hancom Office and live registry submission. Co-authored-by: OmX <omx@oh-my-codex.dev> * Streamline corporate registration forms workflow Prioritize saved HWP forms for ordinary stock-company promoter incorporations, make required court-registry receipts and director identity certificates explicit, and remove the redundant markdown articles template so the skill stays HWP-first. Constraint: 법원등기소 기준 체크리스트 must include fee receipts, director seal/signature certificates, and resident-record documents. Rejected: Keeping a separate markdown articles template | duplicated the stored HWP articles workflow and encouraged non-HWP drafting. Confidence: high Scope-risk: narrow Directive: Keep corporate-registration-consulting focused on stored HWP form copies and explicit issued-document checklists. Tested: node --test --test-name-pattern 'corporate-registration-consulting' scripts/skill-docs.test.js; node --check scripts/skill-docs.test.js; ./scripts/validate-skills.sh; git diff --check Not-tested: Full npm run ci was not run because this is a skill documentation/template refactor, not release or package automation. --------- Co-authored-by: galvaomica <galvaomica@galvaomicaui-MacBookAir.local> Co-authored-by: OmX <omx@oh-my-codex.dev> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
8c2f31ad59 |
Streamline corporate registration forms workflow
Prioritize saved HWP forms for ordinary stock-company promoter incorporations, make required court-registry receipts and director identity certificates explicit, and remove the redundant markdown articles template so the skill stays HWP-first. Constraint: 법원등기소 기준 체크리스트 must include fee receipts, director seal/signature certificates, and resident-record documents. Rejected: Keeping a separate markdown articles template | duplicated the stored HWP articles workflow and encouraged non-HWP drafting. Confidence: high Scope-risk: narrow Directive: Keep corporate-registration-consulting focused on stored HWP form copies and explicit issued-document checklists. Tested: node --test --test-name-pattern 'corporate-registration-consulting' scripts/skill-docs.test.js; node --check scripts/skill-docs.test.js; ./scripts/validate-skills.sh; git diff --check Not-tested: Full npm run ci was not run because this is a skill documentation/template refactor, not release or package automation. |
||
|
|
ff92e77fa5 |
Ground incorporation drafting in real HWP forms
Bundle official court incorporation forms plus public startup incorporation attachments, and make rhwp-filled HWP outputs the default drafting path for the corporate-registration skill. Replace the listed-company articles reference with a startup-suitable Ministry of Justice stock-company form and record source manifests for bundled binaries. Constraint: user requires actual sourced HWP templates, not generated placeholder binaries. Rejected: markdown-only drafting | it cannot produce submission-shaped Korean registry forms. Rejected: listed-company standard articles as the default reference | it is mismatched for typical startup incorporation. Confidence: high Scope-risk: moderate Directive: keep bundled HWP forms source-backed, sanitized, and edited only through copied working files. Tested: node --test scripts/skill-docs.test.js; npm run lint; k-skill-rhwp info on bundled HWP files; kordoc conversion spot checks. Not-tested: manual opening every HWP in Hancom Office and live registry submission. Co-authored-by: OmX <omx@oh-my-codex.dev> |
||
|
|
b8849953d8 |
Ground corporate registration guidance in official form sources
Keep the consulting skill focused on draft/checklist support while pointing users to current IROS and law.go.kr form sources for submission-ready artifacts. Constraint: official registry forms can change outside the repository and must be re-downloaded at use time Rejected: committing copied official HWP/HWPX/PDF forms | they would become stale and risk misleading users Confidence: high Scope-risk: narrow Directive: do not treat Markdown templates as substitutes for official registry submission forms Tested: npm test |
||
|
|
12289bd9a2 |
Guide crawler skills toward reusable discovery (#195)
* chore: version packages * Guide crawler skills toward reusable discovery Constraint: User requested insane-search-style guidance for future crawling k-skills without unrelated implementation changes. Rejected: Adding crawler code or a standalone template | too broad for a docs guidance change and risks dependency creep. Confidence: high Scope-risk: narrow Directive: Keep site-specific access details inside individual skills after a site-agnostic discovery pass. Tested: npm run ci Not-tested: Live crawler behavior; documentation-only change. * Clarify crawler skill discovery guidance Constraint: Crawling k-skills need site-dependent recipes, but should derive them through a reusable discovery pass. Rejected: Leaving guidance only in docs/adding-a-skill.md | AGENTS.md and CLAUDE.md also guide future agents. Confidence: high Scope-risk: narrow Directive: Use site-agnostic discovery to find, then explicitly package, the target site's stable access path. Tested: npm run ci Not-tested: Live crawler behavior; documentation-only change. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
a25d641d00 |
Align court auction lookup with monthly site search (#196)
The court auction notice page posts a YYYYMM search key from its 조회 button and returns a month of rows. Keep day inputs as a compatibility filter over the monthly response and normalize the current nested detail payload shape. Constraint: courtauction.go.kr has no public API and blocks bursty automated calls. Rejected: querying every day independently | the upstream search surface is month-based and day calls return false empty results. Confidence: high Scope-risk: narrow Directive: Preserve the site-observed YYYYMM notice search contract unless the PGJ143M01 XHR changes again. Tested: npm --workspace packages/court-auction-notice-search test; npm run ci; live 서울중앙지방법원 2026-05 notice/detail smoke lookup. Not-tested: PR CI after push. Co-authored-by: OmX <omx@oh-my-codex.dev> |
||
|
|
c51bcef87f |
Merge pull request #188 from seolcoding/feature/foresttrip-vacancy
✨ feat: 자연휴양림 빈 객실 조회 스킬 추가
|
||
|
|
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로 분리됨. |
||
|
|
f79308acfc |
Merge pull request #181 from NomaDamas/feature/#173
Feature/#173 |
||
|
|
11b1150110 |
Protect jangbu wrapper installs from incomplete payloads
The promoted upstream subskills need to be discoverable without making home installs destructive or incomplete. The wrapper installer now copies its support payload into both home skill roots, allows installed-wrapper reruns, and refuses to overwrite unrelated top-level jangbu-* skills unless explicitly overridden. Constraint: PR #181 review requires top-level subskill discovery under both Claude and agents roots. Constraint: Home installs must remain re-runnable without a source checkout. Rejected: Continue using generic sync_dir for promoted skills | it silently deletes unrelated user-authored skills. Confidence: high Scope-risk: narrow Directive: Do not bypass the promoted-skill ownership check without preserving unrelated home skill directories. Tested: node --test scripts/skill-docs.test.js --test-name-pattern='korean-jangbu-for' Tested: bash -n korean-jangbu-for/scripts/install.sh Tested: bash korean-jangbu-for/scripts/install.sh plus installed ~/.claude and ~/.agents wrapper reruns Tested: bash ~/.claude/skills/korean-jangbu-for/upstream/scripts/install.sh and verify.sh with Python 3.11 shim Tested: npm run ci Tested: Architect verification APPROVED Not-tested: Live CODEF collection requiring user BYOK credentials and external authentication |
||
|
|
5a4ff0759f |
Preserve jangbu attribution in top-level subskills
The wrapper advertised upstream /jangbu-* routing for both Claude and agent-compatible installs, but only nested the pinned upstream checkout. The installer now registers the upstream subskills at top level in both home skill roots while appending the wrapper attribution and accounting disclaimer policy to direct subskill use. Constraint: PR review required top-level discovery for ~/.claude/skills and ~/.agents/skills Constraint: korean-jangbu-for responses must retain original link, @kimlawtech (SpeciAI), Apache-2.0, and accounting/tax disclaimer Rejected: Copy raw upstream subskills unchanged | direct /jangbu-* use would bypass mandatory wrapper response policy Confidence: high Scope-risk: narrow Tested: node --test scripts/skill-docs.test.js --test-name-pattern='korean-jangbu-for' Tested: bash korean-jangbu-for/scripts/install.sh plus top-level Claude/agents subskill marker checks Tested: upstream runtime install and verify with Python 3.11 shim Tested: npm run ci |
||
|
|
4a44cf6a0d |
Add korean jangbu automation skill wrapper
Issue #173 needs a k-skill entry point centered on kimlawtech/korean-jangbu-for while preserving upstream attribution and accounting/tax disclaimers. Add a thin wrapper with pinned upstream install, bundled Apache license/disclaimer/notice, docs, and regression coverage for the required original link and @kimlawtech (SpeciAI) mention.\n\nConstraint: Upstream implementation remains in kimlawtech/korean-jangbu-for and is installed by pinned SHA instead of vendoring runtime payload into k-skill\nConstraint: Generated accounting/tax outputs are reference drafts, not official audits or tax filings\nRejected: Reimplement ledger automation locally | would duplicate upstream and widen maintenance scope\nConfidence: high\nScope-risk: narrow\nDirective: Keep responses for this skill citing https://github.com/kimlawtech/korean-jangbu-for and @kimlawtech (SpeciAI); do not remove tax/accounting disclaimers\nTested: node --test scripts/skill-docs.test.js --test-name-pattern='korean-jangbu-for'\nTested: bash korean-jangbu-for/scripts/install.sh\nTested: bash ~/.claude/skills/korean-jangbu-for/upstream/scripts/install.sh with Python 3.11 PATH shim\nTested: bash ~/.claude/skills/korean-jangbu-for/upstream/scripts/verify.sh\nTested: npm run ci\nNot-tested: CODEF live collection flow; requires user BYOK credentials and external auth |
||
|
|
ff255bf272 |
Improve restroom coverage with Kakao source merging
The public-restroom lookup now keeps the official CSV as the authoritative first layer while enriching sparse areas with Kakao Local keyword and gas-station searches when a REST API key is configured. All returned POIs are normalized onto local haversine distance calculations so Kakao's unreliable distance field cannot affect ordering, and map links encode names before coordinates.\n\nThe CSV path can optionally use Kakao coord2address to correct display names and addresses for known source-data coordinate mismatches without changing the default no-key behavior.\n\nConstraint: Kakao REST API requires caller-provided REST API key via option or KAKAO_REST_API_KEY\nConstraint: Existing no-key CSV-only behavior must continue to work\nRejected: Replace CSV with Kakao-only search | loses official open-time metadata and source priority\nRejected: Trust Kakao distance field | issue evidence shows user-origin mismatch\nConfidence: high\nScope-risk: moderate\nDirective: Keep CSV sourceLayer priority ahead of Kakao dedupe unless official data is explicitly deprecated\nTested: npm test --workspace public-restroom-nearby\nTested: npm run lint --workspace public-restroom-nearby\nTested: npm run ci\nNot-tested: Live Kakao REST API call with a production key |
||
|
|
0b280839d6 |
Clarify cleaner usage evidence boundaries
The cleanup helper now streams local logs, reports which evidence sources were merged, and keeps README table coverage tied to the central skill-name fixture so the documented cleanup signal stays trustworthy for large local histories and mixed imported counts. Constraint: Follow-up addresses PR #178 review comments without changing the non-destructive recommendation model. Rejected: Filtering imported usage JSON by --days inside the helper | imported counts are already aggregated and lack per-record timestamps. Confidence: high Scope-risk: narrow Directive: Keep --usage-json documented as pre-windowed unless the input schema gains timestamped per-record events. Tested: PYTHONPATH=scripts python3 -m unittest scripts.test_k_skill_cleaner Tested: node --test scripts/skill-docs.test.js Tested: npm run lint Tested: npm run typecheck && npm test Tested: npm run ci |
||
|
|
10cb419212 |
Align cleaner helper contract with selective installs
The cleanup helper is now shipped inside the k-skill-cleaner skill payload while the repo-root script remains as a compatibility wrapper. The CLI also enforces the interview-selected usage window with --days/--since and reports the effective cutoff so recommendations match the documented contract.\n\nConstraint: Selective skill installs only receive files under the skill directory.\nRejected: Remove k-skill-cleaner from selective install docs | the feature is intended to be installable standalone.\nConfidence: high\nScope-risk: narrow\nDirective: Keep the skill-local helper as the canonical implementation; the root script should stay a thin wrapper.\nTested: PYTHONPATH=scripts python3 -m unittest scripts.test_k_skill_cleaner\nTested: node --test scripts/skill-docs.test.js\nTested: CLI smoke via k-skill-cleaner/scripts/k_skill_cleaner.py with --days 90\nTested: npm run lint\nTested: npm run typecheck && npm test\nTested: npm run ci\nTested: Architect verification APPROVED\nNot-tested: Live agent transcript schemas beyond fixture-style local log samples |
||
|
|
58717576ee |
Help users retire unused K-skills
Add a conservative k-skill-cleaner workflow that interviews users, scans best-effort agent trigger logs, and reports deletion or review candidates without mutating skill directories automatically. Constraint: Trigger-count storage differs by coding agent and may be absent or rotated locally Rejected: Auto-delete low-usage skills | cleanup recommendations need explicit user approval because log signals are incomplete Confidence: high Scope-risk: narrow Directive: Keep deletion behavior recommendation-only unless a future issue explicitly approves mutation with stronger safeguards Tested: PYTHONPATH=scripts python3 -m unittest scripts.test_k_skill_cleaner; helper CLI smoke; npm run lint; npm run typecheck && npm test; npm run ci; architect verification Not-tested: Live exports from OpenClaw/ClawHub or Hermes Agent because no stable public local trigger-count schema is assumed |
||
|
|
c0b38fc517 |
Prevent IROS download path failures after payment
The IROS docs now make the corp-number happy path produce the company-name list that pinned upstream iros_download.py opens after payment, and route the customer workbook excel_path into the same private workdir boundary as other sensitive inputs and outputs. Constraint: Live IROS login/payment smoke requires user credentials, certificate/authentication, and card payment authority Rejected: Rely on upstream data/ defaults | leaves real customer workbook and company list paths inside the cloned repository Confidence: high Scope-risk: narrow Tested: node --test --test-name-pattern='iros-registry-automation' scripts/skill-docs.test.js Tested: ./scripts/validate-skills.sh Tested: npm run lint && npm run typecheck && npm test Tested: npm run ci Tested: cloned pinned upstream SHA and verified companies_list, excel_path, and configured paths resolve under private temp workdir Not-tested: Live IROS login/payment smoke; requires user credentials/authentication/payment authority |
||
|
|
bb12f433b2 |
Constrain IROS automation to a reviewed upstream boundary
The IROS skill delegates sensitive browser automation to an upstream Playwright implementation, so the execution guide now checks out a reviewed SHA and keeps real inputs and generated files in a private workdir instead of the clone. Regression coverage locks the pin and privacy-path contract to prevent future docs drift.\n\nConstraint: PR #177 review required an enforceable upstream execution boundary before merge\nConstraint: Live IROS login and payment smoke requires user credentials and card authority\nRejected: Continue documenting mutable upstream HEAD | unsafe for authenticated legal-document/payment-adjacent flows\nConfidence: high\nScope-risk: narrow\nDirective: Do not update iros-registry-automation/scripts/upstream.pin without reviewing the new upstream diff and updating the documented checkout SHA\nTested: node --test --test-name-pattern='iros-registry-automation' scripts/skill-docs.test.js\nTested: ./scripts/validate-skills.sh\nTested: npm run lint && npm run typecheck && npm test\nTested: npm run ci\nTested: cloned upstream, checked out pinned SHA, rewired config.json to a private temp workdir, and verified selected paths stay under that workdir\nNot-tested: Live IROS login/payment smoke; requires user credentials, certificate/authentication, and payment authority |
||
|
|
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 |
||
|
|
275cc56d8f |
Prevent corporate registration drafts from overreaching
Tighten the Korean corporate registration skill after round-3 review by keeping filled HWP examples outside the repository, turning the investigation-report conclusion into a user/expert-confirmed placeholder, and locking human-only final action prohibitions with regression coverage. Constraint: Legal-document workflow must avoid collecting or committing filled PII artifacts Constraint: Agent may prepare drafts and checklists only, not final legal/tax conclusions or filings Rejected: Add out/ to .gitignore | safer to teach non-repo private output for sensitive generated forms Confidence: high Scope-risk: narrow Tested: node --test --test-name-pattern='corporate-registration-consulting' scripts/skill-docs.test.js Tested: npx --yes k-skill-rhwp create-blank <tmp>/blank.hwp && npx --yes k-skill-rhwp info <tmp>/blank.hwp Tested: npm run ci |
||
|
|
a6e77545e4 |
Keep registration guidance inside safe v1 bounds
Round-two review showed that the new consulting skill still needed explicit stop gates for non-standard incorporation paths and tighter documentation regression locks. The follow-up keeps the user-facing flow beginner-friendly while routing materially different legal/tax structures to official or professional review before draft generation. Constraint: Legal-document skill must remain reference-only and avoid implying filing, tax, or governance determinations for non-standard cases Rejected: Keep broad regex alternations for human-only boundaries | they allowed prior safety requirements to regress while tests still passed Confidence: high Scope-risk: narrow Directive: Do not collapse the separate safety-boundary assertions back into alternations without a stronger replacement Tested: node --test --test-name-pattern='corporate-registration-consulting' scripts/skill-docs.test.js Tested: npx --yes k-skill-rhwp create-blank <tmp>/blank.hwp && npx --yes k-skill-rhwp info <tmp>/blank.hwp Tested: npm run ci |
||
|
|
07ad8be4ed |
Tighten corporate registration safety boundaries
The review follow-up closes legal-document safety gaps before merge by locking the expected guidance in the docs regression test and updating the skill surfaces that users and agents rely on. The representative-director clause now avoids board-resolution wording for the common two-director/no-board case, registration-license tax points to the direct 지방세법 제28조 anchor, and PII plus human-only filing boundaries are repeated where filled document workflows can expose sensitive data. Constraint: PR review requested TDD coverage for legal/tax safety wording and privacy guidance Rejected: Keep a single generic disclaimer only | document templates also need local warnings where filled artifacts are produced Confidence: high Scope-risk: narrow Directive: Do not remove the repeated privacy and human-only boundaries unless every user-facing generation surface keeps equivalent guidance Tested: node --test --test-name-pattern='corporate-registration-consulting' scripts/skill-docs.test.js Tested: npx --yes k-skill-rhwp create-blank <tmp>/blank.hwp && npx --yes k-skill-rhwp info <tmp>/blank.hwp Tested: npm run ci |
||
|
|
aea0b4a655 |
Support guided corporate registration preparation
Add a reference-only corporate registration consulting skill for first-time Korean incorporation workflows. The skill keeps user decisions explicit, provides conservative articles/document templates, and routes HWP automation through existing rhwp/kordoc surfaces instead of introducing new machinery. Constraint: Issue #168 requires legal-disclaimer wording, tax pitfall guidance, rhwp-based form support, TDD, and PR delivery to dev. Rejected: Add a new package or external automation dependency | existing skill docs and rhwp tooling are enough for this documentation/template workflow. Confidence: high Scope-risk: narrow Directive: Do not present generated registration documents as legal or tax advice; keep official-source verification and professional review caveats visible. Tested: node --test --test-name-pattern='corporate-registration-consulting' scripts/skill-docs.test.js; npx --yes k-skill-rhwp create-blank/info smoke; npm run ci Not-tested: Live court registry submission or live tax payment, intentionally outside reference-skill scope |
||
|
|
069fc0a4f4 | Merge origin/main into dev: resolve parking-lot conflicts, keep PR #156 fixes + dev routes | ||
|
|
a01a164a31 |
feat: add catchtable-sniper skill (#146)
* feat: add catchtable-sniper skill * Make the Catchtable skill loadable and discoverable The submitted skill landed under skills/ without YAML frontmatter, which broke the repo's auto-discovery contract and Codex skill loading. Move it to the root-level skill layout, add the required metadata block, and document the feature in the main README plus a dedicated guide so the PR ships in a usable state. Constraint: This repository auto-discovers skills from root-level directories only Constraint: Skill manifests must start with YAML frontmatter for Codex to load them Rejected: Keep the nested skills/catchtable-sniper layout | validate-skills and the repo's documented convention reject it Rejected: Add only README links without a feature guide | would create a broken documentation target Confidence: high Scope-risk: narrow Reversibility: clean Directive: Future skill PRs should follow docs/adding-a-skill.md and place each skill in its own root directory Tested: node --test scripts/skill-docs.test.js Tested: ./scripts/validate-skills.sh Tested: git diff --check Not-tested: End-to-end Catchtable reservation completion on a logged-in account --------- Co-authored-by: Jeffrey (Dongkyu) Kim <vkehfdl1@gmail.com> |
||
|
|
e0981abd08 |
Merge pull request #160 from NomaDamas/feature/#143
Feature/#143 |
||
|
|
f46f634bf0 |
Document preflight 400 and full canonical dedup contract in naver-news feature doc
Round-3 review flagged two non-blocking doc-completeness nits in docs/features/naver-news-search.md: - 실패 모드의 `400 bad_request` 항목이 preflight 케이스(`start + display - 1 > 1000`)를 누락하고 있었음. SKILL.md line 94 와 본문 line 128 의 '운영 팁' 과 대칭이 되도록 업데이트. - 운영 팁의 canonical dedup 설명이 쿼리 파라미터 순서와 trailing slash 만 언급해서, 실제 구현(`canonicalizeLinkForDedup`)이 같이 정규화하는 host 대소문자와 URL fragment 를 빠뜨리고 있었음. test/naver-news.test.js line 273 이 네 가지 모두 검증하고 있으므로 공개 문서를 구현과 테스트에 맞춰 정정. |
||
|
|
c563ef535b |
rhwp-edit (#155): guard replace-all case-insensitive path against UTF-16 length-drift
Round 2 review flagged a latent Unicode safety bug: when replaceAll's
caseSensitive=false branch encounters characters whose toLowerCase()
changes UTF-16 length (e.g. Turkish İ U+0130 → i + U+0307 combining dot
above), offsets taken in the lowercased haystack drift by the expansion
delta for every subsequent match and silently corrupt the document.
Reviewer repro: 'ABCİABCİXYZ' + case-insensitive İ→Z reported
{ok:true,count:2} but rendered 'ABCZABCİZYZ' instead of 'ABCZABCZXYZ'
(the X at index 8 was corrupted while the second İ survived).
Surface a descriptive error rather than silently drift:
- findAllMatchOffsets: in the case-insensitive branch, verify that the
paragraph text and the query each preserve UTF-16 length under
toLowerCase; otherwise throw with an actionable message pointing the
user to --case-sensitive or input normalization.
- This is strictly a safety guard: the 2025→2026 headline workflow,
ASCII, Hangul, and every existing test are unaffected.
Tests (TDD red → green, net +4 in packages/k-skill-rhwp):
- 'replaceAll refuses case-insensitive matching when source text
contains case-folding length-changing chars (e.g. Turkish İ U+0130)'
reproduces the exact reviewer input and asserts rejection + no output
file
- 'replaceAll refuses case-insensitive matching when the query itself
contains case-folding length-changing chars' covers the query-side path
- 'replaceAll with --case-sensitive succeeds on inputs containing İ'
confirms the guard only fires in the case-insensitive path and that
case-sensitive produces ABCZABCZXYZ with no X corruption
- 'replaceAll case-insensitive still works for normal ASCII/Hangul'
regression-guards against the fix over-rejecting the common case
Doc disclosure in all 4 surfaces called out by the reviewer:
- rhwp-edit/SKILL.md: new failure-mode bullet naming U+0130 specifically
- docs/features/rhwp-edit.md: Unicode 대소문자 무시 주의 paragraph
under scenario 3 (replace-all)
- packages/k-skill-rhwp/README.md: extended Scope section
- packages/k-skill-rhwp/src/cli.js: USAGE 'Scope note' appended
- scripts/skill-docs.test.js: 2 new assertions locking the SKILL.md and
feature-doc disclosure so they can't be silently removed
- .changeset: note the guard in the pending v0.1.0 release notes
Manual QA (end-to-end via the published CLI):
$ k-skill-rhwp replace-all … --query İ --replacement Z
→ exit 1 + 'case-insensitive matching is unsafe because case folding
changes the UTF-16 length …'
→ no output file written
$ k-skill-rhwp replace-all … --query İ --replacement Z --case-sensitive
→ {ok:true,count:2}, render shows 'ABCZABCZXYZ', search İ ⇒ found:false
$ replace-all '2025'→'2026' on '2025 2025 2025' ⇒ {ok:true,count:3}
$ replace-all 'hello'→'hi' (case-insens.) on 'hello WORLD 안녕 HELLO'
⇒ {ok:true,count:2}
Verification:
- npm test --workspace k-skill-rhwp: 35 pass / 0 fail (+4 vs Round 2)
- node --test scripts/skill-docs.test.js: 114 pass / 0 fail
- npm run ci: exit 0 (lint + typecheck + all workspace tests +
pack:dry-run + validate-skills.sh all green)
Refs PR #162 Round 2 review 'Non-blocking residual risk — Unicode
case-insensitive offset drift'.
|
||
|
|
6dbdeb1912 |
rhwp-edit (#155): fix replace-all silent no-op and document body-only scope
Upstream @rhwp/core HwpDocument.replaceAll returns {ok:true, count:N} but
does not persist the mutation into exportHwp() serialization, so the output
bytes are byte-identical to the input. This is confirmed against
@rhwp/core@0.7.3 with SHA diffing and round-trip searchText.
Rewrite the Node wrapper replaceAll to compose engine primitives that do
persist: for each body paragraph, read the full text via getTextRange,
compute all non-overlapping match offsets in JS, then apply replaceText
right-to-left so earlier offsets are unaffected by length changes. This
restores the documented '2025 → 2026 일괄 치환' headline workflow.
Guard rails in the new replaceAll:
- Reject replacements containing newline or paragraph-break characters
(\n, \r, U+2028, U+2029) with a descriptive error. Splitting a paragraph
via replaceText would invalidate subsequent offsets.
- Non-overlapping semantics against the original text, so
--query a --replacement aa against 'aaa' yields 'aaaaaa' (3 replacements)
instead of looping on the freshly inserted 'a' characters.
Tighten the regression tests to assert content, not just length:
- Same-length replacement: output SHA must differ from input, searchText
must find the replacement and must NOT find the original query.
- Longer-length replacement: paragraph length must grow by the correct
amount and output SHA must differ.
- Shorter-length replacement: paragraph length must shrink by the correct
amount and output SHA must differ.
- Empty replacement: deletes every match and output no longer contains
the query.
- Replacement contains query (a→aa on aaa): expects count 3 and length 6.
- Zero matches: count 0, output still written.
- Case-sensitive flag skips mismatched case.
- Newline replacement is rejected synchronously.
Document the body-only scope of search and replace-all in the SKILL.md
routing policy, failure-modes, CLI USAGE text, feature doc, and package
README so users know to use set-cell-text for cell content. This matches
the upstream searchText contract, which does not descend into table cells,
headers, footers, or footnotes.
Add a matching regression assertion to scripts/skill-docs.test.js so the
body-only scope note cannot be silently removed from SKILL.md or the
feature doc.
Closes review round 1 for PR #162.
|
||
|
|
cc4a270043 |
Merge origin/dev into feature/#155: resolve package.json workspace list conflict
# Conflicts: # package.json |
||
|
|
71d577b24d |
Polish naver-news: preflight, link canonicalization, /health docs (#143)
Address the three non-blocking items flagged in the round 1/2 reviews. All were explicitly deferred by the reviewer as "follow-up if the maintainer wants" — picking them up now so the feature lands with a tighter surface. 1) Preflight 400 for start + display - 1 > 1000 Naver's official news endpoint only exposes the first 1000 items (start 1..1000, display 1..100). Asking for start=1000 & display=100 would send a request that silently returns no usable items, wasting an upstream quota call. Reject the combination before calling upstream with a 400 bad_request and a message that tells the caller which item the request would have needed and what the cap is. Boundary values (start + display - 1 === 1000) are still accepted. 2) Canonical link dedup The previous dedup key was link.toLowerCase(), which failed to merge the same article when Naver's redirect URLs differed only by query-param order, trailing slash, host-name casing, or fragment. Added canonicalizeLinkForDedup() which parses the URL, sorts search params by key, strips a single trailing pathname slash, drops the fragment, and lowercases the result — conservative on purpose so different paths or different query values stay as distinct articles. The visible items[].link value is still the original URL returned by Naver; only the dedup key is canonicalized. 3) Clarify the naverSearchApiConfigured vs naverNewsApiConfigured split The two flags currently evaluate the same boolean, but their semantic contracts differ: naverSearchApiConfigured reports "are the Naver Open API keys configured" (which is advisory for the shopping route since shopping has a BFF fallback), while naverNewsApiConfigured reports "is the news route operational end-to-end" (no fallback — 503 when false). Hoist the shared expression into a local, and add a `/health 업스트림 플래그 의미` section to packages/k-skill-proxy/README.md documenting the split. Also update naver-news-search SKILL.md and docs/features/naver-news-search.md to mention the new preflight and the canonical-link dedup behavior. TDD verification: added 4 new node:test cases exercising the boundary, overflow, and URL-dedup paths; ran the full k-skill-proxy workspace suite (202/202 pass) plus the root `npm run ci` (exit 0). Manual QA on a proxy started from this commit reproduces every round-1 case plus the new preflight: start=1000 & display=100 → 400 bad_request before upstream; start=1000 & display=1 and start=901 & display=100 → 503 (or 200/401 depending on keys), confirming the boundary passes preflight. |
||
|
|
e21d70d904 | korean-slang-writing (#133): add feature doc | ||
|
|
ca6d560227 |
✨ feat: add k-dart skill for DART OpenAPI financial disclosures (#147)
* ✨ feat: add k-dart skill for DART OpenAPI financial disclosures 금감원 전자공시시스템(DART) 14개 endpoint 조회 스킬 추가. 공시검색, 기업개황, 재무제표, 배당, 증자/감자, 전환사채, 소송 등. API_K_DART 환경변수로 직접 호출하며 프록시 불필요. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 📝 docs(k-dart): remove redundant korean-stock-search dependency corpCode.xml 자체에 회사명·종목코드·고유번호가 모두 포함되어 있으므로 korean-stock-search 스킬 연계 절차 제거 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 📝 docs: add k-dart to README feature table Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 📝 docs: add k-dart feature guide and fix README link format Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix(k-dart): correct status code 013, remove invalid corp_name filter, update daily limit 3개 critical 정확성 오류 수정: 1. 상태코드 013은 "조회된 데이터 없음"이며 "접근 권한 없음"이 아님 (012=접근 불가 IP). 상태코드 표를 공식 명세 기준으로 재정리하고 누락된 014/021 코드 추가. 2. list.json은 corp_name 파라미터를 검색 필터로 지원하지 않음. SKILL.md의 잘못된 진술과 corp_name을 사용한 misleading example을 제거하고, corp_code 확보 절차를 거치도록 명시. 3. DART 일일 한도는 키당 10,000건이 아닌 20,000건이며 분당 약 1,000회 throttle도 별도로 존재함. SKILL.md 및 docs/features/k-dart.md 모두 정정. 추가로 status: "013" 발생 시 사용자 안내 정책을 Response policy에 추가하고, 오픈API 이용현황 페이지 링크를 Notes에 추가함. * 🐛 fix(k-dart): correct pifricDecsn endpoint, list.json corp_code optional, add empSttus, soften throttle claim Codex adversarial review에서 식별된 4건의 추가 정확성 이슈 수정: 1. endpoint #8 유무상증자 결정이 잘못된 API에 연결됨. piicDecsn.json은 유상증자 결정 (apiId=2020023)이며, 유무상증자 결정은 pifricDecsn.json (apiId=2020025)이 맞음. endpoint를 정정하고 piicDecsn (유상증자) 및 fricDecsn (무상증자)와의 차이를 주의문으로 추가. 2. list.json의 corp_code 는 사실 선택사항이며, 미지정 시 검색 기간이 3개월 이내로 제한될 뿐임. 이전 commit의 "corp_code 필수" 표현을 정정하고, 두 가지 호출 패턴(corp_code 지정/미지정)을 Example requests에 모두 추가. 3. "분당 약 1,000회 throttle"은 공식 공개 가이드에 근거 없음 (apiUsageStatusView.do 는 로그인 게이트). 공식 가이드가 명시한 "일반적으로 20,000건 이상 요청 시 020 발생"만 유지하고 분당 throttle 주장을 제거. 상태코드 표·Response policy도 일관되게 정리. 4. docs/features/k-dart.md가 "직원 현황" 기능을 광고하지만 SKILL.md 에는 endpoint가 누락됨. empSttus.json (apiGrpCd=DS002, apiId=2019011)을 endpoint #8로 추가하고 example도 함께 등록. 기존 endpoint 9~14는 10~15로 재번호. * 🐛 fix(k-dart): align list.json signature and 020 caveat with official spec Codex 2nd-round review에서 식별된 정확성 이슈 2건 수정: 1) list.json 요청 인자 signature가 공식 가이드(DS001/2019001)와 정확히 일치하도록 재작성. crtfc_key 외 모든 파라미터가 선택사항임을 분명히 하고, 각 파라미터의 default 동작과 pblntf_ty 값(A/B/C/D/E)도 명시. "corp_code 지정 시 기간 제한 없음" 표현은 공식 가이드가 보장하지 않으므로 제거. corp_name이 공식 파라미터에 "존재하지 않는다"는 사실로 수정 (이전: "지원하지 않는다"). "corp_code 미지정 시 3개월 제한"은 외부 사용 사례에서 관찰된 동작으로 약화 (공식 가이드에 별도 명시 없음). 2) 020 (요청 제한 초과) 안내가 일일 20,000건 cap 으로 너무 단정적 해석되던 표현을 공식 메시지 그대로 보존: "일반적으로 20,000건 이상 요청 시 발생하며, 키별로 별도 한도가 설정된 경우 다른 임계치에서도 동일 코드가 반환될 수 있음". 상태코드 표·Response policy·Notes·docs/features/k-dart.md 모두 일관되게 정정. * 🐛 fix(k-dart): mirror official Korean DS001/2019001 list.json spec exactly Codex 3rd-round review에서 식별된 잔존 정확성 이슈 수정. 영어 가이드(DE001/AE00001)와 한국어 가이드(DS001/2019001)가 list.json 필수여부에서 다르게 표기되어 있어 이전 commit이 영어 가이드를 따랐으나, 한국어 공식 가이드를 직접 확인한 결과(opendart.fss.or.kr/guide/detail.do ?apiGrpCd=DS001&apiId=2019001) 다음이 한국어 공식 spec임을 확인: - bgn_de, end_de는 Y(필수) (기본값은 명시되어 있으나 표기상 필수) - corp_code 미지정 시 검색기간 3개월 제한은 공식 spec에 명시된 룰 (외부 사용 사례 관찰이 아님) - pblntf_ty는 A~J 전체 enum (정기공시/주요사항보고/발행공시/지분공시/ 기타공시/외부감사관련/펀드공시/자산유동화/거래소공시/공정위공시) - page_count 기본값 10, 최대값 100 - corp_cls 복수 조건 불가 - last_reprt_at, sort, sort_mth 각 default 동작 명시 list.json 섹션을 공식 가이드 표와 1:1 일치하는 마크다운 표로 재작성. 3개월 제한 표현을 "외부 사례"에서 "공식 spec"으로 정정. Response policy 에 잔존하던 corp_name "지원하지 않는다" 표현도 "공식 파라미터에 존재하지 않는다"로 통일하여 #1 endpoint 섹션과 일관성 확보. docs/features/k-dart.md 도 동일하게 정정. * 🐛 fix(k-dart): make list.json table 1:1 mirror of DS001/2019001 + unify corp_name wording Codex 4th-round review가 식별한 잔존 이슈 2건 마무리. 1) list.json 파라미터 표를 공식 가이드 행 순서 그대로(crtfc_key, corp_code, bgn_de, end_de, last_reprt_at, pblntf_ty, pblntf_detail_ty, corp_cls, sort, sort_mth, page_no, page_count) 재정리하고 공식 표의 모든 컬럼(요청키/명칭/타입/필수여부/값설명)을 포함. page_no(1~n) / page_count(1~100, 기본10, 최대100) 범위 값을 공식 표 그대로 표기. pblntf_detail_ty 값설명도 공식 표 그대로 "(※ 상세 유형 참조: pblntf_detail_ty)"로 두고, 자주 쓰는 코드 예시(A001/B001/F001/D001)는 표 아래 별도 단락으로 분리해 표의 1:1 mirror 성격을 유지. 2) corp_name 관련 canonical 문장 "공식 요청 파라미터 표에 corp_name 은 존재하지 않는다" 를 다음 3곳 모두 verbatim 일치 시킴 (이전 commit에서 SKILL.md는 '않는다', docs/features는 '않음' 으로 어미 차이가 잔존했음): - k-dart/SKILL.md #1 endpoint 섹션 주의문 - k-dart/SKILL.md Response policy - docs/features/k-dart.md 에러/제약 섹션 * 🐛 fix(k-dart): unify corp_name canonical sentence verbatim + soften list.json table claim Codex 5th-round review가 식별한 fine-grained 이슈 마무리. 1) corp_name canonical 문장을 self-contained 형태로 재작성하여 3곳 모두 byte-for-byte 동일하게 통일: "DART OpenAPI list.json 의 공식 요청 파라미터 표에 corp_name 은 존재하지 않는다." - SKILL.md #1 endpoint 섹션 주의문 - SKILL.md Response policy - docs/features/k-dart.md 에러/제약 섹션 이전에는 SKILL.md는 "위 공식 요청 파라미터 표에"로 docs/features는 "list.json 공식 요청 파라미터 표에" 로 prefix가 달라 verbatim 일치하지 않았음. 2) list.json 표 헤더 문구를 "공식 가이드 표를 그대로 옮긴 것"에서 "공식 가이드 요청 인자 정리 (필수여부·기본값·허용값은 공식 표 기준, 식별자는 코드 폰트로 표기)"로 약화. 마크다운 backtick 등 포매팅 차이가 "1:1 mirror" 약속과 모순되지 않게 정확히 표현. --------- Co-authored-by: hon2be <hon2be> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Jeffrey (Dongkyu) Kim <vkehfdl1@gmail.com> |
||
|
|
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. |
||
|
|
4c7877a5c9 |
Add naver-news-search skill and /v1/naver-news/search proxy route
Closes #143. Proxies the official Naver Search Open API news endpoint (openapi.naver.com/v1/search/news.json) through k-skill-proxy so users do not need to issue their own Naver Client ID/Secret. Reuses the existing NAVER_SEARCH_CLIENT_ID/NAVER_SEARCH_CLIENT_SECRET that naver-shopping already consumes, since the Naver Developer application enables the 'Search' scope covering both news and shopping. Implementation details: - src/naver-news.js normalizes q/display/start/sort, builds the official URL, calls upstream with X-Naver-Client-Id/Secret headers, and parses the JSON response into rank/title/description/link/original_link/pub_date items. - Strips <b> highlight tags and decodes HTML entities in title/description using zero-width replacement so compound Korean words like '주식형' are preserved (not split into '주식 형'). - Parses RFC822 pubDate into pub_date_iso (ISO-8601 UTC) for clients. - Deduplicates items by normalized link; drops entries missing title/link. - Returns 503 upstream_not_configured when proxy keys are absent (no public BFF fallback exists for news like it does for shopping, so keys are required). - Failure responses are not cached (failure-aware cache layer). - Exposes naverNewsApiConfigured on /health. 14 new tests in test/naver-news.test.js cover query validation, URL building, payload normalization (HTML stripping, entity decoding, deduplication, missing-field tolerance), plus Fastify integration tests for 200/400/401/429/500/503 paths, cache hit/miss, header wiring, and the health flag. |
||
|
|
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. |
||
|
|
e1656541a4 |
Fix parking lot lookups: force HTTPS, cache full dataset, normalize provider fields (#156)
Data.go.kr 이 tn_pubr_prkplce_info_api 를 HTTPS 로만 서비스하고 HTTP 요청은 301 로 리다이렉트하기 때문에 Node fetch 가 `response.ok=false` 로 떨어져 기능이 전체 실패하고 있었다. 이 커밋은 HTTPS 로 직접 호출하도록 수정하면서, 업스트림의 주소/지역 필터가 실제로는 동작하지 않고 페이지당 응답이 1000rows 기준 26s 에 달해 20s fetch timeout 에 꾸준히 걸리던 문제까지 함께 해결한다. ## What changed - packages/k-skill-proxy/src/parking-lots.js - PARKING_LOT_API_URL 을 `http://` → `https://` 로 고정 (root cause). - 업스트림 address/geo 필터가 신뢰 불가하므로 full-dataset 을 한 번 로드해 프로세스 메모리에 6시간 TTL 로 캐시하고, 동시 호출자는 in-flight promise 를 공유하도록 한다. nearby 쿼리는 캐시된 행을 좌표 거리로 필터링해 서비스한다. - DATASET_PAGE_SIZE=300, fetch timeout 30s 로 페이지당 응답이 20s 를 넘기지 않도록 맞췄다. - packages/k-skill-proxy/src/server.js - 더 이상 의미 없어진 numOfRows / maxPages 쿼리 파라미터를 라우트에서 제거하고, 응답 payload 의 query echo 도 정리했다. - packages/k-skill-proxy/test/server.test.js - 새 캐시 기반 동작을 검증하는 테스트로 교체: (1) full dataset load + 좌표 필터 + 프록시 응답 캐시 재사용, (2) public_only 기본값 및 해제 시 동작, (3) 좌표 검증 실패 400, (4) 업스트림 키 미설정 시 503. - packages/parking-lot-search/src/index.js - OFFICIAL_API_URL 도 HTTPS 로 맞춰 직접 호출 모드 사용자도 같은 버그를 밟지 않게 한다. - packages/parking-lot-search/src/parse.js - 업스트림이 `insttCode` / `insttNm` (camelCase) 를 돌려주는데 parser 가 snake_case (`instt_code`, `instt_nm`) 만 인식해 providerCode/providerName 이 비어 있던 문제를 수정. - packages/parking-lot-search/test/* 및 fixtures - HTTPS URL 매칭으로 업데이트하고, insttCode/insttNm 회귀 테스트를 fixture/assertion 에 추가. - docs/features/parking-lot-search.md, parking-lot-search/SKILL.md, packages/parking-lot-search/README.md - 공식 endpoint 표기를 HTTPS 로 통일. - .changeset/parking-lot-https-fix.md - parking-lot-search 패키지 patch 릴리즈 노트 추가. ## How it was verified - `npm run ci` (lint + typecheck + tests + pack:dry-run) 통과. - 로컬에서 실제 `DATA_GO_KR_API_KEY` 로 k-skill-proxy 를 기동해 live 호출 검증: - 광화문 (37.573713, 126.978338) cold cache: 30s 내 전체 18,868 rows 로드, 2km 내 47개 공영주차장 반환 (세종로 414m, 서린노외 456m 등). - 강남역 (37.497952, 127.027621) warm cache: 31ms 응답, 1.5km 내 13개 반환 (역삼문화공원 380m, 역삼푸른솔도서관 421m 등). - 업스트림 직접 HTTPS 호출로 `resultCode=00 NORMAL_SERVICE` 정상 동작 확인. |
||
|
|
c002561f34 |
Sync dev → main: MFDS proxy fixes, cache hardening, HWP kordoc, KRX degraded handling + new skills (#152)
* 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 * 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 * Pin the Hola Poke MCP contract in repo-owned regression fixtures The earlier issue #120 regression only matched prose, so this follow-up records the verified remote MCP tool/result snapshot in a checked-in fixture and makes both docs surfaces byte-align to it. That keeps the discoverability docs honest while turning the review claim into a real contract lock for tools/list, get_menu, get_shop_info, and the invalid-phone event flow. Constraint: The upstream remote MCP server can change independently of this repo Rejected: Keep prose-only regex checks | would not catch contract drift Confidence: high Scope-risk: narrow Reversibility: clean Directive: Refresh the fixture, both JSON fences, and the live-smoke evidence together whenever the upstream contract changes Tested: node --test scripts/skill-docs.test.js --test-name-pattern='hola-poke-yeoksam'; npm run ci; live MCP smoke check against https://hola-poke-yeoksam-skill.onrender.com/mcp (initialize, tools/list, get_menu, get_shop_info, invalid enter_event) Not-tested: Successful enter_event with a real phone number (intentionally avoided to prevent live event participation) * Keep nearby restroom lookups resilient to flaky Kakao place panels The review caught two regressions in the new public-restroom-nearby package: a single broken Kakao panel aborted anchor resolution, and coordinate search dropped maxDistanceMeters before normalization. This change adds targeted regression coverage first, keeps per-candidate HTTP failures recoverable, and hardens request errors with explicit status/url metadata so fallback logic no longer depends on parsing error strings. Constraint: Must preserve the published package surface and keep the fix scoped to PR #123 follow-up Rejected: Swallow all panel errors | would hide non-HTTP failures like network faults Rejected: Parse request error messages for status codes | brittle coupling to string formatting Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep recoverable Kakao panel handling aligned with request() error annotations if request() changes again Tested: npm test --workspace public-restroom-nearby Tested: npm run ci Tested: live smoke searchNearbyPublicRestroomsByLocationQuery('광화문', { limit: 3 }) Tested: LSP diagnostics on packages/public-restroom-nearby/src/index.js and test/index.test.js Not-tested: Live Kakao fallback against a real upstream 5xx place-panel response * Keep the Hola Poke contract claims aligned with verified coverage The reviewed fixture-based regression already locks the documented remote snapshot, but the docs still implied the enter_event success path had live proof. Narrow the docs and the regression so they explicitly say the success fields are pinned by the recorded snapshot while the live smoke only verifies the invalid-phone retry path. Constraint: Live success-path verification would trigger a real event entry and is intentionally avoided Rejected: Leave the broader wording in place | review feedback showed it overstated the live evidence Confidence: high Scope-risk: narrow Reversibility: clean Directive: If a safe non-mutating success-path probe becomes available, update the docs and fixture wording together Tested: node --test scripts/skill-docs.test.js --test-name-pattern='hola-poke-yeoksam'; npm run ci; live MCP smoke against https://hola-poke-yeoksam-skill.onrender.com/mcp (initialize, tools/list, get_menu subset, get_shop_info subset, invalid enter_event) Not-tested: Real enter_event success-path invocation * Document the restroom distance-cap contract with regression coverage The approved issue-117 code fix already restored maxDistanceMeters behavior, but the published docs did not lock or explain that contract. This follow-up adds a failing-first doc regression, then updates the feature guide and package README with the verified 100m example so users and future reviewers see the same behavior the package now ships. Constraint: Must stay scoped to the existing PR #123 follow-up without reopening the implementation surface Rejected: Leave the behavior implicit in code/tests only | published docs would lag the verified contract Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep the public-restroom-nearby docs and skill-docs regression aligned with live maxDistanceMeters smoke evidence if the sample query changes Tested: node --test scripts/skill-docs.test.js (red then green) Tested: npm test --workspace public-restroom-nearby Tested: npm run ci Tested: live smoke searchNearbyPublicRestroomsByLocationQuery('광화문', { limit: 3 }) Tested: live smoke searchNearbyPublicRestroomsByLocationQuery('광화문', { limit: 3, maxDistanceMeters: 100 }) Tested: architect review APPROVED Not-tested: Alternative landmark queries with a non-zero maxDistanceMeters hit set * Expose KRX partial failures instead of misreporting stock lookups The Korean stock proxy used to silently drop failed market snapshots during search and could turn an empty holiday trade snapshot into a 502 by falling back into base-info lookup. This change surfaces degraded market metadata on partial search success, short-circuits empty trade snapshots to not_found, and refreshes the user docs to use a real trading day in examples. Constraint: KOSPI base-info approval is granted separately from other KRX routes Constraint: Healthy markets should still return usable search results during a partial outage Rejected: Return 502 on every partial search failure | hides still-usable markets and breaks current clients unnecessarily Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep degraded search metadata when any market snapshot fetch fails so partial outages stay visible Tested: npm test --workspace k-skill-proxy Tested: node --test scripts/skill-docs.test.js Tested: npm run ci Not-tested: Live KOSPI base-info behavior after the new KRX permission is approved * Adopt kordoc for the hwp skill workflow Issue #119 replaces the previous HWP guidance with kordoc so the skill matches the newer agent-native document flow. The docs and regression tests now center the HWP skill on kordoc parsing, JSON extraction, diffing, form filling, and Markdown-to-HWPX round-tripping, while the install/source references stay in sync. Constraint: The repository treats skill behavior as documentation contracts backed by regression tests Constraint: The requested branch/PR flow must target dev with TDD and verified execution evidence Rejected: Keep @ohah/hwpjs or hwp-mcp as fallback guidance | issue #119 explicitly approves replacing the prior stack with kordoc Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep future hwp skill/docs/tests aligned to a single kordoc-first contract unless a new issue explicitly reintroduces multi-backend routing Tested: node --test scripts/skill-docs.test.js; npm run ci; temp-dir kordoc roundtrip via markdownToHwpx -> sample.hwpx -> kordoc CLI markdown output; architect review APPROVED Not-tested: Live parsing of user-provided proprietary HWP/HWPX samples outside the generated roundtrip fixture * Prevent degraded stock search outages from sticking in cache Reviewer feedback showed that partial KRX market failures could be cached as full search answers, masking recovery on the next identical request. This change adds a regression that fails first, skips route-level caching for degraded search payloads, and keeps the trade-info empty-snapshot contract documented alongside the partial-failure response semantics. Constraint: Existing PR #124 already targets dev and must remain the follow-up lane for issue #99 Constraint: Proxy behavior must stay read-only and dependency-free Rejected: Cache degraded search payloads for a short TTL | still risks transient false negatives during the TTL window Rejected: Broaden trade-info fallback behavior | empty snapshots should stay explicit not_found results Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep degraded search responses out of the long-lived route cache unless a future design adds explicit revalidation semantics Tested: npm test --workspace k-skill-proxy; node --test scripts/skill-docs.test.js; npm run ci; explicit buildServer degraded-search recovery repro Not-tested: Live KRX production endpoints from this branch * Align HWP docs with the published kordoc surface The issue #119 follow-up needs the repository contract to match what the currently published kordoc package actually supports. This narrows the HWP skill/docs/tests to the verified install requirement and supported CLI/Node API surfaces, and removes unsupported fill/mcp claims. Constraint: Published kordoc CLI fails at startup without pdfjs-dist Constraint: Docs/tests must reflect the current npm package behavior, not intended future features Rejected: Keep fill/mcp examples with caveats | still documents unsupported entrypoints Confidence: high Scope-risk: narrow Directive: Reintroduce fill/mcp docs only after verifying the published package exposes them in both CLI and Node API Tested: node --test scripts/skill-docs.test.js; npm run ci; temp-dir clean install smoke; temp-dir kordoc+pdfjs-dist watch/parse/extractFormFields/compare/markdownToHwpx/roundtrip smoke; Claude architect review Not-tested: Real-world HWPX template that produces non-empty extractFormFields output * Keep HWP docs runnable against the published kordoc package The follow-up closes the last runnable-contract gaps from review by documenting the working one-shot npx form and separating Node API examples into a local project install path. The regression suite now locks both install notes so future edits do not drift back to broken command shapes. Constraint: Published kordoc CLI still requires pdfjs-dist at startup Constraint: Global NODE_PATH does not make ESM imports from kordoc resolvable in the documented examples Rejected: Keep bare `npx kordoc` examples | fails in a clean environment Rejected: Keep global-install Node API guidance | ESM import remains unresolved Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep HWP docs aligned to verified published kordoc surfaces until the package contract changes upstream Tested: node --test scripts/skill-docs.test.js Tested: npm run ci Tested: temp-dir local npm install kordoc pdfjs-dist plus markdownToHwpx -> sample.hwpx -> one-shot kordoc roundtrip smoke Not-tested: upstream unpublished kordoc features beyond the verified CLI and Node API surfaces * 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> * Feature/#121 (#127) * Recover KakaoTalk mac skill auth when upstream user_id detection fails Issue #121 reproduces on a real MacBook because `kakaocli auth` can fail even when the encrypted hex-named DB exists. This change adds a thin repo-owned helper that recovers the active user_id from plist revision hashes, caches the validated DB/key tuple, and reuses it for read-only `kakaocli` commands. The skill and feature docs now steer users to the helper when upstream auto-detection stops at candidate key mismatch, and regression tests lock the recovery flow before the implementation. Constraint: Must stay a thin adapter around upstream kakaocli rather than forking the CLI Constraint: Must verify on a real local macOS KakaoTalk install where issue #121 reproduces Rejected: Full kakaocli reimplementation inside k-skill | too broad for the user_id/key-derivation failure scope Rejected: Docs-only workaround | does not actually fix the broken auth path for users Confidence: high Scope-risk: moderate Reversibility: clean Directive: Keep this helper limited to auth/key recovery and read-only passthrough unless upstream gaps widen materially Tested: python3 -m unittest scripts.test_kakaotalk_mac Tested: node --test scripts/skill-docs.test.js Tested: npm run ci Tested: python3 scripts/kakaotalk_mac.py auth --refresh --max-user-id 800000000 --workers 8 --chunk-size 2000000 Tested: python3 scripts/kakaotalk_mac.py chats --limit 1 --json Not-tested: Other kakaocli subcommands beyond auth/chats/messages/search/query/schema * Protect the KakaoTalk helper's safe recovery path Address the PR follow-up by treating malformed auth cache files as cache misses, removing write-capable passthrough from the wrapper surface, and redacting human-readable auth output so the cached SQLCipher key is not echoed back into terminal history. The docs and regression suite now describe and enforce the read-only contract that the helper is meant to preserve. Constraint: Helper must remain a read-only recovery wrapper around local kakaocli access Rejected: Keep query support with SQL validation | still leaves a risky write-capable escape hatch Confidence: high Scope-risk: narrow Reversibility: clean Directive: Do not re-expose arbitrary SQL passthrough or print the SQLCipher key in default text output Tested: python3 -m unittest scripts.test_kakaotalk_mac; node --test scripts/skill-docs.test.js; npm run ci; python3 scripts/kakaotalk_mac.py auth --refresh --max-user-id 800000000 --workers 8 --chunk-size 2000000; python3 scripts/kakaotalk_mac.py chats --limit 1 --json; python3 scripts/kakaotalk_mac.py auth --cache-path <bad-json>; python3 scripts/kakaotalk_mac.py query --help Not-tested: External automation consumers that depend on shell/json auth output beyond the documented helper flows * Lock the helper CLI surface against accidental regressions The approved issue #121 fixes already hardened the KakaoTalk Mac helper, but the test suite still only exercised the passthrough validator directly. Add an explicit parser-level regression so the public CLI contract stays read-only and `query` cannot quietly reappear in future edits. Constraint: Follow-up is on the existing feature/#121 PR branch and must stay minimal Rejected: Re-open helper implementation changes | current code already satisfies the approved review findings Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep parser exposure tests aligned with READ_ONLY_COMMANDS whenever helper subcommands change Tested: python3 -m unittest scripts.test_kakaotalk_mac; node --test scripts/skill-docs.test.js; npm run ci; python3 scripts/kakaotalk_mac.py auth --refresh --max-user-id 800000000 --workers 8 --chunk-size 2000000; python3 scripts/kakaotalk_mac.py chats --limit 1 --json; python3 scripts/kakaotalk_mac.py auth --cache-path <bad-json> Not-tested: No new production code paths changed in this follow-up * Honor explicit Kakao auth recovery overrides The helper now treats manual auth overrides as a cache-bypassing recovery request and rejects invalid brute-force tuning flags at the CLI boundary so users get deterministic behavior instead of stale cached tuples or Python tracebacks. Regression coverage locks both paths before the PR follow-up lands. Constraint: The helper must remain a thin read-only wrapper around kakaocli auth recovery Rejected: Require --refresh whenever --user-id/--uuid is passed | worse UX than honoring overrides directly Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep explicit auth overrides ahead of cache reuse unless the CLI contract is redesigned and documented Tested: python3 -m unittest scripts.test_kakaotalk_mac; node --test scripts/skill-docs.test.js; npm run ci; python3 scripts/kakaotalk_mac.py auth --refresh --max-user-id 800000000 --workers 8 --chunk-size 2000000; python3 scripts/kakaotalk_mac.py chats --limit 1 --json; python3 scripts/kakaotalk_mac.py auth --cache-path <bad-json>; python3 scripts/kakaotalk_mac.py auth --refresh --max-user-id -1; python3 scripts/kakaotalk_mac.py auth --refresh --workers 2 --chunk-size 0 --max-user-id 10; python3 scripts/kakaotalk_mac.py auth --cache-path <temp-cache> --user-id 999; python3 scripts/kakaotalk_mac.py auth --cache-path <temp-cache> --uuid <live-uuid> Not-tested: Manual override success with a truly alternate valid user_id/uuid pair on a multi-account local install * 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 * Add Naver Shopping price comparison skill * Use Naver Shopping BFF fallback * Fix naver shopping BFF page and sort fallback * Clarify Naver OpenAPI review sort fallback * Add library book search skill * Add Data4Library route regression coverage * Fix Data4Library book-exists ISBN-10 handling * Refactor Coupang skill to retention MCP layer * Add Coupang MCP wrapper follow-up coverage * Clarify Coupang wrapper init guidance * Document Coupang MCP init examples * Add parking lot search skill * Add korean-privacy-terms skill regression tests * Add korean-privacy-terms thin-wrapper skill * Document korean-privacy-terms skill across repo docs * Bundle Apache-2.0 LICENSE with korean-privacy-terms wrapper Addresses PR #149 review SHOULD FIX: ship the Apache-2.0 LICENSE text alongside the thin wrapper so Apache License 2.0 §4(a) ('give any other recipients of the Work or Derivative Works a copy of this License') is satisfied even before `install.sh` fetches the upstream payload. - Copy upstream LICENSE verbatim to `korean-privacy-terms/LICENSE.upstream` (byte-for-byte identical to upstream at pinned SHA e390f7b9feb825e368c26726363ea5ce11a34083; SHA256 35ef947614c2f14df01c5fc553f987f644f0c9f6b011adda397bd788a87f1510). - Update SKILL.md Notes to link LICENSE.upstream, clarify that repo-root LICENSE (MIT) is k-skill's own license not this skill's, and document that nested upstream SKILL.md is not discovered by agent platforms. - Document the home-path `bash ~/.claude/skills/.../install.sh` variant in SKILL.md so users who pulled the wrapper via `npx skills add --skill` can install without a repo checkout (installer already resolves ${BASH_SOURCE[0]} absolutely). - Update docs/features/korean-privacy-terms.md to document LICENSE.upstream and the §4(a) rationale. - Strengthen skill-docs regression tests (NICE TO HAVE items from review): * Reject placeholder pins (all-zero / all-f 40-char strings). * Assert the literal upstream clone URL (https://github.com/kimlawtech/korean-privacy-terms.git). * Assert `git clone --filter=blob:none` is used for blobless fetches. * Add new regression test that verifies LICENSE.upstream exists, matches the Apache-2.0 preamble / §4 / APPENDIX structure, and is referenced from both SKILL.md and the feature doc. * Assert APPENDIX anchor in korean-privacy-terms LICENSE.upstream Close Round 3 NICE TO HAVE from PR #149. The LICENSE.upstream regression block asserted preamble, Version 2.0, Redistribution, END OF TERMS, and Copyright 2026 kimlawtech but not the APPENDIX anchor at LICENSE.upstream:179, even though the Round 1 follow-up and Round 2 review collectively described 'APPENDIX structure verification'. Adding this one assertion closes that claim/test parity gap and acts as tamper-detection if upstream reformats LICENSE later. Verified with TDD: temporarily stripped APPENDIX line from LICENSE.upstream, confirmed test 108 FAILS with the expected regex mismatch, then restored and re-confirmed 109/109 GREEN. Byte-for-byte identity with upstream LICENSE still holds (SHA256 35ef947614c2f14df01c5fc553f987f644f0c9f6b011adda397bd788a87f1510). npm run ci exit 0 with 357 ok subtests (unchanged baseline, additive assertion within existing test block). * Fix extractDataGoItems to handle current data.go.kr JSON shapes The MFDS data.go.kr drug and food endpoints now return body.items as a flat array (DrbEasyDrugInfoService, SafeStadDrugService) or an array of {item: {...}} wrappers (PrsecImproptFoodInfoService03), instead of the legacy {items: {item: [...]}} XML→JSON auto-convert shape. Our extractDataGoItems was still looking for body.items.item, so it returned [] for every entry, silently breaking: - /v1/mfds/drug-safety/lookup - /v1/mfds/food-safety/search (improperFood portion) Update extractDataGoItems to accept all three shapes and refresh the mock fixtures in server.test.js to match what upstream actually returns, while adding a backward-compat test for the legacy shape. Note: this does not resolve the remaining FOODSAFETYKOREA_API_KEY being rejected by upstream (issue #148 core symptom) - that is a separate operational key rotation on the proxy server. * Make proxy cache failure-aware and require route-prefixed cache keys Two related issues surfaced while investigating issue #148: 1. Transient upstream failures were being cached for the full 5-minute TTL because every route handler called cache.set() unconditionally with whatever payload came back - including empty items + warnings from a flaky upstream like openapi.foodsafetykorea.go.kr. The user would then see "empty + warning" for 5 minutes even after upstream recovered. 2. makeCacheKey(payload) hashes the whole payload, but fine-dust/report was the only route calling it without a "route" prefix (makeCacheKey(normalized) instead of makeCacheKey({ route: "fine-dust-report", ...normalized })). Different routes with the same normalized shape could collide. Fix both globally in the cache layer so every current and future route benefits without per-route edits: - createMemoryCache.set rejects any payload that isFailureResponse considers a failure (explicit error field, upstream.degraded flag, or empty items alongside warnings). Returns false on reject, true on accept, so callers can observe the decision if needed. - makeCacheKey now throws if payload.route is missing or empty. This catches the fine-dust inconsistency and prevents new routes from reintroducing it. - fine-dust/report now passes `route: "fine-dust-report"` like every other route. New tests: - makeCacheKey asserts distinct routes produce distinct keys and throws without a route. - isFailureResponse covers all failure signatures plus graceful- fallback cases (items present alongside warnings) that must stay cacheable. - createMemoryCache.set refuses each failure shape and still stores healthy payloads. - End-to-end: food-safety/search with a flaky recall upstream serves the upstream failure, retries live when upstream recovers, and only caches once the payload is healthy. TTL itself is unchanged - the value still protects upstream rate limits; it just no longer amplifies transient errors. * Document Coupang hosted fallback contract and affiliate disclosure retention-corp/coupang_partners#1 is merged, so upstream now transparently falls back to the Retention Corp hosted backend at https://a.retn.kr/v1/public/assist when Coupang Partners API credentials are missing. The k-skill wrapper already passes environment variables through unchanged, so this commit lines up the documented contract with the actual two-path behavior without changing runtime logic. - SKILL.md and docs/features/coupang-product-search.md describe both execution paths (operator local HMAC vs credentialless hosted fallback), the honored OPENCLAW_SHOPPING_* env vars, the allowlist client-id convention including the k-skill-specific coupang-mcp-fallback value, and the mandatory affiliate disclosure when a.retn.kr/s/ shortlinks or lptag=AF deeplinks appear in responses. - docs/sources.md adds the hosted assist endpoint and the merged upstream PR so the source surface stays truthful. - README.md reflects the 선택사항 semantics for the 쿠팡 상품 검색 row and extends the column legend so 선택사항 is distinct from 불필요. - coupang_partners_mcp.py expands its --help epilog so operators discover the honored upstream env vars without reading the wrapper source; no runtime behavior change. - scripts/test_coupang_partners_mcp_wrapper.py locks env pass-through as a regression, asserts the new --help contract, and adds an opt-in K_SKILL_COUPANG_SMOKE=1 live smoke test that verifies the credentialless hosted path returns a Coupang deeplink. - scripts/skill-docs.test.js extends the docs regression to require the hosted assist URL, OPENCLAW_SHOPPING_* env prefix, affiliate disclosure wording, and hosted fallback concept while keeping the yuju777 HF Space negative assertion. Verified: npm run ci exits 0, live smoke test (K_SKILL_COUPANG_SMOKE=1) returns a.retn.kr/s/ shortlinks via credentialless wrapper, and manual env -u COUPANG_ACCESS_KEY -u COUPANG_SECRET_KEY call returns isRocket+lptag=AF3727577 responses through the hosted fallback. Refs: #134 * Drop non-allowlisted coupang-mcp-fallback recommendation from hosted fallback docs Direct probes against https://a.retn.kr/v1/public/assist confirmed that X-OpenClaw-Client-Id: coupang-mcp-fallback returns HTTP 403 Client is not allowlisted, while the upstream default openclaw-skill returns HTTP 200. The default wrapper path already works because upstream falls back to openclaw-skill, but the explicit recommendation in SKILL.md and the feature doc was luring users to a 403 path. Remove the dead recommendation and lock in the working configuration: - Docs describe openclaw-skill as the upstream-allowlisted default and note that k-skill does not override OPENCLAW_SHOPPING_CLIENT_ID. - Wrapper --help epilog drops the Suggested k-skill value line and documents openclaw-skill as the allowlist value in play. - New skill-docs regression asserts coupang-mcp-fallback is absent from SKILL.md, the feature doc, the wrapper, and docs/sources.md while openclaw-skill is documented across all three narrative surfaces. - New Python wrapper regression asserts --help drops the dead value and surfaces openclaw-skill so the constraint stays locked. - Existing env-forwarding test uses openclaw-skill as the pass-through sentinel so the repo no longer ships the non-allowlisted string at all. --------- Co-authored-by: minsing-jin <ironman0722@naver.com> |
||
|
|
83263c564f |
Drop non-allowlisted coupang-mcp-fallback recommendation from hosted fallback docs
Direct probes against https://a.retn.kr/v1/public/assist confirmed that X-OpenClaw-Client-Id: coupang-mcp-fallback returns HTTP 403 Client is not allowlisted, while the upstream default openclaw-skill returns HTTP 200. The default wrapper path already works because upstream falls back to openclaw-skill, but the explicit recommendation in SKILL.md and the feature doc was luring users to a 403 path. Remove the dead recommendation and lock in the working configuration: - Docs describe openclaw-skill as the upstream-allowlisted default and note that k-skill does not override OPENCLAW_SHOPPING_CLIENT_ID. - Wrapper --help epilog drops the Suggested k-skill value line and documents openclaw-skill as the allowlist value in play. - New skill-docs regression asserts coupang-mcp-fallback is absent from SKILL.md, the feature doc, the wrapper, and docs/sources.md while openclaw-skill is documented across all three narrative surfaces. - New Python wrapper regression asserts --help drops the dead value and surfaces openclaw-skill so the constraint stays locked. - Existing env-forwarding test uses openclaw-skill as the pass-through sentinel so the repo no longer ships the non-allowlisted string at all. |
||
|
|
f2204f752e |
Document Coupang hosted fallback contract and affiliate disclosure
retention-corp/coupang_partners#1 is merged, so upstream now transparently falls back to the Retention Corp hosted backend at https://a.retn.kr/v1/public/assist when Coupang Partners API credentials are missing. The k-skill wrapper already passes environment variables through unchanged, so this commit lines up the documented contract with the actual two-path behavior without changing runtime logic. - SKILL.md and docs/features/coupang-product-search.md describe both execution paths (operator local HMAC vs credentialless hosted fallback), the honored OPENCLAW_SHOPPING_* env vars, the allowlist client-id convention including the k-skill-specific coupang-mcp-fallback value, and the mandatory affiliate disclosure when a.retn.kr/s/ shortlinks or lptag=AF deeplinks appear in responses. - docs/sources.md adds the hosted assist endpoint and the merged upstream PR so the source surface stays truthful. - README.md reflects the 선택사항 semantics for the 쿠팡 상품 검색 row and extends the column legend so 선택사항 is distinct from 불필요. - coupang_partners_mcp.py expands its --help epilog so operators discover the honored upstream env vars without reading the wrapper source; no runtime behavior change. - scripts/test_coupang_partners_mcp_wrapper.py locks env pass-through as a regression, asserts the new --help contract, and adds an opt-in K_SKILL_COUPANG_SMOKE=1 live smoke test that verifies the credentialless hosted path returns a Coupang deeplink. - scripts/skill-docs.test.js extends the docs regression to require the hosted assist URL, OPENCLAW_SHOPPING_* env prefix, affiliate disclosure wording, and hosted fallback concept while keeping the yuju777 HF Space negative assertion. Verified: npm run ci exits 0, live smoke test (K_SKILL_COUPANG_SMOKE=1) returns a.retn.kr/s/ shortlinks via credentialless wrapper, and manual env -u COUPANG_ACCESS_KEY -u COUPANG_SECRET_KEY call returns isRocket+lptag=AF3727577 responses through the hosted fallback. Refs: #134 |
||
|
|
bf07c25a43 |
Bundle Apache-2.0 LICENSE with korean-privacy-terms wrapper
Addresses PR #149 review SHOULD FIX: ship the Apache-2.0 LICENSE text alongside the thin wrapper so Apache License 2.0 §4(a) ('give any other recipients of the Work or Derivative Works a copy of this License') is satisfied even before `install.sh` fetches the upstream payload. - Copy upstream LICENSE verbatim to `korean-privacy-terms/LICENSE.upstream` (byte-for-byte identical to upstream at pinned SHA e390f7b9feb825e368c26726363ea5ce11a34083; SHA256 35ef947614c2f14df01c5fc553f987f644f0c9f6b011adda397bd788a87f1510). - Update SKILL.md Notes to link LICENSE.upstream, clarify that repo-root LICENSE (MIT) is k-skill's own license not this skill's, and document that nested upstream SKILL.md is not discovered by agent platforms. - Document the home-path `bash ~/.claude/skills/.../install.sh` variant in SKILL.md so users who pulled the wrapper via `npx skills add --skill` can install without a repo checkout (installer already resolves ${BASH_SOURCE[0]} absolutely). - Update docs/features/korean-privacy-terms.md to document LICENSE.upstream and the §4(a) rationale. - Strengthen skill-docs regression tests (NICE TO HAVE items from review): * Reject placeholder pins (all-zero / all-f 40-char strings). * Assert the literal upstream clone URL (https://github.com/kimlawtech/korean-privacy-terms.git). * Assert `git clone --filter=blob:none` is used for blobless fetches. * Add new regression test that verifies LICENSE.upstream exists, matches the Apache-2.0 preamble / §4 / APPENDIX structure, and is referenced from both SKILL.md and the feature doc. |
||
|
|
d0c014e38b | Document korean-privacy-terms skill across repo docs |