Development record
2026-09-29 — The product thinker answered the twenty-six Group J rulings (plan or close), J1 to J26 (recorded by lane recGroupJ of autonomous run A, for orchestrator abcd-fc). The answers are kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29.md`, section "Group J", dated 2026-09-29, and are restated here because that file is not committed. PLAN: the installer script becomes a minimal starter with an ownership-checked hand-over, planned as a new intent with its planning interview owed (J2, iss-377, draft itd-2609292106557115); token metering and size classes are planned as one intent (J3, iss-2608301744251874 and iss-2608301856299268), and session token accounting in the history store joins that metering intent (J4, iss-2608220150157508; all three in draft itd-2609292107351737); the sources tooling moves into abcd's core with ingest and consult as abcd verbs (J5, iss-27, whose corpus half itd-76 already delivered), and the backfill of the placeholder source entries is part of that intent (J6, iss-55; both in draft itd-2609292108089653); the grill hands off to an installed external interview skill and falls back to its own (J11, iss-165, draft itd-2609292108373494); an opt-in local-model prompt sanitiser is planned (J14, iss-2608261543489261, draft itd-2609292109005937); decision-to-transcript links are planned, with the anchor kind and the link's home settled in the planning interview owed for draft itd-171 (J16, iss-2608290819228175); the dredge synthesis, its write-ups as their own memory source class, is planned together with draft itd-25, whose planning interview is owed (J19, iss-2609211905340006); one provenance register across ingest and vendoring is planned together with draft itd-26, whose planning interview is owed (J20, iss-2609211905346507); release retention, keeping the newest release per version line, is automated by planning draft itd-70 (J21, iss-282); a rules-backend seam with an opt-in CARL adapter is planned, the native loader staying the default (J22, iss-64, draft itd-2609292109214516); core-owned managed pre-commit gates are planned with draft itd-62 (J23, iss-84); a behavioural end-to-end scenario suite per verb family is planned (J24, iss-48, draft itd-2609292109475690). Every draft stays in drafts/ until a person plans it, and each source issue links its draft and names that planning interview in its deferral. BUILD: the teaching plane, the rules-loader safety domain generated from the hazard registry, is built as a lane, the registry being the single source (J10, iss-151 and itd-103; a code lane owns it). RULED DETAILS: `source_kind` carries both, as two separate labels, one for the tool and one for the route (J13, iss-2608230752354928); the prompt router's removal signal is the full list of active domains every time, a domain's absence meaning it has stopped (J15, iss-2608261550580260); setup offers an outside AI service (for example OpenRouter) at install, skippable, once the API adapter ships (J18, iss-2609081951416843, which waits on the API adapter); the salvage-hook timeout is 120 seconds, the wait must show a counter or a message while it runs and never stall silently, and every per-event timeout is pinned in a test (J25, iss-323). J13, J15 and J25 are carried by code lanes. CLOSE: the quick-tunnel preview protocol is closed unless the need recurs (J26, iss-2608230617385431, wontfix with that reason). PARKED ON A TRIGGER: agent payment protocols are kept under watch, not now, revisited as the protocols mature (J8, iss-138); the findings-only skill waits for the skill format to be versioned and stewarded (J9, iss-139); the disposition worksheet as an intent and a site page waits until after the first study (J17, iss-2609021815529020). DECIDE LATER: the Homebrew tap stays parked (J1, iss-380); pluggable search back ends (J7, iss-26); forge-backed record numbering (J12, iss-2608210737264758).
2026-09-29 — The product thinker answered the twenty-six Group J rulings (plan or close), J1 to J26 (recorded by lane recGroupJ of autonomous run A, for orchestrator abcd-fc). The answers are kept verbatim in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29.md, section "Group J", dated 2026-09-29, and are restated here because that file is not committed. PLAN: the installer script becomes a minimal starter with an ownership-checked hand-over, planned as a new intent with its planning interview owed (J2, iss-377, draft itd-2609292106557115); token metering and size classes are planned as one intent (J3, iss-2608301744251874 and iss-2608301856299268), and session token accounting in the history store joins that metering intent (J4, iss-2608220150157508; all three in draft itd-2609292107351737); the sources tooling moves into abcd's core with ingest and consult as abcd verbs (J5, iss-27, whose corpus half itd-76 already delivered), and the backfill of the placeholder source entries is part of that intent (J6, iss-55; both in draft itd-2609292108089653); the grill hands off to an installed external interview skill and falls back to its own (J11, iss-165, draft itd-2609292108373494); an opt-in local-model prompt sanitiser is planned (J14, iss-2608261543489261, draft itd-2609292109005937); decision-to-transcript links are planned, with the anchor kind and the link's home settled in the planning interview owed for draft itd-171 (J16, iss-2608290819228175); the dredge synthesis, its write-ups as their own memory source class, is planned together with draft itd-25, whose planning interview is owed (J19, iss-2609211905340006); one provenance register across ingest and vendoring is planned together with draft itd-26, whose planning interview is owed (J20, iss-2609211905346507); release retention, keeping the newest release per version line, is automated by planning draft itd-70 (J21, iss-282); a rules-backend seam with an opt-in CARL adapter is planned, the native loader staying the default (J22, iss-64, draft itd-2609292109214516); core-owned managed pre-commit gates are planned with draft itd-62 (J23, iss-84); a behavioural end-to-end scenario suite per verb family is planned (J24, iss-48, draft itd-2609292109475690). Every draft stays in drafts/ until a person plans it, and each source issue links its draft and names that planning interview in its deferral. BUILD: the teaching plane, the rules-loader safety domain generated from the hazard registry, is built as a lane, the registry being the single source (J10, iss-151 and itd-103; a code lane owns it). RULED DETAILS: source_kind carries both, as two separate labels, one for the tool and one for the route (J13, iss-2608230752354928); the prompt router's removal signal is the full list of active domains every time, a domain's absence meaning it has stopped (J15, iss-2608261550580260); setup offers an outside AI service (for example OpenRouter) at install, skippable, once the API adapter ships (J18, iss-2609081951416843, which waits on the API adapter); the salvage-hook timeout is 120 seconds, the wait must show a counter or a message while it runs and never stall silently, and every per-event timeout is pinned in a test (J25, iss-323). J13, J15 and J25 are carried by code lanes. CLOSE: the quick-tunnel preview protocol is closed unless the need recurs (J26, iss-2608230617385431, wontfix with that reason). PARKED ON A TRIGGER: agent payment protocols are kept under watch, not now, revisited as the protocols mature (J8, iss-138); the findings-only skill waits for the skill format to be versioned and stewarded (J9, iss-139); the disposition worksheet as an intent and a site page waits until after the first study (J17, iss-2609021815529020). DECIDE LATER: the Homebrew tap stays parked (J1, iss-380); pluggable search back ends (J7, iss-26); forge-backed record numbering (J12, iss-2608210737264758).
Frontmatter
| id | dcn-2609290000000020 |
|---|---|
| type | decision |
| date | 2026-09-29 |
.abcd/work/decisions/dcn-2609290000000020-the-product-thinker-answered-the.md
open on GitHub ↗ · commit history ↗
mentions42
- iss-26sources corpus retrieval seam: the MVP is the current native store (per-source folders, text.md extraction, grep-based consult — shipped) and retrieval/processing becomes a pluggable seam with opt-in deeper backends, mirroring the spec seam pattern (native minimal default, adapter for depth): a RAG backend (RAG-Anything, already downloaded locally, has its own content processor that could replace pandoc/pdftotext extraction and serve semantic retrieval) and/or a CMS backend. Adapter contract, not a rewrite: consult and ingest skills keep one surface; the backend is configuration.
- iss-27corpus tooling graduates into the Go core: the sources-corpus contract (per-source folders with location-as-classification, CSL-JSON metadata, append-only provenance ledger, banlist projection) is proven by the user-tier script MVP; absorb it as a native abcd sources/ingest verb family, converging with the itd-36 provenance substrate (internal/core/provenance: licence detection, citation generation, source-hash registry) rather than porting standalone. The scripts remain the reference implementation until the native verbs are wired; /abcd:consult and /abcd:ingest keep one surface across the swap.
- iss-48behavioural end-to-end coverage: evals/smoke_test.go is structural only (help renders, no panic) — no scenario drives the built binary through a real verb round-trip (capture an issue, resolve it, list it; ahoy install into a temp repo; memory ask against a fixture substrate). Detector: a small scenario suite against the cross-compiled binary, one scenario per verb family, run in CI on both platforms. Acceptance corpus: the verb families with zero behavioural e2e today — capture, ahoy, memory, docs, history, launch.
- iss-55Six public corpus entries are keyword stubs with no document text — five practitioner SDLC pieces and one harness-engineering post — and they yielded zero extraction candidates in the 2026-07-09 tool-extraction pass, so the corpus claims coverage it cannot deliver. The fix serves retrieval honesty: backfill the full texts via the ingest path, and attach the on-disk PDF to the already-registered research-integrity paper entry so its text is queryable too. Detector: a corpus lint flags any text.md stub whose ledger entry claims a fetchable URL; acceptance is a lint run with zero such stubs and a consult query over the six entries returning document text rather than keywords.
- iss-64Make rule-injection a seam: keep the native Go loader (itd-3) as the floor, add an opt-in 'carl' backend so a user with CARL installed can route to it. Per adr-22 native-default + easy-onboard-a-better-external. Config rules.backend: native | carl.
- iss-84Managed pre-commit gates: the interim prepare-this-repo skill offers the secrets and absolute-path pre-commit config from a private template directory outside the repo. The gate belongs to the configuration layer itself: a core-owned surface should install and maintain commit gates in managed repos, replacing the template copy. Seeded from the scaffold-repo retirement analysis; relates to the pluggable safety gate draft (itd-62).
- iss-138payments protocols have no recorded position: the itd-100 terminology crosswalk found the record silent on agent-led payments (AP2 at the FIDO Alliance, x402, the two-vendor Agentic Commerce Protocol). The crosswalk row is WATCHING because a REJECTS needs a recorded reason; this capture is where that reason gets decided — likely out-of-scope-by-design for a development-configuration tool, but that is a maintainer call, not an inference. Detector: the crosswalk row cites this id; resolving it means recording the position and updating the row.
- iss-139SKILL.md compatibility watch: the record rules abcd ships zero skills (commands-only namespace; any state mutation is a command). The external Agent Skills spec (agentskills.io) is unversioned, draft-stage, and without a standards-body steward, but multi-vendor adoption is real. If a findings-only skill ever ships, SKILL.md is the accepted executable form — this capture tracks the spec's maturation (versioning, stewardship, the Experimental fields) so that decision is made against current facts. The itd-100 crosswalk's REJECTS row cites this id.
- iss-151itd-103 shipped only ONE of its two promised planes: the execution-time guard plane is fully wired (abcd guard check/hook, ahoy health), but the TEACHING plane — the rules loader injecting matched shell-safety rules before shell-heavy work, per spc-16 'Two planes, one registry' — is not built; there is no guard/safety/hazard domain in internal/core/rules/. All four itd-103 ACs concern the guard plane only, so the fidelity review is 3 MET/1 MWC, but the intent headline ('two planes') is only half delivered. Wire the teaching plane as a rules-loader safety domain sourced from the same bundled hazard registry, or amend the intent's scope.
- iss-165The grill/interview capability should follow the basics-built-in, SOTA-delegated pattern: when an external state-of-the-art interviewing skill is installed in the host (the maintainer names Matt Pocock's grill skill), abcd's grill delegates to it; when absent, abcd offers its own comprehensive built-in interview instead. Same stance as the oracle boundary: the external skill is an opt-in dependency, never a requirement.
- iss-282The retention prune has no executor: ComputeRetention renders the newest-per-line plan on every cut (brief section 3) and ship.go names GitHub Release + retention prune as a later phase, so superseded patches (v0.5.0, v0.4.0 today) stay published until someone deletes them by hand from the plan. First rung: a documented manual prune after each publish (gh release delete, tags kept for record); the executor belongs in the release workflow after that proves out
- iss-323hook salvage entries invoke bootstrap.sh with no timeout budget below its 180s curl worst case so a slow-link provision is killed and suppressed for ten minutes
- iss-377Demote hooks/bootstrap.sh to a cold-start trampoline once abcd update ships (itd-130 follow-on rung). Trigger: itd-130 shipped. When any abcd binary is resolvable, the hook delegates provisioning to the Go core (abcd update); the raw curl fetch survives only for the no-binary-anywhere cold start — the one state a Go updater cannot serve. Seam hardening carried from itd-130's Decisions: delegate only to a binary passing an ownership check, keep the raw fetch as the fallback when delegation fails, and freeze the release-asset layout as a contract so an old PATH binary provisioning a new plugin root keeps working across cuts. Goal: one canonical downloader instead of three (bootstrap.sh, the README one-liner, the Go verb).
- iss-380Homebrew tap for abcd (a personal tap, brew install <personal account>/tap/abcd). Trigger conditions are now MET: the repo is public and abcd update exists (its install-channel refusal already prints brew upgrade abcd on a Cellar-resolved path). Recorded and parked in [dcn-2608200000000006](../../decisions/dcn-2608200000000006-homebrew-distribution-recorded-and.md); this ledger entry makes it queryable rather than prose. abcd's release pipeline is bespoke (semantic-gate attestations, no goreleaser), so the tap push is a hand-rolled release-workflow step, not goreleaser's homebrew_casks pipe. Ready for triage rather than deferral.
- iss-2608210737264758The optional forge-backed allocator (itd-114 ac-5) is deferred by recorded ruling — spc-33 names it a later adapter behind the same mint seam, adr-45 ruling 4 fixes its posture (allocates and never stores per itd-129's ledger-canonical line; offline falls back to native loudly) — but no open work item holds the seat, so nothing tracks building it. The fidelity verdict on itd-114 carries the criterion as NOT_MET/deferred-by-ruling; this capture is the deferred work's ledger seat, builds on itd-129's adapter seam when that lands
- iss-2608220150157508Local-only token-usage accounting in the history store: at history capture time, extract per-message usage (input, output, cache-read, cache-write) and the model id from the transcript's own usage fields, store the aggregate with a timestamp in the stored transcript's metadata, and offer a report summing per session and per repo. Pricing is a user-level table (~/.abcd), recorded on explicit ask only: when a report meets a model with no recorded pricing it offers an explicit refresh verb in the docs-cite-refresh mould — never an implicit fetch (adr-38). Estimates are labelled API-equivalent (subscription seats do not bill per token; cache tiers price differently). Local-only by construction: never committed, never rendered on any site
- iss-2608230617385431a quick-tunnel preview flow (cloudflared tunnel --url against a local site build) covers phone testing when the LAN route is blocked and multiple simultaneous testers during dev work; worth a documented protocol or make target if the need recurs — the URL is public while the tunnel runs, so the protocol must say what may be served through it
- iss-2608230752354928the history store's validKinds drops the source harness of an imported transcript
- iss-2608261543489261Optional feature: a local model within the harness captures prompts and sanitises, cleans and PII-checks them before they are piped through to the harness's foundation model. A small on-machine model sits at the prompt seam (the UserPromptSubmit surface is the natural hook) and rewrites or flags secrets, private names and PII locally, so nothing sensitive leaves the machine unredacted — the redact-on-write posture the history store already takes for transcripts, applied upstream to live prompts. Composes with the existing scanner and banlist layers rather than replacing them, and with the privacy legibility thread of the UX work: the product thinker gets one plain claim, nothing leaves this machine unchecked. Opt-in adapter per the host-delegated default; a missing local model degrades loudly to pass-through, never silently.
- iss-2608261550580260The prompt-router emits only domains whose content changed this turn, so a client that snapshots injected rules — a host-side adaptor staging them into a system prompt, or a future MCP consumer — keeps a domain that was deleted or renamed mid-session until session end: there is no removal signal in the protocol. Emit the full active-domain-name set, or tombstones for removals, so a snapshotting client can prune. A local second-harness adaptor lab hit this and had to accept the lingering snapshot as a recorded gap.
- iss-2608290819228175A decision recorded in an intent, an ADR or the decision log should point at the section of the redacted transcript where it was actually made, so the reasoning behind a record is recoverable rather than lost with the session that produced it. This is the Naur point the lifeboat work already rests on: the record is the floor of recoverable theory, not the theory itself, and today nothing leads from a decision back to the conversation that reached it. The store is closer to this than it first appears. A transcript record already carries session_id, a source_sha256 content hash, and captured_at as an RFC3339 nanosecond timestamp, so the SESSION is timestamped and content-addressed already. What is missing is granularity inside one transcript: there is no per-turn or per-section anchor, so a link can name the session but not the passage. Two constraints shape the design and both rule out the obvious approach. A line number is the wrong anchor, and the repository already refuses that shape elsewhere through the no-brittle-line-refs rule, which tells an author to use a section anchor instead. And redaction rewrites spans in place, so any byte offset or line number computed against the raw transcript is invalid against the stored redacted one: an anchor has to be derived from the redacted artefact, or be content-addressed rather than positional. The plausible shape is therefore a typed cross-reference carrying session_id plus source_sha256 plus a stable intra-transcript anchor, minted when the decision is recorded rather than reconstructed later, with per-turn timestamps or ids added to the stored transcript so such an anchor exists to name. Worth deciding whether the anchor is a turn id, a content hash of the passage, or a heading, and whether the link is stored on the decision record, in the transcript, or both.
- iss-2608301744251874development token metering is parked as a note and owes a file or reject decision at the next phase planning
- iss-2608301856299268a size classification for specs and tasks is parked as a note and owes a design and filing decision in a future session
- iss-2609021815529020The human step of answering a run's items has no surface beyond the disposition command: a worksheet that walks the researcher through every outstanding item one reading at a time, offers the four states as the design allows them per position with the refusals built in (grounds required on every state but held, an exit condition on held, no default and nothing meaning already covered), loads the outstanding items from a markdown export of the reading records and returns one uniquely named answer file that a session records through the disposition command, was prototyped outside the record for the opening run. Whether it becomes a planned intent, and whether the site renders the outstanding items of every open run as a read-only page, is a maintainer decision after the first run shows what the form needs.
- iss-2609081951416843Setup discovery (ahoy) could probe OpenRouter reachability and, when reachable, offer it to the user as an opt-in code-review oracle — once the OpenAI-compatible api oracle adapter ships, OpenRouter is provider config (baseURL https://openrouter.ai/api/v1 + key), and the offer is an ahoy-time question, never an auto-selected backend.
- iss-2609211905340006Dredge synthesis output lands in the memory store as its own source class. itd-36 (closed as delivered on 2026-09-21) asked that the dredge synthesiser (itd-25, still a draft) write its synthesised entries to .abcd/memory/<type>_<domain>_<slug>.md with source.class dredge_synthesis and the per-run provenance the lint reads; dredge does not exist yet, so the memory store has no such class and the lint has no rule for it. Wanted, when itd-25 is planned: the class in the closed enum, the writer in the dredge path, and MS001/MS002 reading it as a cross-class input.
- iss-2609211905346507One registry entry for a source ingested as documentation and vendored as code. itd-36 (closed as delivered on 2026-09-21) asked that the same source content ingested by memory ingest and by the code-vendoring path (itd-26, loot, still a draft) share one provenance registry entry with an ingest count of two; the vendoring path does not exist, so the registry has one writer and no count. Wanted, when itd-26 is planned: the registry keyed by source hash across both paths, the count, and one licence declaration read by both.
- iss-2610241549052683Twelve decisions are recorded twice, under two ids with byte-identical bodies: dcn-2609290000000011 and dcn-2609290000000020 (the Group J rulings, J12 among them), dcn-2609290000000012 and dcn-2609290000000021 (ruling J13), and ten more pairs dated 2026-09-27 to 2026-09-30. The old .abcd/work/DECISIONS.md already held each of these entries twice before c2fdca9e1 migrated every entry into a record of its own, so each duplicate became a second record. None of the twelve higher ids is cited anywhere, but abcd decide lists each ruling twice and a reader cannot tell which id is the record.
- itd-25Patterns Surface Themselves
- itd-26Raid the Open Ocean, Bring the Cargo Home with Papers
- itd-62abcd Routes The Invisible Risks An Amateur Cannot See To A Real, Fail-Closed Gate That Wraps A Trusted Scanner
- itd-70Drawn-out intent
- itd-76abcd Lets You Consult Sources You Cannot Cite — and Remembers Every Debt
- itd-103**abcd teaches repo agents the shell commands they must never run — and blocks them when they try.** An agent that runs `cd scratch && rm -rf *` is one failed `cd` away from deleting the working tree, and the facilitator watching the session usually has no way to know that. abcd ships a hazard registry: each entry a dangerous command pattern, its severity, the safe successor, and a plain-language why. One registry, two planes. The rules loader injects the matched safety rules before shell-heavy work, so the agent is taught the safe form up front; a deterministic guard — a core verb any harness hook can call — refuses a matching command at execution time and replies with the safe successor, so the block itself is the lesson. Hosts without hook support still get the teaching plane; hosts with hooks get both, wired in at install. The registry grows from reality: a facilitator who sees something scary needs to know exactly one move — capture it — and recurring captures promote patterns into the bundled defaults, each entry shipping with a fixture that proves its guard fires. "I couldn't have told you why that command was dangerous," said Nia, a facilitator. "I didn't have to. The guard refused it, told the agent what to run instead, and told me why in words I understood. The one time something new scared me, I captured it and moved on."
- itd-171A decision points back to the conversation where it was reached
- itd-2609292106557115A fresh machine installs abcd through one small starter that hands over to a trusted abcd binary
- itd-2609292107351737A development session's token cost is measured, and set against the size class its spec predicted
- itd-2609292108089653Ingesting and consulting sources are abcd verbs, and no corpus entry is a keyword stub
- itd-2609292108373494The grill hands the interview to an installed interviewing skill, and runs its own when there is none
- itd-2609292109005937An opt-in local model checks every prompt for secrets and personal data before it leaves the machine
- itd-2609292109214516Rule injection is a seam: the native loader stays the default, and an opt-in CARL back end can take it over
- itd-2609292109475690Every verb family has a behavioural scenario that drives the built binary end to end