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
The zipcode-search docs and regression suite now stop constraining the curl retry path with an outer Python timeout. The docs instead state that curl owns the transport budget, which matches the blocking review feedback and keeps the regression test aligned with that invariant.
Constraint: Follow-up had to stay on the existing feature/#3 PR branch and keep the documented curl-based flow intact
Constraint: ePost endpoint was timing out from this environment during live verification, so the fix had to be grounded in the reviewed failure mode and local regression evidence
Rejected: Raise timeout=30 to a slightly larger Python cap | still duplicates curl transport budgeting and risks another too-short wrapper limit
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: If the zipcode-search transport example changes again, keep the regression test aligned with whichever layer owns retry/timeout control
Tested: node --test scripts/skill-docs.test.js; npm run ci; npx --yes skills add . --list; repeated python3/curl probes to parcel.epost.go.kr and www.epost.go.kr
Not-tested: Successful live ePost query from this environment on 2026-03-26; current probes timed out with curl exit 28
The follow-up narrows the regression test to retry-related transport invariants and updates the zipcode-search examples to document intermittent ePost resets/timeouts while using retry-aware curl flags. The Python example now captures curl output cleanly so successful retries do not leak transient transport noise into the user-facing walkthrough.
Constraint: Review feedback required a docs-first fix on the existing feature/#3 PR branch
Constraint: The ePost endpoint intermittently resets/times out even when the retry path eventually succeeds
Rejected: Revert to urllib example | modern local runs were less reliable than curl with HTTP/1.1 + TLS 1.2
Rejected: Leave curl stderr streaming during retries | transient reset logs made successful examples look flaky
Confidence: high
Scope-risk: narrow
Directive: Keep the retry flags and official ePost extraction fields aligned between the skill doc, feature doc, and root regression test
Tested: node --test scripts/skill-docs.test.js; npm run ci; npx --yes skills add . --list; live docs example query for 세종대로 209 (3 runs)
Not-tested: Alternate address keywords beyond 세종대로 209
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