Development record
a-stale-abcd-never-answers-silently-every-surface-that-runs
Summary
Staleness detection for the abcd binary, detection-only: every surface knows
its own vintage and says so, and the one verb where stale logic writes state
(ahoy install) refuses through a stale or unknown-vintage binary. The
intent implements — never redefines — the network posture extracted at its
planning decomposition:
adr-38 and
brief invariant 7 (implicit checks disk-only; the network answers only an
explicit ask; provisioning fetches only the pinned artifact). Planning
rulings of record (2026-08-15, in the intent's Design Decisions): explicit
check at abcd version --check; refusal narrow (ahoy install only);
unknown vintage fails closed; harness portability of the session-start
channel explicitly deferred to the itd-22 lineage.
Scope
- The comparison seam (core): a version-source provider interface
feeding one comparator —
compare(current, expected)— per the upheld fit-challenge. Disk providers only in this cut: embedded build revision (runtime/debug.BuildInfoVCS stamping), dogfood checkout tip, and the plugin-cache manifest pin. The comparator's outcomes are fresh / stale / unknown — unknown is a first-class result (unstamped build,-buildvcs=false,.git-less build, dirtyvcs.modifiedrebuild), never silently mapped to fresh. - Warning surfaces (adapters over the seam): the SessionStart gap-notice
channel names a stale binary, its vintage, the reference it trails, and
the one-command fix;
abcd versionandabcd ahoyalways print install mode + vintage + staleness; ordinary verbs stay silent. - The refusal:
ahoy installevaluated through a stale-against-tip or unknown-vintage binary refuses before any write, naming the mismatch (or the unknown state) and the rebuild fix. Whether an explicit override flag exists — and its name — is decided in this spec's implementation review, not improvised. - The explicit check:
abcd version --checkfetches the latest release once, compares through the same comparator via a network provider used only here, and reports with the source named. - Transition reporting: after provisioning (itd-105/108's mechanism) has fetched a new pinned binary, the next session reports the version transition performed.
Out of scope: any healing (rebuild is the dev shim's job, re-download is
provisioning's); any second warning cadence (anti-wallpaper re-surfacing is
iss-230's seed); refusal on verbs other than ahoy install; any
version-discovery request (adr-38 tier 1); non-default-harness session-start
wiring (deferred, itd-22 lineage).
Approach
One core package owns the provider interface and comparator; front doors
consume results, never re-derive them (transport-agnostic core). The
SessionStart notice rides the existing gap-notice channel — no new hook
machinery. The refusal is a precondition check inside the install verb's
existing gate sequence, before the first apply step. The --check network
provider is the only tier-2 network touch this intent adds, and it lives
behind the explicit flag per adr-38; every other path must pass the
zero-network test harness.
Acceptance-criteria satisfaction
- Session-start notice (AC 1): the checkout-tip provider supplies
expected; the notice renders vintage, trailed tip, and the rebuild command via the gap-notice channel. - Refusal (AC 2) and unknown-vintage refusal (AC 7): the install verb's precondition consumes the comparator result; stale and unknown both refuse before any write, fresh proceeds. Tests watch both refusals fail before the change and pass after, per the TDD gate.
- Vintage output (AC 3):
versionandahoyrender install mode + vintage + staleness from the same comparator — one source of truth, two renders. - Zero-network invariant (AC 4): every path except
version --checkruns under the zero-network harness the citation gate already uses; adr-38 tier 1 is the asserted property. - Explicit check (AC 5):
version --checkfetches once, names its source, and reuses the comparator through the network provider. - Transition report (AC 6): the session compares the running binary's vintage against the last-reported one recorded beside the plugin-cache metadata and reports a transition when they differ; the fetch itself is provisioning's, out of this intent.
- Platform parity (AC 8): the staleness scenarios enter the itd-109 calibration set as machine-class criteria, human-verified per platform — this spec delivers the scenario list, itd-109 delivers the harness.
Frontmatter
| id | spc-22 |
|---|---|
| type | spec |
| lifecycle | closed |
.abcd/development/specs/closed/spc-22-a-stale-abcd-never-answers-silently.md
open on GitHub ↗ · commit history ↗
References1
- itd-111A Stale abcd Never Answers Silentlyimplements
mentions14
- adr-12`.work/issues.md` stays the live operational ledger; the structured per-issue store is deferred until the native spec layer schedules the migration (historical)
- adr-38Implicit checks are disk-only — the network answers only an explicit ask
- dcn-26081500000000032026-08-15 — itd-111 planned at the live interview (spc-22 minted, `intent ready` exit 0). The itd-84 decomposition's first live hand-run rendered SPLIT, confirmed: the network trichotomy extracted to adr-38 ("implicit checks are disk-only — the network answers only an explicit ask") + brief invariant 7, which the intent now cites rather than declares; the SessionStart staleness notice vs the iss-206 skew-notice retirement was ruled a SCOPED REPLACEMENT (`refines`, not `reverses`) — steady-state skew machinery stays retired, itd-111 covers dev checkouts and failed provisioning. Interview rulings: explicit check at `abcd version --check` (ahoy stays disk-only); refusal-on-stale deliberately narrow (ahoy install only); unknown vintage (unstamped/dirty builds) is a first-class comparator outcome that fails closed at the refusal gate; harness portability of the session-start channel explicitly deferred to the itd-22 lineage. Independent SOTA fit-challenge UPHELD path 2 with three recorded caveats (seam = version-source provider interface, not a fixed-arity function; git's behind-upstream notice joins the anchors; BuildInfo stamping holes motivate the unknown outcome). AC 6 narrowed to the transition report (the fetch is itd-105/108's); one AC added (unknown vintage). Hand-run graded into the decomposition-calibration note (entry 2).
- dcn-26092900000000082026-09-29 — Two itd-111 follow-ups from its fidelity audit (lane itd111Follow of autonomous run A). The stale-binary refusal of `ahoy install` runs before the adoption question as well as before the `--bin-dir` writability probe, so a refusal asks nothing it then ignores and touches nothing (iss-2609291942529461; the record fixed only "before any write"). The criterion 6 transition reference that spc-22 placed beside the plugin-cache metadata is not built: who writes that record, where it lives when the data directory comes from the environment, and whether it replaces the per-repo setup_version comparison are unsettled, so iss-2609291942520919 is deferred past v0.11.1 with those questions owed to the product thinker.
- dcn-26092900000000172026-09-29 — Two itd-111 follow-ups from its fidelity audit (lane itd111Follow of autonomous run A). The stale-binary refusal of `ahoy install` runs before the adoption question as well as before the `--bin-dir` writability probe, so a refusal asks nothing it then ignores and touches nothing (iss-2609291942529461; the record fixed only "before any write"). The criterion 6 transition reference that spc-22 placed beside the plugin-cache metadata is not built: who writes that record, where it lives when the data directory comes from the environment, and whether it replaces the per-repo setup_version comparison are unsettled, so iss-2609291942520919 is deferred past v0.11.1 with those questions owed to the product thinker.
- iss-230offer a one-tap micro-prompt channel (survey pattern) for maintainer decisions: when abcd needs a single small human ruling (a yes/no, a pick from two or three options), it renders one micro-prompt the facilitator can answer in one tap instead of a full interview session. Lifted out of itd-111's open questions during the 2026-08-15 forward-plans grill so the staleness intent keeps a clean scope; strike the open question from itd-111 when it goes through intent plan. Facilitator-touch item, homed in the facilitator-experience plan.
- iss-237Brief drift: 05-internals/04-universal-patterns.md and 01-product/03-mental-model.md describe internal/core/docfidelity, the spc-74/75 marker grammar, and a .abcd/validation_disciplines/ registry as current state; none exists in the Go tree and those spc ids belong to the pre-adr-21 spec space (live specs are spc-1..spc-22).
- iss-239Dangling pre-rebuild spec ids in the draft corpus: itd-44 (spc-56), itd-51 (spc-33/37), itd-57 (spc-48/60/62), itd-61 (spc-75) cite specs from the numbering adr-21/adr-26 reset (live store is spc-1..spc-22). Worse, intents/README.md and itd-34 assert the itd-44 lineage 'landed as itd-44 (spc-56 thin adoption)' — no such spec or decision-verdict code exists, so the record claims a delivery the tree cannot back.
- iss-2609291942520919itd-111 acceptance criterion 6 (after provisioning fetched a new pinned binary, the next session reports the version transition performed) is delivered as a per-repo comparison: ahoy.VersionTransition (internal/core/ahoy/vintage.go:220-234) compares core.Version against meta.setup_version in the repo's .abcd/config.json, written by ahoy install, and reports no transition when either side is a dev build. spc-22 stated the reference would be recorded beside the plugin-cache metadata. So a repo never set up by ahoy install, or a dogfood dev build, sees no transition report after provisioning fetched a new binary, which is the scenario the criterion describes. Either the plugin-cache record the spec named is the reference to consult, or the narrowing is recorded on the criterion.
- itd-4Nothing You Notice Gets Lost
- itd-22abcd Reaches Any Harness Through an Adaptor
- itd-105A fresh plugin install just works: the hook binary survives install and every update
- itd-109Acceptance Criteria Verify Themselves, And The Manual Rest Renders For A Human
- spc-2609230613208843Staleness behaviour is calibrated per platform