mirror of
https://github.com/NomaDamas/k-skill.git
synced 2026-09-14 16:37:18 +08:00
2ff51db5d2
* 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>
gongsijiga-search
대한민국 국토교통부 부동산공시가격알리미(realtyprice.kr)의 공개 API를 호출해 지번 단위 개별공시지가(원/㎡)를 조회하는 Node.js 패키지입니다. 다년도 추이와 전년 대비 변동률을 정규화된 JSON으로 돌려줍니다.
Note
realtyprice.kr는 API 키가 필요 없는 완전 공개 엔드포인트이므로 이 패키지는k-skill-proxy를 경유하지 않고 사용자 머신에서 직접 upstream을 호출합니다. (참고: 저장소의 k-skill-proxy inclusion rule — 프록시는 API 키가 필요한 upstream만 다룹니다.)
설치
배포 후:
npm install gongsijiga-search
이 저장소에서 개발할 때:
npm install
사용 예시
const { lookupGongsijiga } = require("gongsijiga-search");
async function main() {
const result = await lookupGongsijiga("서울특별시 강남구 역삼동 736");
console.log(result.latest); // { year, price_per_sqm, notice_date, base_date }
console.log(result.history); // [{ year, price_per_sqm, notice_date }, ...] (descending)
console.log(result.yoy_change_pct); // 전년 대비 % (소수점 둘째 자리 반올림)
}
main().catch((err) => {
console.error(err.code, err.message);
process.exitCode = 1;
});
입력 주소 형식
<시도> <시군구> <읍면동…> [산] <본번[-부번]> 형태의 한국어 지번 주소.
- 시도: 17개 광역자치단체 풀네임/약칭 모두 지원 (예:
서울특별시/서울) - 세종특별자치시는 시군구가 없으므로
세종 <읍면동> <지번>형식 - 산 지번은
산 1-2또는산1-2 - 본번은 4자리 이하 숫자, 부번은
-뒤에 옴
예: 서울 강남구 역삼동 736, 전남 무안군 청계면 청천리 산 1-2, 세종 어진동 575.
응답 모양
{
"address": "서울특별시 강남구 역삼동 736",
"jibun": "736번지",
"san": false,
"latest": {
"year": 2026,
"price_per_sqm": 72340000,
"notice_date": "2026-04-30",
"base_date": "2026-01-01"
},
"history": [
{ "year": 2026, "price_per_sqm": 72340000, "notice_date": "2026-04-30" },
{ "year": 2025, "price_per_sqm": 68600000, "notice_date": "2025-04-30" }
],
"yoy_change_pct": 5.45,
"source_url": "https://www.realtyprice.kr/notice/gsindividual/search.htm"
}
에러 코드
error.code |
의미 | statusCode |
|---|---|---|
ADDRESS_PARSE_FAILED |
주소 파싱 실패 / 미인식 시도 / 토큰 부족 | 400 |
INVALID_BUNJI |
본번이 비숫자 또는 4자리 초과 | 400 |
REGION_NOT_FOUND |
시군구/읍면동 매칭 실패 (err.candidates 후보 최대 3개) |
404 |
LAND_NOT_FOUND |
해당 지번이 공시지가에 등재되지 않음 | 404 |
UPSTREAM_ERROR |
realtyprice.kr 비정상 HTTP 응답 | 502 |
UPSTREAM_TIMEOUT |
30초 타임아웃 | 504 |
공개 API
lookupGongsijiga(addressRaw, fetchFn?)— 주소 → 정규화된 응답parseAddress(rawAddress)— 주소 파서 (지번/산/세종 처리)parseSido(text)— 시도명 → 2자리 코드normalizeSearchResult(raw)— gsiList 항목 →{ year, price_per_sqm, notice_date }buildResponse({ address, jibun, san, history })— 최종 응답 합성fetchSigunguList,fetchEupmyeondongList,fetchGsiSearchList— 단계별 upstream 호출fetchWithTimeout(url, opts, timeoutMs?, fetchFn?)— AbortController 기반 타임아웃createCache()— 단순 in-memory TTL 캐시 (Map 백엔드)SIDO_MAP,REALTYPRICE_BASE_URL,REFERER,makeError
Notes
- 공시지가 ≠ 시세. 시세는 통상 공시지가의 1.5~3배.
- 매년 1월 1일 기준, 4
5월 발표. 14월에는 전년도가 최신. realtyprice.kr호출에는 별도Referer헤더가 필요하며, 이 패키지가 자동 처리합니다.