Reserve used to replay search results and trust a fresh ordinal index, which could silently target a different train when sold-out entries disappeared or ordering changed. This change emits a stable train_id from search output, requires reserve to match the exact train identity on replay, and updates docs/tests to lock the safer CLI contract.
Constraint: Korail search results can reorder between search and reserve while the helper still needs to replay the live lookup
Rejected: Keep --train-index as the reserve selector | still allows silent wrong-train bookings when the result set shifts
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If upstream train identity fields change, update the train_id payload and the docs/tests together before changing reserve selection again
Tested: python3 -m py_compile scripts/ktx_booking.py; python3 -m unittest discover -s scripts -p test_ktx_booking.py; node --test scripts/skill-docs.test.js; npm run ci; live search/reservations/reserve/cancel/reservations with sops-managed Korail credentials
Not-tested: Forced live stale-train_id failure against a disappearing train between search and reserve
The feature branch already restored the patched Korail helper, so this follow-up stays narrow: lock the documented helper flags in regression tests and teach both KTX docs surfaces about the search and waiting-list toggles the live CLI already supports.
Constraint: Follow-up had to stay compatible with the shipped scripts/ktx_booking.py parser and existing PR scope
Rejected: Expand README into a full command matrix | duplicates the dedicated KTX docs and skill guide
Confidence: high
Scope-risk: narrow
Directive: When the helper CLI changes, update both KTX docs surfaces and the regression assertions in the same change
Tested: node --test scripts/skill-docs.test.js
Tested: python3 -m py_compile scripts/ktx_booking.py
Tested: npm run ci
Tested: live python3 scripts/ktx_booking.py search/reservations/reserve/cancel via sops-managed Korail credentials
Not-tested: 예약대기 success path on a sold-out train
Korail's current mobile endpoints reject the published raw korail2
examples with MACRO ERROR, so this change adds a repo-local
helper that patches Dynapath token/Sid/version behavior and reroutes
KTX docs/tests to the helper-based flow.
Constraint: Must keep credentials in sops-managed secrets and prove the flow with a real reservation
Rejected: Fork and publish a patched korail2 package | broader release surface than this repo needs
Confidence: high
Scope-risk: moderate
Directive: Re-check the helper constants and private korail2 hooks whenever Korail changes its mobile anti-bot flow
Tested: python3 -m py_compile scripts/ktx_booking.py
Tested: npm run ci
Tested: Live search via scripts/ktx_booking.py search 서울 부산 20260328 000000 --include-no-seats --include-waiting-list
Tested: Live reserve/cancel via scripts/ktx_booking.py reserve/cancel/reservations on March 28, 2026 KTX #001
Not-tested: Final payment completion after reservation
Add aligned CJ and 우체국 sample public-output blocks to both delivery-tracking docs and extend the docs regression so those examples stay synchronized with the normalized non-PII contract. The new examples are dated live smoke-test captures, giving reviewers and users a concrete expected result without relying on raw carrier fields.
Constraint: feature/#4 already matched dev, so the follow-up needed a small reviewable change to reopen PR work on the same branch
Constraint: Keep verification offline in CI and avoid new runtime dependencies
Rejected: Add live carrier calls to CI | external endpoints are flaky and would make the docs regression nondeterministic
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Refresh both dated sample-output blocks together if the smoke-test invoices ever change their public tracking history
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: python3 /tmp/cj_verify.py
Tested: python3 /tmp/epost_verify.py
Tested: npx --yes skills add . --list
Tested: git diff --check
Not-tested: Automated live carrier verification in CI
The current delivery-tracking follow-up already describes a shared
normalized schema, but the regression test still allowed drift in the
actual field expressions. This change upgrades the docs regression to
exact key/value allowlists and aligns the 우체국 feature example with
named summary groups so the published examples stay in sync.
Constraint: Follow-up had to stay docs-first on feature/#4 / PR #12
Constraint: The published CJ and 우체국 examples must remain privacy-safe while sharing one exact schema contract
Rejected: Keep key-only checks in the regression suite | still allows silent expression drift in published examples
Rejected: Refactor the docs examples into separate reusable scripts | too broad for this bounded follow-up
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If the delivery examples change again, update both the printed object mappings and the exact allowlist regression in the same diff
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Not-tested: Live carrier requests were not needed for this schema-lock follow-up because behavior remained documentation-only and prior live verification already covered the transport paths
The approved issue-4 follow-up was already on the branch, so this pass tightened the regression suite first and then made the shared schema explicit in both delivery-tracking docs. The docs now name the normalized keys directly and state that recent_events is capped at the latest three entries, matching the verified CJ and 우체국 examples.
Constraint: Keep the published examples aligned with the verified carrier flows and the existing normalized output contract
Rejected: Broader refactor of the delivery-tracking examples | unnecessary for this follow-up and would widen review scope
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the docs and regression test aligned whenever the normalized tracking schema changes
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: npx --yes skills add . --list
Tested: Live CJ official flow for 1234567890
Tested: Live 우체국 flow for 1234567890123
The delivery-tracking docs promised one carrier-agnostic result shape,
but the CJ and 우체국 examples had drifted into different schemas.
This updates both published examples and the regression suite to emit
the same normalized fields, include recent_events, and sanitize ePost
TEL fragments observed during live verification.
Constraint: Issue #4 follow-up must keep published examples non-PII and aligned with the documented common-format contract
Rejected: Preserve carrier-specific fields in the published examples | contradicts the carrier-adapter normalization promise and review feedback
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep CJ and ePost published examples on the same normalized schema and strip contact fragments from documented ePost locations
Tested: node --test scripts/skill-docs.test.js; npm run ci; npx --yes skills add . --list; live CJ verification for 1234567890; live ePost verification for 1234567890123; architect verification
Not-tested: Shared runtime adapter implementation outside the published docs/examples
The CJ official response can embed staff name and phone data in crgNm, so the published skill and feature examples now emit only normalized summary fields. The root docs regression suite also locks the safe output shape so raw CJ event payloads do not creep back into the docs.\n\nConstraint: Official CJ tracking responses may include personal contact data in crgNm\nRejected: Keep a message field with ad-hoc redaction | deleting the field is safer for published examples\nConfidence: high\nScope-risk: narrow\nReversibility: clean\nDirective: Keep carrier doc examples limited to normalized summary fields; do not dump raw tracking payloads without privacy review\nTested: node --test scripts/skill-docs.test.js; npx --yes skills add . --list; npm run ci; CJ official curl+cookie+_csrf verification for 1234567890; 우체국 curl --http1.1 --tls-max 1.2 verification for 1234567890123; lsp_diagnostics scripts/skill-docs.test.js\nNot-tested: Live carrier responses beyond the documented smoke-test invoice numbers
The first delivery-tracking draft exposed too much of the raw CJ event payload in the public examples. This follow-up keeps the examples useful for status checks while normalizing them to non-PII fields only, and locks that expectation in the docs regression suite so the raw field is not reintroduced.
Constraint: Must preserve the verified official CJ flow while removing avoidable personal-contact leakage from the shipped examples
Constraint: Follow-up had to stay docs-first and scoped to the existing feature/#4 PR branch
Rejected: Keep raw CJ payload output and rely on users to ignore | published examples should not leak names/phone numbers unnecessarily
Rejected: Drop CJ example detail entirely | loses practical verification value for the main carrier path
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Any future CJ example update must continue to avoid printing raw or other contact-bearing fields in public docs
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: python3 normalized CJ official endpoint verification for 1234567890
Tested: python3 우체국 follow-up verification for 1234567890123
Not-tested: Real non-placeholder customer waybills with different event shapes
The delivery-tracking skill already existed on feature/#4, but the
CJ example still documented a naive Python HTTP path. This follow-up
switches the documented CJ flow to the verified curl+cookie+_csrf
sequence, then tightens the surrounding docs so the shipped scope and
future carrier-extension story stay consistent.
Constraint: CJ tracking-detail rejects naive direct HTTP calls without preserved session state
Constraint: Must keep the existing feature/#4 PR against dev accurate without widening scope
Rejected: Keep the urllib-only CJ example | live smoke test returned 403 and contradicted the docs
Confidence: high
Scope-risk: narrow
Directive: Re-run live carrier smoke tests before changing documented transport steps for CJ or 우체국
Tested: npm run ci; live CJ curl+cookie+_csrf verification for 1234567890; live 우체국 curl verification for 1234567890123
Not-tested: Real non-placeholder customer waybills
Issue #4 asks for a first-class way to check Korean parcel status from invoice numbers. This change adds a delivery-tracking skill covering CJ대한통운 and 우체국 through their official surfaces, wires it into the repo docs, and locks the carrier-specific endpoint rules with the root regression suite.
Constraint: Must stay docs-first with no new dependencies or bundled carrier client code
Constraint: Official carrier surfaces use different transport shapes (CJ JSON with _csrf, 우체국 HTML/form flow) so the skill must document adapter-specific rules explicitly
Rejected: Use a third-party aggregate tracking site | violates official-surface requirement and weakens long-term maintainability
Rejected: Collapse both carriers into one generic parsing recipe | carrier-specific transport and parsing rules differ too much
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep future carrier additions as explicit carrier adapters with official URLs, length rules, and parsing guidance instead of broadening the current CJ/우체국 snippets into a catch-all flow
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: npx --yes skills add . --list
Tested: python3 CJ official endpoint verification for 1234567890 and 000000000000
Tested: python3 requests verification of the 우체국 landing page plus trace.RetrieveDomRigiTraceList.comm follow-up for 1234567890123
Not-tested: Real customer shipment numbers across more carriers or edge-case invoice formats
The zipcode-search docs were directionally correct, but they left a few practical failure modes underexplained for real operator use. This update makes the retry order explicit, adds guidance for temp-file based parsing in wrapped shells, and documents the benign curl (23) case when downstream readers close early.
Constraint: Keep the change docs-first without adding runtime code or dependencies
Constraint: The official ePost endpoint remains intermittently flaky, so guidance must focus on stable operator behavior rather than pretending transport is deterministic
Rejected: Replace the docs example with a larger shell wrapper script | too heavy for a small skill-doc improvement
Rejected: Ignore curl (23) and here-doc issues as user error | repeated operator confusion is worth documenting
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If the zipcode-search example changes again, keep the retry order and shell-wrapper caveats aligned between the skill doc, feature doc, and regression test
Tested: node --check scripts/skill-docs.test.js
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: npx --yes skills add . --list
Not-tested: Live ePost requests for this doc-only follow-up
Broaden the root regression suite to cover the roadmap/source/feature-doc surface and replace the fragile urllib example with a curl-backed, timeout-bounded snippet that matches the verified live query path.
Constraint: The ePost endpoint resets the shipped urllib transport on current local python3 toolchains
Constraint: Must keep the fix doc-only with no new dependencies
Rejected: Keep urllib and add a warning only | the published example would still fail as written
Confidence: high
Scope-risk: narrow
Directive: If the ePost markup or transport requirements change, update both docs and scripts/skill-docs.test.js together
Tested: node --test scripts/skill-docs.test.js
Tested: npx --yes skills add . --list
Tested: python3 /tmp/zipcode_live_check.py
Tested: npm run ci
Not-tested: Alternative HTTP clients beyond the curl-backed path
Issue #3 asks for a low-friction way to turn a known Korean address into a postal code. This change adds a dedicated zipcode-search skill, wires it into repo docs, and protects the new discovery/documentation surface with a root-level regression test that now runs under npm test/ci.
Constraint: Must use the official ePost postal search page and avoid new dependencies
Rejected: Data.go.kr key-based postal API | unnecessary setup for a simple lookup skill
Confidence: high
Scope-risk: narrow
Directive: Keep the zipcode-search extraction logic aligned with the official ePost HTML fields unless a more stable public API replaces it
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: npx --yes skills add . --list
Tested: python3 live query against the ePost endpoint for 세종대로 209
Not-tested: Broader address variants beyond the verified ePost query example
Add the new kakaotalk-mac skill as a docs-first capability with regression coverage, repository discoverability, and clear macOS permission/install guidance built around kakaocli. The change keeps the repo docs-only while making the feature installable and reviewable through existing skill validation paths.
Constraint: This repo ships skill definitions and docs, not KakaoTalk automation binaries
Constraint: Guidance must stay macOS-specific and require explicit confirmation before sending to other people
Rejected: Add executable integration code in this repo | issue scope is docs-only skill packaging
Rejected: Document unofficial non-macOS workarounds | upstream tool is macOS-only and issue explicitly targets Mac
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep future updates aligned with upstream kakaocli commands and macOS permission requirements before broadening this skill
Tested: node --test scripts/skill-docs.test.js
Tested: npm run ci
Tested: npx --yes skills add . --list
Tested: Architect review approval on working tree
Not-tested: Live kakaocli execution against a local KakaoTalk installation on macOS
The feature guide already documented `--include-images`, but it did not
spell out the verification rule as clearly as the skill doc. Add a
feature-level verification checklist and tighten the regression test so
repo docs stay aligned with the actual `hwpjs` inline-image behavior.
Constraint: `hwpjs to-markdown --include-images` embeds images as base64 data URIs instead of writing sidecar files
Rejected: Leave verification guidance only in `hwp/SKILL.md` | feature docs could drift without their own regression coverage
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the feature-guide verification text aligned with `npx --yes @ohah/hwpjs to-markdown --help` if the CLI flag behavior changes
Tested: node --test scripts/skill-docs.test.js; npx --yes @ohah/hwpjs to-markdown --help; npm test; npm run ci; npx --yes skills add . --list
Not-tested: End-to-end conversion against a real `.hwp` fixture
The follow-up review found that the HWP skill docs described
`hwpjs to-markdown --include-images` as if it generated image
paths/files, while the actual CLI help says the flag embeds images
as base64 data URIs. This update corrects the verification wording
in the skill docs, mirrors the same note in the feature guide, and
adds regression coverage so the docs stay aligned with the verified
CLI behavior.
Constraint: Follow-up must stay on PR #5 / branch `feature/#1` and keep the existing HWP feature wiring intact
Constraint: Root regression coverage should lock the reviewed documentation behavior before future edits
Rejected: Switch the docs to `--images-dir` examples instead | would change the documented workflow instead of fixing the reviewed mismatch
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If `hwpjs` changes `--include-images` semantics, update both `hwp/SKILL.md` and `docs/features/hwp.md` and keep `scripts/skill-docs.test.js` in sync
Tested: `node --test scripts/skill-docs.test.js`
Tested: `npx --yes @ohah/hwpjs to-markdown --help`
Tested: `npm test`
Tested: `npm run ci`
Tested: `npx --yes skills add . --list`
Not-tested: End-to-end HWP conversion with a fixture document in this repository (no sample `.hwp` fixture was added)
Issue #1 adds a new hwp skill that routes routine conversion work to @ohah/hwpjs and reserves hwp-mcp for Windows environments with Hangul installed and direct-control needs. The repo docs and root verification now cover the new skill so it remains visible in listings and regressions catch missing documentation.
Constraint: The repository is documentation-first for skills, so the change needed tested docs rather than a new runtime package
Constraint: No new dependencies were allowed for the repo implementation
Rejected: Adding a bundled HWP runtime wrapper package | issue scope only required the installable skill and guidance
Rejected: Defaulting to hwp-mcp on Windows without explicit Hangul availability | too risky for unsupported environments
Confidence: high
Scope-risk: narrow
Directive: Keep conversion/extraction guidance biased toward @ohah/hwpjs unless direct Hangul automation is explicitly available
Tested: npm test
Tested: npm run ci
Tested: npx --yes skills add . --list
Not-tested: Live conversion against a sample .hwp file using @ohah/hwpjs
Not-tested: Windows-only hwp-mcp control against a locally installed Hangul application
Document the intended post-install path around k-skill-setup, add opt-in guidance for update checks and GitHub starring, and mark KTX booking as currently unavailable so users do not assume it is production-ready.
Constraint: Setup guidance must avoid automatic persistent changes or GitHub side effects without explicit user consent
Constraint: Repository docs should steer users toward the actual skills install surface rather than `.codex`
Rejected: Keep per-skill install branching as the default path | it obscures the intended full-bundle install flow
Rejected: Auto-star the repository from the setup skill | violates explicit-consent expectations
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep install docs, setup docs, and k-skill-setup instructions aligned whenever the installer workflow changes
Tested: npm run ci; rg verification of README KTX availability notice
Not-tested: Manual execution of cron/schtasks examples and `gh repo star` flow
This snapshots the current repository updates as a coherent release-prep
baseline: workspace/package scaffolding, release automation docs and
workflows, refreshed skill/setup documentation, roadmap expansion, and
the README thumbnail polish.
Constraint: Node packages in this repo must use npm workspaces and Changesets for releases
Constraint: Python release automation stays scaffold-only until a real package exists
Rejected: Split the current work into multiple commits | user asked to commit the current changes together
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep release docs, workflows, and package metadata aligned when adding future packages
Tested: npm run ci
Not-tested: GitHub Actions execution on remote after push
The published kbo-game package does not match the README example, so the KBO skill docs now show the API shape that actually works in practice. The examples use the exported getGame function and convert YYYY-MM-DD inputs into Date objects before calling it.
Constraint: Must document the currently published kbo-game@0.0.2 behavior without adding new dependencies
Rejected: Keep the upstream README example | local reproduction shows it throws at runtime
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Re-verify the package exports before changing these examples if kbo-game releases a new version
Tested: Local npm install of kbo-game; reproduced getGameInfo failure; verified getGame(new Date(...)) success; npm run ci
Not-tested: Future kbo-game releases with different exports or argument contracts
The README previously listed skill package names without making the
actual user-facing capabilities obvious, and several linked docs used
local absolute paths instead of repository-relative links. This change
reframes the entry point around tasks users can accomplish, adds real
feature pages for each supported workflow, and connects the install and
security docs to those pages with working relative links.
Constraint: Keep the change documentation-only and avoid introducing new dependencies
Rejected: Link directly to each SKILL.md | too implementation-centric for a README first impression
Rejected: Keep one short README and defer detail to package names | does not make capabilities obvious enough
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep README organized by user-facing jobs rather than internal skill identifiers unless the product positioning changes
Tested: Local markdown link validation across all .md files
Not-tested: GitHub web rendering preview after push
The train skills no longer share a generic wrapper. SRT now documents the dedicated SRTrain surface, and KTX now documents korail2 directly, which makes the install path, imports, and reservation examples match the libraries the user explicitly validated.
Constraint: SRT and KTX should stay separate skills with their own native library surfaces
Rejected: Keep the shared koreantrain abstraction | it hides the real backend and weakens trust in the examples
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep future train-skill examples aligned with the concrete upstream library each skill depends on
Tested: bash scripts/validate-skills.sh
Tested: Import and signature inspection for SRTrain and korail2 from temporary installs
Not-tested: Live login and booking against SRT and Korail services
The top-level page now acts as a short landing page instead of a long manual. Installation steps, agent copy-paste text, and package-runner fallback guidance live in a dedicated install document so first-time users can find them without bloating the README.
Constraint: The README should stay extremely short while still pointing new users to the right next step
Rejected: Keep detailed install prose in README | it makes the landing page noisy and harder to scan
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep README short; move future onboarding detail into focused docs unless it is essential at first glance
Tested: Manual review of README and docs/install.md links
Not-tested: Render verification on GitHub after push
Credential-bearing skills now point to a shared cross-platform setup based on sops plus age instead of a hosted password manager. The repo also gains a default setup skill and a small verification script so users can bring one encrypted secrets file to every relevant skill.
Constraint: The secret workflow must work on macOS, Linux, and Windows without mandatory vendor signup
Rejected: Keep 1Password CLI as the default | it requires account creation and sign-in
Rejected: Plaintext .env as the default | too easy to leak in a repo and too easy for tools to read at rest
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If a future skill needs stronger isolation than exec-env provides, expose a capability wrapper instead of injecting the raw secret
Tested: bash scripts/validate-skills.sh
Tested: npx --yes skills add . --list
Tested: bash scripts/check-setup.sh (expected failure without sops/age installed)
Not-tested: End-to-end sops encryption and exec-env flow on a machine with sops and age installed
The repo starts as a markdown-first multi-skill package with one shared security policy, one validation script, and lightweight install docs. This keeps v1 easy to publish and easy to review before any skill-specific automation grows deeper.
Constraint: Skills must stay compatible with the skills CLI package layout
Rejected: Add a repo-level manifest or build system | the package spec only requires per-skill SKILL.md
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep credential-bearing skills on 1Password CLI runtime injection, not plaintext env files
Tested: bash scripts/validate-skills.sh
Not-tested: Fresh-machine install via npx skills add