This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

Decision log

2026-1151

  • dcn-26110522305464352026-11-05

    2026-11-05 — The product thinker ruled that a lane's review before an unattended merge may read the lane in full in one round and its records commit in a second round scoped to that commit, and that this is the full pair their earlier ruling asked for. It confirms the reading the build loop's landing change recorded.

  • dcn-26110522305406882026-11-05

    2026-11-05 — The product thinker ruled that the warning for an agent session running without the wall may ship in this release as one line on stderr, with a line a person can read later owed as follow-up work.

  • dcn-26110519080786962026-11-05

    2026-11-05 — The build loop records a review receipt only from a pair that read the pushed head, its records commit included. Where the mode is auto, a lane's full round is told each resolution it declares and judges it, and the records commit then takes a review round of its own, scoped to that commit, before anything is pushed, unless the commit moves an issue's record that round was not told of or holds more than plain markdown, when the lane parks before any round. A round that does not pass parks the lane at its pull request for a person, with no fix round, and a parked lane is not synced. By the coordinator's reading, this meets the reason behind clause 6 of dcn-2610291524030570 and the full-pair ruling in dcn-2611012113436014; the person is told and can overrule. It supersedes that clause's statement that the loop writes no receipt.

  • dcn-26110517204906302026-11-05

    2026-11-05 — Test reuse's classifier reads test source on a best-effort basis, so some spellings escape it, among them a program name held in a local variable (iss-2611051719413677). This is deferred as a design limit of a local speed-up, not a route to close before the cut: the hosted run reuses nothing and stays the authority on whether a change passes.

  • dcn-26110509591616002026-11-05

    2026-11-05 — The release hold's posted sentences change in three places, amending dcn-2610230833367984, whose other sentences stand. In place of its withdrawn sentence: "abcd release hold: the merge of #1234 is withdrawn by octo while release v0.16.0 is cut, and is re-armed after it where the merge gate arms its head." New, where the merge gate holds a re-arm: "abcd release hold: the merge of #1234 stays withdrawn after release v0.16.0: no review or approval in this checkout names its head 0123456789ab. abcd land from a checkout holding the review re-arms it." New, where a withdrawn or admitted pull request stands armed by another account at a head the merge gate does not arm (state standing): "abcd release hold: the merge of #1234 stays armed at 0123456789ab, which the merge gate in this checkout does not arm; the hold for release v0.16.0 has ended. To withdraw it: gh pr merge 1234 --disable-auto, and take it out of the merge queue on its page if it is queued." Each carries validated fields only, as the others do. An older binary reads a tip carrying standing as unreadable, which holds merges for it for up to 2 hours where the release is untagged (the reservation's lease), so that hold is this record's cost and not a fault to chase.

  • dcn-26110509312293562026-11-05

    2026-11-05 — The off-profile warning is one line on the verb's stderr, printed after the move. While the away mode holds it reaches the agent alone, and nothing records it for the person's return, because no one existing call fits: a queued step is an act for the person to approve, and a recorded stop reads on return as a stop. dcn-2611041550129278 asks for a line that cannot be missed, so carrying it to the person's return stays owed under the itd-2611040344170206 criterion opening "Given a session that is not on a profile".

  • dcn-26110509312192132026-11-05

    2026-11-05 — A terminal abcd drain --drive takes no off-profile warning: it starts agents of its own from a plain terminal, so it is not a session starting work under the person's own setup. This changes the clause of the itd-2611040344170206 criterion opening "Given a session that is not on a profile" that listed abcd drain --drive among the starts that warn.

  • dcn-26110508151159042026-11-05

    2026-11-05 — A no-host drive's eight-hour deadline gives way to a bound the person sets. abcd drain --drive --until <date> ends the run at that time with the lane saved, and until then no limit, outage or stuck queue ends it: each is waited through at a capped interval, the wait on screen, the claims renewed. With no flag each wait keeps its eight-hour limit, so an attended short run behaves as before. A limit is met at the hard limit only: no usage window is read ahead of it, no other route is opened. Under the bound, and only there, a limit is asked about with one short launch that asks for no tools rather than with the lane's own work: on a capped backoff when it names no reset, and at a low rate when it names one, since a reset read from a stream can be wrong. An agent that goes silent cannot yet be told from a hung one, so it is treated as a hang: killed at its stage's deadline, its work left in the lane's worktree, the role retried. The first limit a run meets, and the first failure that may be one, leave an evidence file in the local tier, which is how the behaviour of a headless limit gets observed.

  • dcn-26110501363237912026-11-05

    2026-11-05 — load.narrow_runs follows the process's home, as load.preflights does, so a recipe that sets HOME chooses which configuration the gate reads. That stays: the same recipe could skip the gate altogether, so the setting adds nothing a repository could not already do, and under .abcd/development/principles/abcd-fixes-what-it-adds.md the finding is closed, with no change to how a repository works.

  • dcn-26110423400662882026-11-04

    2026-11-04 — On 2026-11-04 the product thinker ruled the order of the work ahead: efficiency first, then the terminal drain's engine, the stop and restart and the launch ledger, whose work stands on branches, with the digest after them. The number of sub-agents is limited by the machine, tests are held to the load gate, and a release is cut when every gate passes. An account at 95 per cent of a window still waits for its reset (dcn-2611041608057544).

  • dcn-26110422484500892026-11-04

    2026-11-04 — A repository's ledger.retention_days and ledger.retention_count may lengthen what this machine keeps and may not shorten it. Decision 14 of itd-2611031342011261 let a machine or repository figure override the shipped retention, but the store is machine-scoped and holds every repository's launches, so a figure in a repository's own config, which is whatever its last committer wrote, pruned other repositories' entries past the floor against the person's own machine figure. The machine layer sets the retention, a repository's figure stands only where it is longer, and one below is named and ignored; a figure past 36500 days or 1000000 entries is refused, so the date arithmetic cannot overflow and the store stays bounded. Each launch prunes the whole store by the figures it read, so a repository's longer figure binds that repository's launches alone, and another repository's launch still prunes by its own; only the machine's figure binds every launch. The floor of 32 days is unchanged. The cost is that a person who wants one repository's entries kept for less cannot say so from that repository; a per-repository pruner would have to open every old entry at every launch to read its repository, and nobody has asked for it.

  • dcn-26110422055566882026-11-04

    2026-11-04 — A delta pair reviews a wording fix after a full pair, and nothing else. Every changed line is letters, digits and a sentence's punctuation, naming no record of any family and no file and holding no code; a corrected id or path takes a full pair. The list of where such a fix may fall is closed and in the build of abcd that runs land: markdown under docs/explanation/, docs/how-to/ and docs/tutorials/, the plans and roadmap of the design record, and resolved and wontfix issue records. Open issues and decisions stay off it, because later steps read those bodies, so a change to them takes a full pair, and so does a ledger record's grounds section, which is structured and append-only. No file is added, removed or moved, and every file keeps its frontmatter byte for byte. No part of a listed path starts with a dot or begins as the name of a host's instruction file does. Everything else takes a full pair.

  • dcn-26110422055562212026-11-04

    2026-11-04 — A delta review satisfies the full-pair rule of dcn-2611012113436014 for records and docs alone: after a change has passed a full ruthless and security pair, a small follow-up to the record or the docs may rest on that pair with a delta pair that reads only the follow-up and whether the earlier findings closed. Anything that touches code always takes a full pair. The product thinker ruled this on 2026-11-04.

  • dcn-26110422025093342026-11-04

    2026-11-04 — The product thinker ruled on 2026-11-04 that the merge queue runs Linux on every entry and hosted macOS runs nightly and on demand, after a day on which queue entries kept dropping because GitHub had no macOS runner to give, with no test failing. Each release cut also runs its own macOS suite before releasing, whatever the nightly said. The release path runs it: release.yml's tag and publish jobs need a gate over the shards it runs on the commit it is about to tag (iss-2611042224527148). A self-hosted runner is held for later, if one is ever needed.

  • dcn-26110416080575442026-11-04

    2026-11-04 — The product thinker ruled on 2026-11-04 on two points left over from the planning interview. Ctrl-C in a terminal run behaves as a stop: the call finishes and claims are released, and a second press kills at once. For the first run each subscription belongs to one account: an account at 95 per cent of a window waits for its reset rather than moving onto the other account's subscription, and that can be revisited after the first run.

  • dcn-26110415501392642026-11-04

    2026-11-04 — The product thinker's rulings on the stop switch (itd-2611041549471712), the restart path (itd-2611041549461012) and the daily digest (itd-2611041549483696), at their filing. The stop lives on the machine that runs the work, in a shared folder chosen as an option at setup (/Users/Shared on macOS and its counterpart on Linux), on a machine no other person shares; the store ownership rule admits this one exception, and a stop that reaches the machine over a private network or through a cloud adapter is later work. The daily digest is a dated file in that same folder: the digest draft asked that one choice hold for both, and an unshared machine answers the privacy cost, so this followed from the ruling above and no question was put. A stop lets an agent in a call finish that call, then stops. A stop releases the run's claims on its work, so a peer may take it up. The drain's plugin page stays an agent's command and its terminal form stays the person's way to drive it; this changes the 2026-10-09 ruling on itd-2610090831227812 that the drain joins the person's menu when itd-82 ships.

  • dcn-26110415501355662026-11-04

    2026-11-04 — The product thinker's rulings on usage windows for unattended work on a subscription, at the planning interview of itd-2611040344170206. An agent already running when a subscription's window crosses 95 per cent finishes its stage there; no stage is checkpointed for the crossing. Either window a tool reports reaching 95 per cent, the short one or the long one, moves the next stage off that subscription. A tool that reports no usage window is used unattended only when no subscription that reports one is free.

  • dcn-26110415501292782026-11-04

    2026-11-04 — The product thinker's rulings on the profiles draft itd-2611040344170206, at its planning interview. Every agent abcd starts unattended carries abcd's guard whichever way its work is paid for: a stage on the key route runs on a profile with hooks on, and the bare launch adr-2610222222326104 names for the key route gives way for stages. Each way of paying, a subscription or a named key, is one profile with its own login and its own bare settings; a worktree is where the files are, a profile is who pays and what an agent can reach, and abcd pairs one of each per agent. A subscription's profile needs one login by the person; a key's profile needs none. A session the person starts that runs work unattended off a profile is warned in a line that cannot be missed, never refused. Whether an agent on a profile may reach the machine's other sessions is a setting, off by default. A profile's name is a readable one, never a random string: abcd ships a neutral list, a themed one such as a television series' characters is the person's own in their machine configuration, and a name is fixed at creation and retired once used; this replaces the random names of the draft's fourth decision, and the registry records the name, the tool and the date. abcd ships a sensible default allow-list of tools and a repository configures it within one bound: a repository file may narrow the list, only the person's own machine configuration may widen it, and an agent can never widen it. The same stance settles every open question of that kind, those of the ledger draft itd-2611031342011261 among them: abcd ships a sensible default and the person configures it per repository. The draft's title and scope widen to every way of paying, keys included.

  • dcn-26110415501266392026-11-04

    2026-11-04 — The product thinker's rulings on the per-key budget draft itd-2611011230226453, at its planning interview. The API key a session names is a named credential, resolved through the credential store by name from whichever of its homes the person chose (adr-2609221017021499); the keychain is the suggested home, never a required one, so a machine without a keychain tool is offered the key route like any other, and the draft is reworded to say so. Spend never passing a cap admits the exceptions the record names: a response larger than any launch cost recorded on the key before it, a launch whose cost cannot be read, several launches sharing one key at once, and the same key used by abcd on a second machine; an overrun abcd can see is recorded against the key and named in the run's record, and the provider's own console limit is the outer stop past every one of them. On that ruling adr-2611011231015519 is accepted, and its refinement of decisions 17 and 34 of itd-2610161733316518 is no longer advisory. The key route and the subscription route compose by one rule: a key at its cap pauses or moves to a second key the person named and never falls to a subscription, a subscription at its usage mark never opens a route the person has not named, and both out at once is a wait, never a third route. The key reaches the harness by a channel the agent's own shell cannot read, proved to work with the harness first, and that proof is the plan's first step; this binds how the key is handed over and not what an agent spends through the harness, which the caps bound.

  • dcn-26110413384544982026-11-04

    2026-11-04 — The product thinker ruled on 2026-11-04 that worktree prune may trim the Go build cache on its own: on every prune that removes a worktree it deletes cache entries unused for two days and says what it freed, because a full disk otherwise stops unattended work until a person acts, and Go rebuilds a deleted entry at the cost of one slower build.

  • dcn-26110323484090912026-11-03

    2026-11-03 — On 2026-11-03 the product thinker allowed one session, the release coordinator in one of the two accounts, to run build stages without the wall of dcn-2611031722512037 for that night, having been told the session holds their connectors and personal memory; its stage sub-agents are told to use file and shell tools only. The ruling is unchanged for every other session, in either account.

  • dcn-26110317225120372026-11-03

    2026-11-03 — The product thinker ruled on 2026-11-03 that drain --drive keeps its walled subscription route, and that watching is no control: a person cannot interrupt a tool call as it runs, so a person's presence never makes an unwalled agent acceptable. So every session that coordinates unattended work starts walled itself (no connectors or MCP servers, no personal memory, abcd's own guard hook kept), and a stage run as a host sub-agent gets only file and shell tools, never the person's connectors, browser or documents; a stage that cannot run within that limit does not run. This refines dcn-2611031720012399's host routing.

  • dcn-26110317200123992026-11-03

    2026-11-03 — The run builds on the person's subscriptions: the build loop's roles are routed to the host, so each stage runs as a sub-agent of the coordinating session on its subscription, since the claude runner's --bare launch always bills a key; the keys stay a fallback at 95% of a subscription window, per dcn-2611031615094092. The main work moves to the account that always runs the latest build, and a second account keeps the latest release.

  • dcn-26110317200036332026-11-03

    2026-11-03 — The product thinker said yes on 2026-11-03 to step 1 of spc-2610230813348813, the live proof that the walls of drain --drive's subscription route hold on their real machine; it runs as lab lab-261103171720-c0bdccf after they log a dedicated configuration directory into the subscription once (the lab chose ~/.abcd.noindex/claude-walled/, inside abcd's home, since the spec names no location), on the account the drive will run in.

  • dcn-26110316150940922026-11-03

    2026-11-03 — The product thinker's rulings for an experiment testing a long autonomous run (given 2026-11-03): during the experiment a release is cut whenever every gate passes, and any refusal waits for the product thinker; each API key has a hard monthly cap and no separate daily limit; sessions use the person's subscriptions first and move to a key when a subscription window reaches 95%, returning once it resets; the run may use the API keys the person has named to it; agents may plan a draft whose open questions each have one defensible answer on the record, and hold every other draft for the person; and the run keeps the person informed through one private daily digest page (what merged, what stalled, spend per key, what waits for them).

  • dcn-26110315490876172026-11-03

    2026-11-03 — Priorities ruled by the product thinker on 2026-11-03: efficiency comes first, lowering the time, cost and effort it takes to see a pull request through, so that many more agents can work at once on capped API keys. After it, in order of need: work run from the CLI alone; work across several accounts; API work with a way to manage several APIs and routes, one per model if need be; and work with stakeholders, such as live brief editing. Building continues while a release is cut, its pull requests waiting behind the release reservation.

  • dcn-26110313420201152026-11-03

    2026-11-03 — Held for the product thinker: a principle that manual facilitation means holding the major responsibility, not approving each decision, so that the facilitator's automatic mode, once widened, makes every decision a human technical facilitator would make except genuine trade-offs and those with wide-ranging consequences. Raised in lab lab-261103114820-bcba06f (finding F-23) on 2026-11-03; the wider mode itself stays with the autonomy-grant draft itd-2610240850336695, and the principle is filed only on the product thinker's word.

  • dcn-26110207225796322026-11-02

    2026-11-02 — The product thinker confirmed on 2026-11-02 the decision 8 of itd-2610301914350541 as it was edited inside its build lane (#1333). When abcd cannot read a repository's or a person's question-limits file, the question gate still reports it loudly, and abcd's own question is checked at abcd's default limits rather than run unchecked. A value that is read but falls outside its bounds is still refused. The edit stands as the decision.

  • dcn-26110207201052062026-11-02

    2026-11-02 — abcd's new website follows the release cut of 2026-11-02 rather than preceding it. The README renders from the brief from its first day, so the brief-sourcing intents itd-2611011151475128, itd-2611011151512956 and itd-2611011239589823 are planned and built first; they carry no acceptance criteria, mechanism or scope yet, and the first holds nine open questions, so each needs the person's planning interview before an automatic plan can run. Pages step 2 of itd-2610142145236613 is built and held unarmed, landing together with the README work and the held identity draft, so the front page and the record's address change once.

  • dcn-26110207200997632026-11-02

    2026-11-02 — Both open questions the technical facilitator held on itd-2610031026190632 are settled as proposed: a harness whose version reads but for which abcd ships no floor is named as having no floor to check against, never as current; and each adapter carries one update step to start, a harness whose own settings hold its updates being named as held rather than given a command.

  • dcn-26110207154919282026-11-02

    2026-11-02 — The product thinker ruled on the morning of 2026-11-02, in an interview another session relayed and one question put here: the test stages run from one fixed check directory per repository, ~/.abcd.noindex/tests/<root-sha>/, used by one check at a time, so results carry over between worktrees and criterion 1 of itd-2611011325421304 holds for tests that read the tree; a key's budget caps count the whole key, every session on that key pauses together at a cap, and spend never passes it, which replaces the 2026-11-01 reading in dcn-2611012123470476 that a limit stops only the session that hit it; what happens at a cap is a per-repository setting, pausing by default, with moving to a second key the person named for that purpose as the alternative and the subscription never; the terminal interview fix iss-2611011402496418 is lowered to minor so the build loop takes it on the API key, a ruling the product thinker gave directly to the session that records it, in answer to a question it put, which that session's transcript in the person's transcript store carries; and a command agents cannot run that admits one named issue above minor to the build loop is to be built next (iss-2611020305525945). The same morning they confirmed the edited wording of itd-2611011325421304's press release, that a test declared as reading what abcd cannot see always runs, in place of the wording confirmed at its interview.

  • dcn-26110121373800162026-11-01

    2026-11-01 — The product thinker asked on the night of 2026-11-01 for the key-supply draft itd-2611011230226453 (the person's keys read from the operating system's secret store, one named key per session, and the day, week and month caps ruled the same day) to be planned unattended overnight through abcd build --auto-plan, after its two plan reviews and with every decision recorded, and to be reviewed by them in the morning. The same evening they set a per-key spending ceiling for the night, counted per key across every session from the runner's route receipts: work runs on the main key until its total reaches the ceiling, then the session that passes it switches to the second key and tells the others.

  • dcn-26110121234704762026-11-01

    2026-11-01 — The product thinker ruled on 2026-11-01, for the agents abcd starts on a person's API key: each session names the one key it uses, so spend is attributed per session and a limit stops only that session; abcd finds a named key in the operating system's own secret store (the login keychain on macOS, the Secret Service on Linux); spending caps are configurable per day, per week and per month, and when any one is reached abcd pauses and waits rather than falling back to another route or surprising the person; a key route with no cap set refuses to start, so a budget is always set before money is spent; and a cap is set or raised through a command abcd refuses to agents, with a security-key or fingerprint touch to raise it left to a later intent. These settle the open questions of itd-2611011230226453 and its key-supply rework.

  • dcn-26110121232405762026-11-01

    2026-11-01 — The product thinker ruled on 2026-11-01 how a terminal interview treats a question abcd's check refuses: it is handed back to the interviewer to redraft, up to a bound each repository may configure, three by default; once the bound is reached abcd shows the question as it stands, repairing what it can mechanically, rather than ending the interview. The rows limit becomes a warning on the terminal route too, drawing the question as the host's question check already does; today the terminal route refuses on it. This settles the question path of iss-2611011402496418's remedy; a done outcome still refused at the bound ends under dcn-2611011402510346's rule that any end tells the person what happened and what to do.

  • dcn-26110121134360142026-11-01

    2026-11-01 — Records-only changes keep the full review pair, a ruthless and a security review, before they merge under autonomous merging, as code changes do. The pair runs on the person's API key once a verb runs the review pair on the runner. The product thinker ruled this on 2026-11-01.

  • dcn-26110121134320542026-11-01

    2026-11-01 — When a build agent abcd hands to a runner fails to start, the work waits for the person's API key instead of falling back to the session that started the build: the lane pauses and says why, and nothing is billed to the session's subscription. Each later step retries the paused role once on the runner, so the work resumes as soon as the key works, and a retry can also be asked for by hand. The product thinker ruled this on 2026-11-01.

  • dcn-26110121054014372026-11-01

    2026-11-01 — The terminal drain (itd-2610222215485265) keeps the 2026-10-23 route: a drive runs the person's own claude on their subscription by default, behind the wall dcn-2610230716408975 describes, and on an API key only when their configuration asks for it. The per-repository route choice of dcn-2611012102280663 covers the agents abcd hands out from a build or drain, not the terminal drive's own route, so spc-2610230813348813 stands as planned.

  • dcn-26110121022806632026-11-01

    2026-11-01 — Which route the agents abcd hands out (the implementer, both reviewers, the intent auditor, the drain judge and the planning interviewer) bill is a per-repository choice between the person's subscription and their API key, and the subscription is the default abcd ships. The subscription route is the person's own claude on their subscription: the host session's agents today, and the walled claude CLI dcn-2611011332308128 describes once that is built. The choice is the person's own per-repository setting, in the git-ignored local layer of the configuration order, never a committed repository file, which is still refused a runner route so a clone can never spend the person's key; the machine layer may set it for every repository. abcd offers and explains the choice rather than leaving the person to hand-write a roles block, and writes it only on their yes, so host delegation stays the written default of AGENTS.md's Boundaries. This keeps dcn-2611011332308128's subscription default and adds the per-repository choice; the terminal drive's own route keeps its subscription default (dcn-2611012105401437). While the subscription's weekly budget is near its limit, this repository's own work runs on the API key. It answers the routing default iss-2611012054262885 asks for; how the subscription route itself is walled stays open in iss-2610230716454430.

  • dcn-26110120490564912026-11-01

    2026-11-01 — The drain's user-visible hand-back of iss-2610312044551391 is accepted as written: when the auto-plan's start digest cannot copy the index, the lane is handed back before the first plan review, with a reason naming the index it cannot copy. The issue is built as an ordinary issue, its new reason being the wording the person accepted.

  • dcn-26110120490507032026-11-01

    2026-11-01 — A build's reservation over its spec's footprint follows a per-repository setting with two rules: as each step lands, narrow the reservation to the files the steps not yet landed still name (the default), or reserve only the steps in flight, widening as each lane opens and narrowing as each lands. The default never lets a later step's files go unreserved mid-run; the second blocks other copies least, at the cost of a build that can stall when its next step's files are taken. This answers the trust-rule hand-back of iss-2610230839002949.

  • dcn-26110120490462592026-11-01

    2026-11-01 — With the drain wound down on 2026-11-01, three streams of work start in parallel: the terminal drain (itd-2610222215485265) in this session, the load work (itd-2610262140595217, itd-2610262141001890 and the memory floor) with Eve, and the CI work (itd-2610261025516272 and its new drafts) with Henry. While the subscription's weekly budget is near its limit, every agent a build or drain hands out runs on the person's API key through the claude runner, never as a host subagent; only the driving sessions stay on the subscription.

  • dcn-26110119440396012026-11-01

    2026-11-01 — Land PR #1333 (step 2 of spc-2610301950037469) with iss-2611011943547454 open rather than fixing it first. The finding is one sentence in abcd guard question's text render; the JSON and the exit code are correct. It shows only when a draft's only findings are non-refusing structure findings while a store cannot be read. A fix now would cost another full preflight and review round, at one to two hours each, on a machine whose load the product thinker has made the first priority. The fix goes to a drain lane: the issue is a nitpick inconsistency with found_at internal/surface/cli/guard_question_verb.go, which the drain can reserve and fix.

  • dcn-26110115512169582026-11-01

    2026-11-01 — ADOPTED (product thinker, 2026-11-01), refining dcn-2611011248594647 and setting the stages of its section-by-section rule: (1) the sections derived from the repository's facts (install, requirements, first run, citation, badges, licence, links, contents) render now; (2) the brief-sourced sections become compulsory in abcd-managed repositories once the brief has an editing surface, because from then the owner's words live in the brief; (3) the text the README opens with is written by the product thinker; (4) the scope is the README and every page under docs/; (5) the how is optional per repository and, where it exists, holds how-to guides owned by the product team and learning material (tutorials, exercises, video) that educators and trainers may own, in the same repository, site and toolchain, kept current by tests; (6) every change that alters behaviour records a docs-impact state (needed, done, not needed) and the release cut refuses while a needed update is open, binding once the intent that carries it ships (it is open in itd-2611011239589823 where the state is recorded and which changes count); (7) editing for non-engineers starts with the forge's own editor and previews. Grounds: the product thinker's rulings in the planning conversation of 2026-11-01 and their confirmation of the routing table that day. Whether the reversal of itd-2610031348087517 stands is confirmed at the intents' planning interview. Reverse by a later decision naming this one.

  • dcn-26110114025103462026-11-01

    2026-11-01 — The product thinker ruled on 2026-11-01 that an interview must never stop on a question abcd's check refuses: stopping breaks the flow and leaves the person, product thinker or technical facilitator, not knowing what to do next. A refused question is handed back for the interviewer to redraft, and anything that does end an interview tells the person in plain words what happened and what to do. The ruling reverses the written interview's stop-on-refusal behaviour (the brief line 'the interview stops' in internal/core/interview/written.go), and the fix is tracked by iss-2611011402496418, the terminal route's issue.

  • dcn-26110113323081282026-11-01

    2026-11-01 — The product thinker's ruling of 2026-11-01, answering the follow-up dcn-2610230716408975 left open: the drain judge and the build runner take the terminal drive's default, the person's own claude CLI on their subscription behind the same walls, and stay configurable per person among the routes available (an API key, a pinned local model, or a host session). The runner's present --bare route needs an API key and stays the explicit opt-in. Reverse by a ruling that sets a different default for either role.

  • dcn-26110113323065712026-11-01

    2026-11-01 — The technical facilitator's ruling of 2026-11-01 on publishing schemas: abcd generates JSON Schemas for its boundary documents from the Go types in this repository, record front-matter included and run-state excluded, gated against drift and shipped with each release under a stable location-independent $id namespace; the work folds into itd-113, whose MCP front door needs per-tool input schemas anyway, and the OpenAI-compatible oracle adapter sends a reply's schema with each request so a local model server can constrain its answer. A separate schema repository, superseding adr-28, is reopened only when a non-Go implementation needs its own cadence or a second organisation proposes a schema change. Reverse by superseding adr-28.

  • dcn-26110113322995962026-11-01

    2026-11-01 — The product thinker's ruling of 2026-11-01 on the drain's pace: build the plain-terminal drain (itd-2610222215485265) before more drain lanes, since a lane's preflight and the build's share one load gate on the machine; once it ships, run several drains across machines, which order and skip each other's work. Reverse by resuming lanes before it ships.

  • dcn-26110113322980162026-11-01

    2026-11-01 — The technical facilitator's ruling of 2026-11-01 on iss-2610230643562468: a GitHub activity listing from which github.Pushers passed over any push entry (no actor or a malformed field) settles nothing in the release hold's placement, so the hold stays unsettled and asks again. Grounds: the unbroken-chain check catches one missing entry but not two that cancel out, such as a push and the force-push rewinding it; a harmless malformed entry blocking until a clean read is the accepted cost. Reverse by a later ruling that keeps the chain check alone.

  • dcn-26110113322914222026-11-01

    2026-11-01 — The product thinker's ruling of 2026-11-01 on iss-2610312234315875: abcd intent ready gates on the claim_sections start check, so READY means abcd build will start. That check binds both claim rows, an unanswered or empty Mechanism and unrecorded Scope Conditions, so this reverses the earlier ruling on iss-2609091009111294 for both rows; the ruling's stated ground, that READY means the build will start, holds only if both gate, so the scope was read from it rather than asked again. A Scope Conditions section holding the token None stated. satisfies its half. Grounds: on 2026-10-31 intent ready called itd-39 READY and the build then refused it at claim_sections. Reverse by a later ruling that makes either row advisory again.

  • dcn-26110112485946472026-11-01

    2026-11-01 — ADOPTED (product thinker, 2026-11-01): abcd-managed repositories move to documentation that holds no prose of its own. What people write lives in the design record (the brief, what the product is and why, its users and roles, with its principles) or the how (how-to guides, and optionally tutorials, exercises and video), and everything else is generated from code and release facts. The rule binds a page section by section as abcd comes to render it; until then a repository's hand-written prose stays where it is. A hand edit to a rendered page is caught and offered back to its source rather than overwritten. Grounds: every-claim-has-one-home already rules a second copy out for the record, and abcd's own README drifted from the brief it restates; two state-of-the-art reviews (2026-11-01) supported explanation in the design record, generated reference, tested how-to and tutorial pages, and one site with separate owners. Recorded in itd-2611011151475128, itd-2611011151512956, itd-2611011239589823 and adr-2611011153058085 (proposed). Reverse by a later decision that names this one; the drafts carry the open questions (rendered or held, where the how lives) that planning settles.

  • dcn-26110109331595742026-11-01

    2026-11-01 — iss-2611010041545467 is resolved by the remedy change alone. A source checkout's build refusing a newer run or drain state now says that abcd update does not change it, and tells the person to run the command from the same directory with the scripts/abcd.sh of a newer checkout, such as a worktree of origin/main; this was proved live on 2026-11-01 against a schema-17 run in the main checkout. Two parts of the issue's remedy are not taken. Recording the writing abcd's version and commit in the run state would bump the state schema, and every bump makes every older build refuse every run the newer one touches, the very refusal this fixes, for a gain of one named commit in a message that already names a working route. A CONCURRENCY rule that a session drives its runs from its own worktree's scripts/abcd.sh is not added, because a run lives in the local tier of the checkout that started it, so the rule would strand every run already started in a main checkout; the refusal now teaches the route at the moment it is needed.

2026-10425

  • dcn-26103120420315392026-10-31

    2026-10-31 — Stop run-2610310228179894 after lane-1 (spec step 11, --auto-plan) merged as c6e6bfb50; do not take lane-2 (step 12, the no-host drive), which the loop opened on its own straight after lane-1's land stage. The session's mandate covered step 11 only and took no new work, and the iss-2610311224444576 lane is waiting for this reservation. The reservation is tombstoned (412aaa904); lane-2's worktree stays at c6e6bfb50, with nothing on it, so a later abcd build itd-2609201916151817 reserves again and resumes at lane-2's brief stage.

  • dcn-26103120050404872026-10-31

    2026-10-31 — iss-2610311544004033, facilitator on delegation: abcd's own README keeps the layout-C header the person chose. Its badge rows are wrapped in one <p> block, and readme.parts is release-badge, build-badge, abcd-badge, licence and links, each placed where layout C shows it, so the result renders as the hand-written header does. contents is left out: layout C's link line replaces the contents list, and its Install and First run links stay hand-written.

  • dcn-26103120050381172026-10-31

    2026-10-31 — iss-2610311544004033, facilitator on delegation: inline bodies. A badge is one line, an <a href> around an <img src alt>, with every attribute value HTML-escaped. Links, licence and contents are each one line of <a> links joined by a spaced middle dot. Inline links use short labels (Changelog, Contributing, Security, Code of conduct); the inline licence links the identifier and the word licence (MIT licence), or Licence when abcd cannot name it; inline contents lists level-two headings only so it stays one line, a heading with an unsure anchor shown as plain escaped text.

  • dcn-26103120050378462026-10-31

    2026-10-31 — iss-2610311544004033, facilitator on delegation: placement. An absent part whose nearest present part is inline goes on the line beside it, with no blank line between, in the inline form, so it joins the same HTML block. With no part present, an absent part goes after a leading frontmatter block, else after the first live level-one heading, a Markdown # line or an HTML <h1> line outside every code fence, else at the top; there it is written in block form, set off by blank lines. Removing an inline part leaves no blank line in the block it sat in.

  • dcn-26103120050216682026-10-31

    2026-10-31 — iss-2610311544004033, facilitator on delegation: the inline form is chosen by where the owner puts a part, not by a new setting or flag. A part whose opening mark is a continuation line of an open block-level HTML block (CommonMark types 6 and 7, such as a <p> or <div> block, which run to the next blank line) is written as HTML, because Markdown inside an HTML block is never rendered; a part anywhere else is written as today. Grounds: CommonMark 0.31 HTML block rules; a body that cannot render where it stands is a defect, not a preference.

  • dcn-26103115443253972026-10-31

    2026-10-31 — The person, as technical facilitator, chose on 2026-10-31 how an issue lane widens its hold before it edits a path beyond its reservation (iss-2610311224444576, refining dcn-2610311251002713): the implementer runs abcd implement widen, naming the lane and each further path, before its first edit there; the step reserves the issue again with the held footprint and those paths, judged for overlap like any reservation, and exits 3 with nothing changed when another copy holds a live reservation on one, so that file is not edited and the implementer stops without a receipt, the implement stage handing the lane out again on a later step. As the backstop, an implementer's receipt is refused while the lane's branch changes a path its reservation does not cover, naming the paths and the widen step, which catches a forgotten call and an edit made through the shell. A lane leaving its landing for a fresh round keeps the paths it widened to beside its found_at. Rejected: a hook on the host's file tools as the control, since it reaches origin on every edit, fails offline, does not run on a host without hooks and misses edits made through the shell; and widening only at the receipt, which finds a clash after the work is done.

  • dcn-26103115390248482026-10-31

    2026-10-31 — The product thinker ruled on 2026-10-31, answering the question dcn-2610311251002713 sent back on iss-2610311224444576, that work on an issue or an intent is reserved only by a build or a drain: a fix that would be done by hand starts through abcd build instead, which holds an issue's found_at (an intent's, its spec's footprint) and, once iss-2610311224444576 builds it, widens an issue lane's hold file by file before each further edit, backing off a live hold another copy has there. The hand reservation of an issue or an intent is removed, but only after that widening ships, so a fix that edits beyond its found_at is never left with no way to hold the file (iss-2610311539091723); a release's reservation, and releasing a hold, stay. Accepted costs: an issue needs a found_at and an intent a READY spec before any work starts, a small fix runs the whole loop, and someone working outside abcd has no way left to mark work as taken. Rejected: keeping hand reservations, since one wide hold stalled nine of thirteen chosen builds on 2026-10-31.

  • dcn-26103113582785062026-10-31

    2026-10-31 — Each ideate reviewer's list of what the idea implies building is recorded as an optional implies_building field on that reviewer and rendered under its label in leg 3 (iss-2610310815034547), not relayed to the person and dropped. Grounds: an independent review of the change found the ignore mode told reviewers to list delivery gaps with no field to keep them, so the strict decoder left the host to lose the list or file it as the kill attempt the same rule forbids; the product thinker's ruling calls that gap the roadmap the exercise exists to find, and a verdict is recorded so a later session need not re-run it. The field is optional because a reviewer may name no gap, and it is held to the same rules as every other free-text list (no empty entry, a cap of 50, redaction, record ids resolved). Proposed while the product thinker is away; they review it on return. Reverse by dropping Reviewer.ImpliesBuilding and telling the page to relay the list with the verdict instead.

  • dcn-26103113561211722026-10-31

    2026-10-31 — The technical facilitator resumed its own landing work at 2026-10-31 13:56Z after pausing it at about 13:52Z. The pause followed a hold the product thinker gave the identity session (commit and push nothing until discussed), whose scope was unclear. The grounds for resuming are that the hold was addressed to that session about its own branch, and that the product thinker's standing instruction to this session (build the selected work autonomously, with the technical facilitator mode autonomous) still stands; that session's report that the hold named neither PR #1291 nor this session's work corroborates this and does not settle what the product thinker meant, which their own answer does: the question was queued for their return under the away mode. Reverse by the product thinker's word, and any hold they give this session stops every push at once.

  • dcn-26103113445293662026-10-31

    2026-10-31 — The ideate verdict payload gains current_state as a required top-level field while staying schema_version 2 (iss-2610310815034547). Grounds: the version number exists to stop a host composing against an old page from being misread in silence, and a payload without the field cannot be misread: it is refused with a message naming current_state and both modes, so the host that sent it learns exactly what to add. A version bump would refuse every old payload with a message about the version rather than the field, and would churn every fixture for no extra protection. The field sits at the top level rather than on the adversarial leg because it is the person's choice for the run, stated before the legs start. Reverse by bumping SchemaVersion to 3 in internal/core/ideate and teaching olderSchemaError that version 3 adds current_state.

  • dcn-26103113103370462026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 3: the auto-plan's checkout digest copies the checkout's index only when the index path is a regular file, opened without following a link or waiting on a pipe, and at most 1 GiB; otherwise it folds in a value unique to the call, so the digest never matches again and the lane is handed back. Grounds: a link to an endless device or a named pipe at the index path would fill the scratch volume or hold the step; 1 GiB is well past the index of the largest checkouts in use, which run to hundreds of megabytes; handing the lane back is the outcome that vouches for nothing it did not read.

  • dcn-26103113103343542026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 3: the auto-plan's checkout digest folds in, for the checkout's index, the SHA-256 of the copy's entries as git ls-files -z --stage -t -v lists them, next to the tree write-tree makes of the copy, and both run on the copy with core.splitIndex off. Grounds: write-tree leaves intent-to-add entries out of the tree and records no entry flags, so an intent-to-add entry or a skip-worktree flag changed the person's index with HEAD, the tree and the working tree unchanged; the listing carries each entry's mode, object, stage, path and flag tags but no cached file stats, so a stat refresh still changes nothing; -z keeps every path unambiguous. With core.splitIndex on, git writes a new shared index file into the git directory when it writes a copy, so every scratch index the shared helper runs on is written whole, inside the scratch directory.

  • dcn-26103112510136572026-10-31

    2026-10-31 — The product thinker ruled on 2026-10-31, on iss-2610311225001256, that a peer copy holding a record in an earlier lifecycle bucket than this checkout, with edits of its own, is reconciled rather than waited out or ignored: the refusal names the copy, its branch, its last commit's age, and the reconcile move (rebase that copy onto the default branch, which carries its edits onto the record at its current path, after which it holds the same bucket and no longer blocks), and that move belongs to the person or to that copy's own session, never to the refused build: abcd and the agents it runs never rewrite another copy; a copy that cannot be reconciled cleanly keeps blocking and goes to the person. The product thinker asked whether such a copy could be merged into the plan; this rule is that answer, and it is open to revision. Rejected: an advisory refusal alone, since the build stays blocked; ageing a copy out of the check, since its edits are silently overtaken; and never counting an earlier bucket, since fresh draft edits are overtaken too.

  • dcn-26103112510136472026-10-31

    2026-10-31 — The product thinker ruled on 2026-10-31, on iss-2610311224587853, that the board's Next list shows only intents that pass the build's record-only pre-start checks; an intent that fails one (a spec with no footprint, an open question, a hold, an unsettled blocker, no step left) is listed under Later with the failing check named, as the pick head already treats it, and the issue is fixed as a defect rather than planned as an intent. Rejected: keeping such intents in Next marked with their failing check, since Next would mix buildable and blocked work; and promoting the issue to an intent, since Next would mislead until it shipped.

  • dcn-26103112510027132026-10-31

    2026-10-31 — The product thinker ruled on 2026-10-31, on iss-2610311224444576, that an issue's reservation is narrowed at the source: reserving an issue lane holds its found_at and the paths its fix changes, and a reservation made by hand keeps the footprint it names. The technical facilitator settled one point after the review pair read the ruling: the lane widens its hold before it edits a further path and backs off a live hold another copy has there, because widening after the edit would find the clash only once the work is done. Found after the ruling: abcd build <iss-N> and the drain already reserve an issue's found_at alone but do not yet widen to the further paths a fix edits, and the 35-path hold iss-2610311224444576 records carries no run stage, so it was made by hand; this ruling does not reach it, and how a hand reservation wider than its record is treated goes back to the product thinker. Rejected: flagging an over-wide hold while leaving it in force, since builds stay blocked; and lapsing a hold with no run stage sooner, since a paused holder would lose its cover.

  • dcn-26103112393888462026-10-31

    2026-10-31 — The one status branch made before status branches took anonymous holder ids carries a member's login in its name. It is kept as the single accepted exception to the rule that no member name or login appears in anything committed or posted: status branches are kept for ever under their protection rule, and every status branch made since uses an anonymous holder id, so no further exception can arise. Decided by the product thinker on 2026-10-31.

  • dcn-26103110471460872026-10-31

    2026-10-31 — Checklist row 105, the CI headroom check: every check-job step that runs go test runs under a job-clock watchdog (cmd/ci-watchdog), which at the leg's cap less a 5-minute margin sends SIGQUIT to the test binaries, the processes in the step's own process group whose parent is go test, and 30 seconds later sends the whole group SIGKILL through the leader's handle, so a hang fails with goroutine dumps before the cap cancels the job with none. go test itself is never sent SIGQUIT: it takes the signal for an interrupt and drops the output it holds for each package of a multi-package run, which lost the dump in 8 of 9 trials when the whole group was signalled. Each target is read from ps by the group's id, never by name, and its group and parent are read again just before its signal. Limit: a target is signalled by pid, not through a handle, so a process that exits between that last read and its signal can have its pid reused; the read narrows this to a new process in the step's own group under the same parent, which only the step's own processes can be. go test's -timeout counts from each test binary's start, so it cannot bound the job clock: on a passing merge-group run the last package binary started 23.8 minutes into the ubuntu leg and 66.0 into the macOS leg, so a hang there would meet the 45- and 85-minute caps long before the 40m -timeout fired. The -timeout stays 40m, the per-package budget make preflight shares. The test steps now end by 40 minutes on the ubuntu leg and 80 on the macOS leg, the caps less the margin, so a passing leg whose tests would have finished inside the last 5 minutes of its cap now fails at the deadline instead. Rejected: a static headroom check with a lower -timeout, because on macOS a late package would need 19 minutes or less while internal/core/implement/loop alone ran 19.1 minutes there, so no single value fits, and lowering it on ubuntu alone would split the budget CI and preflight share; and raising the caps, which is the technical facilitator's call, cannot carry the macOS leg past the merge queue's 90-minute check response cap, and would leave the late-start gap in place. The coordinating session chose the watchdog on delegation; the caps stay as they are.

  • dcn-26103110344566612026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 2: no ignore rule is added for .abcd/work/.decisions.lock. Grounds: no code at this tree creates it; it was the lock of the single decision log, and its ignore line went with the log in v0.15.0, while abcd decide now flocks the decisions folder and leaves no file. A copy left by an older release is a static untracked file, the same in the start's checkout digest and every later one, so it hands nothing back; only an older release writing it during the reviews would, and every record writer's write changes the checkout anyway. An ignore rule for a file no current code writes would be configuration for nothing.

  • dcn-26103110344561522026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 2: a record the auto-plan's plan stage finds already in planned/ is never counted as the run's plan; the lane is handed back citing no verdict and the planned record is left as it is. This replaces the crediting of a plan found after the lane was marked as planning, and the limit dcn-2610310456565451 recorded with it. Grounds: a second step stopped after intent plan and before its state write leaves the same record another act's plan would, and the run cannot tell them apart; handing both back costs a run that ends handed back after a stopped step, which the person resolves by reading the plan, while crediting both would cite reviews for a plan they did not judge. The two plan steps stay: the mark says, in the hand-back, whether the run might have made the plan, and the stored-state check still requires it for a recorded plan.

  • dcn-26103110344427722026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 2: the auto-plan's checkout digest folds in the checkout's index, as the tree write-tree makes of a copy of it in the digest's scratch directory; a checkout with no index folds in a fixed marker, and an index git cannot write as a tree (an unmerged path) folds in its bytes. Grounds: a change staged while the working tree matches HEAD left HEAD and the working-tree digest unchanged, yet the person's next commit would carry it; write-tree caches its trees in the index file it reads, so it runs on a copy and the checkout's own index is never written. The digest still leaves out ignored files and the git directory, and leaves out the local tier by design, since the run's state and the reviewers' returns are written there.

  • dcn-26103104565840562026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 1: the auto-plan start records a digest of the checkout (HEAD plus the tree its working tree stages to in a scratch index, the local tier removed), and a checkout that changed is handed back after the reviews and before the plan. Grounds: git status --porcelain names paths only, so a second edit to an already modified file would go unseen; a scratch index stages content as the person's git does without writing the checkout's own index. The row re-check runs before the checkout check, so a change a row names is reported by its row.

  • dcn-26103104565838312026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 1: the auto-plan start gains a plannable row (kebab-case slug, no spec_id already set, planned form under the size cap) rather than handing the lane back on any intent plan refusal. Grounds: a Plan error can be transient (a lock, an I/O fault), and a permanent hand-back on it would end a run that the next step could finish; a malformed target_release is not a refusal when no target is passed, so it needs no row.

  • dcn-26103104565795632026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 1: the two plan reviews run one after the other, the second handed out only once the first's verdict is recorded, rather than stating the overlap as a limit in the ADR. Grounds: sequencing costs only the wall time of one review and removes the case where two reviewers are out together and one could hand in the other's return; the build's validators keep their parallel rounds, since each reviews a diff on its own lane.

  • dcn-26103104565743342026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 1: an auto-plan run's reviews always run on the host's agents. Drive dispatches no runner for them and records no fallback, a --route on such a step is refused before anything is written, and DriveReview sends nothing. Grounds: the lane has no worktree to confine a Bash-granted runner to, and pointing one at the shared checkout with no base would run it unconfined; a reviewer route renders a request from a validation round and a diff, which the lane has none of.

  • dcn-26103104565722172026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 1: the shared-main-checkout refusal for an auto-plan plan is passed into the loop as Options.PlanGuard and called under the run's lock immediately before intent plan, replacing the front door's unlocked pre-read of the state (PlanStageNext, removed). Grounds: judged outside the lock, two concurrent steps could let the plan run unguarded; the core stays transport-agnostic, since the guard is a function the CLI supplies.

  • dcn-26103104565654512026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 1: the auto-plan's plan stage takes two steps. The first re-checks the substitute and marks the lane (plan_started); the second re-checks it and runs the plan. A record found in planned/ counts as this run's plan only once the mark is set, and is otherwise handed back as another act's, citing no verdict. Grounds: a second step killed after the plan and before its state write must still be recorded, and a plan made by hand at the plan stage must not be credited to reviews that judged the draft. Limit: a hand plan made between the two steps is credited too; telling it apart from a killed step would need the plan to take a spec id the loop chose beforehand, which intent plan does not offer.

  • dcn-26103104565631032026-10-31

    2026-10-31 — spc-2609202134338445 step 11, fix round 1: intent plan takes PlanOptions.ExpectDigest and compares it with the draft bytes it reads under the intent store's lock, refusing with ErrDraftChanged before anything moves or is minted. The auto-plan's plan passes the digest its reviews read, and a refusal hands the lane back. Grounds: the loop's own digest check runs before Plan takes the lock, so an edit landing between the two reads would be planned unjudged; comparing on the bytes every write is made from closes that window, and an empty value leaves every other caller unchanged.

  • dcn-26103102471305802026-10-31

    2026-10-31 — spc-2609202134338445 step 11: an --auto-plan run plans in the checkout the run lives in, as a person's abcd intent plan does, and ends complete at the plan, releasing its reservation (the draft and its planned path) when its lane is done or handed back; a plan review that does not pass hands the lane back rather than opening a fix round; on an intent already planned the flag is a no-op and the run builds it; on an issue it is refused (implementer of run-2610310228179894 lane-1). Grounds: a planned intent's spec is a stub with no steps, so the build cannot continue without a spec author the spec does not name; applying a review finding would rewrite the person's record, the judgement the sign-off stands for; the plan step keeps the record writers' shared-checkout refusal at implement step

  • dcn-26103102471257552026-10-31

    2026-10-31 — spc-2609202134338445 step 11: adr-2610310235000654's criteria provenance is read as the draft carrying at least one acceptance criterion and an origin and production_mode inside the closed provenance vocabulary, and its grounds part as the most recent ground a person wrote being pursued (implementer of run-2610310228179894 lane-1). Grounds: these are the record's only machine-readable statements of where its text came from and why it is pursued; a deferred or declined conjecture is not one to plan unattended; a scope condition with no identity marker passes the claim-sections row because plan is the verb that stamps it, judged on an in-memory stamp with the probe minter so the row says exactly what plan will leave

  • dcn-26103102471238692026-10-31

    2026-10-31 — spc-2609202134338445 step 11: both --auto-plan plan reviews are started as the ruthless-reviewer agent, one brief per lens (design and feasibility, record discipline), its SHIP or FIX FIRST verdict parsed by the loop (implementer of build run-2610310228179894 lane-1, settling what the brief left open). Grounds: the adversarial-review principle names the pair by lens, not by agent; agents/ holds no record-discipline reviewer, and the security-reviewer's lens is a trust boundary, which a draft record is not; reusing the ruthless reviewer keeps the runner routing, tier routing and verdict vocabulary the loop already has for that role, and a new agent definition is a change of its own

  • dcn-26103100584214562026-10-31

    2026-10-31 — RunToEOF treats a failure Wait reports once its context has ended as cut by the context (iss-2610310054494441), rather than wrapping the command's Cancel to record whether exec stopped it. The Cancel wrapper is not exact either: a kill that reaches a command which has exited but is not yet reaped still succeeds, so it shares the same window, and it would mutate the caller's Cancel and add a second path for a command built without one; the ctx.Err() check is one condition. Its cost is that window, up to the scheduling delay before the check under load: a command that failed on its own just as its context ended reads as stopped, and its exit text is still in the message. Every caller that reads an exit code already checks its context first (ctx.Err(), or DeadlineExceeded on a deadline-only context), so none loses an answer.

  • dcn-26103019134699552026-10-30

    2026-10-30 — The product thinker ruled on 2026-10-30 that they are asked only the questions they need to answer, the design decisions with an obvious trade-off, and that the technical facilitator settles everything else that is sensible. From then on the technical facilitator settles routing, typed links, wording that follows from settled rulings, review findings the record settles and the acceptance criteria of an intent the product thinker asked to plan, and records each such decision with its reason; a design choice with an obvious trade-off is still put to the product thinker. The same day the product thinker asked for iss-2610301855200679 to be planned as an intent, which is their sign-off for planning itd-2610230756259215.

  • dcn-26103015160400542026-10-30

    2026-10-30 — An entry another holder recorded on a release before the holder id names that holder's login, which nothing abcd pushes may carry, so an act that writes one still to settle into a new commit writes it under one fixed, login-free marker, pre_id, meaning a holder from before the holder id, and keeps it on the release instead of refusing the act (iss-2610290809526033). The refusal it replaces left such a release with no act able to renew, release or settle it, and while it was still being cut it turned every new cut away. A marker entry is no reader's own in any first-record, own-record, vouching, acting or lost-withdrawal check, and no copy ever re-arms, withdraws again or admits it; renewals and take-overs carry it unchanged; the act that ends the release settles each one still to settle as manual, without asking the forge or posting on it, and prints one line naming its pull requests for their authors to re-arm by hand, naming no login. The write guard still refuses a withdrawal whose holder is neither a holder id nor the marker, so no act can add a login. The holder who first recorded the entry still finds it, through their own newest push rather than the tip: their own vouched entry for the pull request is kept over the marker entry and re-armed under their kept id, and the marker entry is dropped from that push. A release holds one entry for each pull request, and a commit listing one twice is never written. Another login's entry never displaces the reader's own: where two records are combined, the reader's own entry, as their own newest push records it, is kept over every other entry for its pull request, whatever that entry's state, vouching or place on the branch; between two entries neither of which is the reader's own, the entry still to settle is kept over a settled one, then the one its holder's own push vouches for, then, both vouched or neither, the one recorded earliest on the branch; this also fixes the default branch writing the reader's own entry beside another holder's for the same pull request. Rejected alternatives: dropping the entry, which loses the only record that the merge is held; and naming the login, which the holder id exists to keep off the remote. Ruled by the coordinating session on delegation from the product thinker.

  • dcn-26103015070149302026-10-30

    2026-10-30 — How a judgement route picks the decision adapter's second candidate, the small text model scored by log-probability (itd-2609221009495079, spc-2609221011151661; lane implementer on the run coordinator's delegation): a provider block on the person's own machine lists, under logprob_models, the models from its own models list that are asked that way, and a route to one of them is judged by the log-probability candidate while every other route keeps the first, typed-decision candidate. No new route prefix and no new judgement mode: the route grammar (host, shadow:<provider>/<model>, <provider>/<model>) stays as it is, the provider block already holds what is per model (its allowlist and pins) and sits on the machine layer alone, so a repository cannot change how a model is asked, and the field marks only a listed model, so it admits nothing the allowlist does not. Both candidates call through the same APIConfig.Call, so the allowlist, the denylist, the key by name and the router's window check apply to both unchanged; with logprob_models absent every path is as before.

  • dcn-26103013163404112026-10-30

    2026-10-30 — itd-2610262127138979, delta docs-fidelity findings 7 and 8 before the cut: docs/how-to/install.md now says make preflight waits its turn at the load gate before its load check, but AGENTS.md's preflight comment is left as it is, because AGENTS.md has under thirty bytes of room under its smallest reader's cap and the gate's wait is taught in the implement page, the LOAD rule and the Makefile. The intent's slug and title stay as they are: a rename is not a wording fix, and the intent's own Decisions section hands sizing the count automatically to itd-2610262141001890. Agent decision in an autonomous run.

  • dcn-26103013090398612026-10-30

    2026-10-30 — A find that deletes each match with rm and no recursive flag (find . -name x -exec rm {} \;) is not a guard hazard: it removes only the files the find names, one at a time, the same everyday delete dcn-2609280000000003 allows as rm -rf $(find ...), and a blocker there would teach sessions to route around the guard (adr-42, a mistake filter). Decided by the technical facilitator on delegation while judging iss-2609300536290307.

  • dcn-26103010371126562026-10-30

    2026-10-30 — itd-2610262127138979 step 3, review round 1: the test comments that call a running preflight one 'in its test stages' (machineload/slots_test.go, implement/load_slots_test.go, load_race_command_test.go, load_whole_run_test.go, surface/cli/implement_load_slots_test.go) stay as written. Each describes a fixture whose preflight is running its stages, which is literally true; the reviewer graded them a nit that ships unfixed, and the code comments and taught text that said the gate admits test stages are reworded. The taught sites (LOAD rule, commands/implement.md, the implement brief chapter, machineload/race.go) now say once that a records-only change takes a shorter rule that waits at no gate. Agent decision in an autonomous run.

  • dcn-26103009551548512026-10-30

    2026-10-30 — Merge approval and pull-request check rulings. Human mode's merge approval is a rule agents keep, not a proof of who approved: it stops an agent merging by mistake, not one set on getting round it, abcd says so wherever it describes the mode, and no proof mechanism enters this release. The person approves in the terminal through an abcd command (abcd land --approve today, or a dedicated verb), so the current act stands; the dashboard or a web app is one more channel for the same approval (itd-2610300955049260), not a gap. Agents working under a forge account of their own is optional work, designed from current practice to run in the cloud and locally, through an API key or a subscription (itd-2610300955026531). Requiring a security key touch for an approval is later work (itd-2610300955031405). The three checks every pull request runs, the change labeller, the dependency review and the vulnerability scan, stay non-blocking, and a failure in any of them is fixed without being asked until it passes.

  • dcn-26103009544339522026-10-30

    2026-10-30 — itd-2610262127138979 step 3: the first gate's settle rewrite above one slot keeps judging a race command's own first-gate hold as the settle hold, and the code says so, rather than narrowing it to holds written at one slot. A hold does not record the count it was written at, so narrowing would add a field to the hold file every abcd on the machine reads; the race run is counted from the process table either way, so the gate never admits more than the slots. Agent decision in an autonomous run, on the review note carried in dcn-2610300700434360.

  • dcn-26103007131753162026-10-30

    2026-10-30 — Decided by the technical facilitator, on delegation, for iss-2610290913450522: the remote audit pins each required check to the one GitHub App observed reporting it in the check runs of the default branch's three newest commits and the three newest pull requests' heads, by the app id GitHub's answer names, never a hard-coded one. A check two apps or a commit status reported, or no recent run reported, stays required from any source and is named; a read that fails or is cut short pins nothing; an existing pin is never changed; pinning a check already required from any source is a tightening applied only on the apply's yes. Grounds: GitHub's rulesets documentation says any person or integration with write access can set the state of any status check, and that a rule may name an app as a check's expected source (https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets); the rules REST API takes that source as a required check's optional integration_id (https://docs.github.com/en/rest/repos/rules); and push access is enough to post a commit status (https://docs.github.com/en/rest/commits/statuses). Assessed against abcd-fixes-what-it-adds: the any-source route is GitHub's default and exists without abcd, so this is hardening of a protection abcd writes, not a weakness it adds.

  • dcn-26103007004343602026-10-30

    2026-10-30 — itd-2610262127138979: four review notes on step 2's last fix are carried into step 3 rather than fixed on steps 1-2, since fixing them there would void a running preflight on the cut's critical path and none is a defect: the Makefile comment naming the load gate's go run as the first Go step holds on the full rule only; the settle-hold rewrite above one slot also covers a race command's own first-gate hold, which is slower and never less safe; the tests do not pin the settle window or the disk floor's boundaries; and the floor-rose refusal's parenthesis should name the floor. Step 3 fixes all four.

  • dcn-26103006183713212026-10-30

    2026-10-30 — itd-2610262127138979: when a look reads more than one slot, a first-gate command hold written by a run admitted at one slot is judged as a settle hold (in force only until its open plus the settle time), so raising load.preflights reaches a run already queued behind a held command, as iss-2610241414124940's resolution says; the running preflights are still counted against the slots from the process table. A disk refusal at the open look whose floor rose because the slot count rose says so, naming the new count, rather than saying the disk fell.

  • dcn-26103006154516592026-10-30

    2026-10-30 — iss-2610261837062463: when a lane leaving land cannot fetch the reservations to re-judge its other-copy overlap, the step waits as for an outage, the way fetching the default branch does (netFailure), rather than refusing for a person; a view that cannot be read after a good fetch refuses the step. An issue run's lapsed revival at land narrows to its changed files as the landing's renewal does, and only an intent run keeps its whole footprint and names the other copy's reservation it went past.

  • dcn-26103005284944732026-10-30

    2026-10-30 — Merging main's disk floor into whole-run admission (itd-2610262127138979): the load gate reads the disk where main reads it (before the wait, which main's one-slot race shortcut followed, and at the open look after the jitter) and also before a one-slot race shortcut a later look reaches, not at every look, and judges each read against the floor sized by the slot count read at that same look. A race shortcut reached at a later look, after the count fell to one, refuses with the at-open wording, since the waiter has waited by then.

  • dcn-26103005254314482026-10-30

    2026-10-30 — Withdrawals a person made under their login on a release that has ended, before their home keeps a holder id, are re-armed only once their first reservation or announcement keeps an id (iss-2610290809526033); until then the peers listing says each time that held merges from before the holder id stay held until that act, without naming the login. The cost accepted is that those merges stay held longer for a person who has not acted since the update. Three alternatives were rejected: minting the holder id on a read path such as the peers listing, since a read never writes the person's identity file; pushing a tombstone that names the login, since nothing pushed carries the login; and re-arming without the tombstone that claims the end, since that tombstone is the compare-and-swap that keeps two copies of the person from settling against different tips. The act that keeps the id writes each of those withdrawals under it, in the tombstone that settles them and in every later push of the person's that carries them, so no push names the login; a home whose id is set or kept but refused is not told the id is awaited, since every act refuses until it is fixed. Ruled by the facilitator on delegation from the product thinker.

  • dcn-26103005230059472026-10-30

    2026-10-30 — Decided by the technical facilitator on delegation (the product thinker's ruling of 2026-10-29 that embark's lesson ranking stays in the decision adapter intent as a real judgement; iss-2610262033055327 named that it has no host answer to pair), how embark's lesson ranking becomes a judgement, for step 2 of spc-2609221011151661 to build. (a) The judgement is one score question per lesson, on a scale of 0 to 4: how far does this lesson apply to the new voyage as its brief frames it. Its state is the brief's framing (bounded to fit the window) and the one lesson. A choose question over the lessons is not used, because a lesson is often longer than an option may be and the option set would grow with the lifeboat. (b) The host answers it: embark lessons lists each lesson's question in its result, the agent running the embark page scores them, and passes the scores back with a scores file; the lessons are then ranked by those scores, term overlap breaking ties. Without a scores file the result is today's term-overlap order, still named a heuristic, so no caller breaks. (c) The type routes like the drain's judgement: in shadow the adapter scores each lesson beside the host's answer and each pair is recorded in the newest lab home; turned on (only from the person's own machine file) the adapter's scores rank the lessons and no host scores are asked for; an adapter that cannot answer leaves the host's request standing with a fallback receipt. (d) With no brief, the lessons stay listed unranked, as today, and nothing is asked.

  • dcn-26103004390041872026-10-30

    2026-10-30 — itd-2610150602547271: now that the merge gate reads facilitator.mode, the board's merges line says what the gate does, read through the gate's own resolver (the default branch's committed config and the machine layer) so the board and the gate never disagree: human reads as merging once the technical facilitator approves the head, auto as merging autonomously once a review pair has passed the head, each with the layer that set it, and the facilitator view keeps the key and the mode. A contributor's pull request needing approval in either mode is said in the docs, not on the line.

  • dcn-26103004224814862026-10-30

    2026-10-30 — iss-2610261837062463: a lane at validate is never past editing, since one verdict hands a fix implementer any file of the footprint; a lapsed revival narrows only when every lane is done, discarded, handed back, or at land with no sync pending, and a lane sent back from land to editing has the run's own-copy overlap judged again on the whole footprint, as an issue run's leaving land already is. The waiter waits at most a few seconds for a renewal round in flight when its command exits, well inside the gate's settle hold, because a waiter lingering on a slow push reads as queued and holds every other gate on the machine; a pushed renewal left unlogged costs one record line, and the next round reads the fresh tip.

  • dcn-26102922381914962026-10-29

    2026-10-29 — iss-2610261837062463: a lapsed revival narrows its own-copy overlap check to the lanes' committed changes only when every lane is past all editing: handed back, at land, or at validate awaiting reviewers alone, with no implementer awaited (a fix round), no sync conflict pending and no spec step pending. Any other lane, held ones included, makes the revival judge the whole footprint, since an implementer's edits stay uncommitted until its receipt. The waiter waits, bounded, for a renewal round in flight before it exits, so a pushed renewal is logged.

  • dcn-26102922361616732026-10-29

    2026-10-29 — Decided by the technical facilitator on delegation (coordinator rulings on the review of the merge that landed step 2 of spc-2610240951109420, 2026-10-29), two rules for a model asked per request, for step 3 to build. (a) When a request asks the claude runner for a model the machine pins, the dispatch is refused before anything launches and nothing falls back, to the host or to any other runner, with the words the refusal of a --route to a pinned model on claude already uses: claude can hold no pin, and a run on another model is a run nobody asked for. As merged, the request is refused at launch and the role is handed back to the host; step 3 makes that refusal final. (b) When a request names a model and a --route names a model too, and the two differ, the dispatch is refused before anything launches, naming both; when they are the same model it runs, and the up-front pin check vets that one model.

  • dcn-26102919255082862026-10-29

    2026-10-29 — iss-2610261837062463: a lapsed revival narrows its own-copy overlap check to the lanes' changed files only once no lane is still at or before its implement stage and no spec step is pending; otherwise it judges the whole footprint and backs off, because an implementer's uncommitted edits are invisible on the branch tip and two automated lanes must never edit one file. The waiter and implement status also leave a run parked at land alone, as the drain does, and re-read the reservation view under the run lock so one lapse is renewed once.

  • dcn-26102915241003252026-10-29

    2026-10-29 — Merge-gate step 5 (itd-2610150602547271, spc-2610161609350616), decided the way that fails closed. While facilitator.mode is human the shell guard refuses every gh pr merge that merges, not only one aimed at a queue: with no queue gating the default branch a plain gh pr merge merges at once, which is the same unapproved merge; only gh pr merge --disable-auto, which withdraws an arming, is let through. Beside the enqueuePullRequest mutation it refuses enablePullRequestAutoMerge, the GraphQL form of gh pr merge --auto. The guard package sits below the resolver (internal/core/landing reads the mode through the layered reader, which imports the guard), so a front door hands the mode in (guard.WithMergeMode, read through landing.ReadDefaultFacilitator); a mode that cannot be read counts as human, and a registry with no mode handed in (the bundled defaults alone) judges no merge command. The approval act, abcd land --approve, is refused in any mode: through the binary by the registry entry abcd-land-approve, which also teaches it, and through go run ./cmd/abcd by the guard's own check, which no pattern can name. A query the guard cannot read (a gh api graphql -F query=@file) is not seen, as a body held in a variable is not. Decided by the agent building steps 4 to 6 under the orchestrator's delegation, 2026-10-29.

  • dcn-26102915240305702026-10-29

    2026-10-29 — Merge-gate step 4 (itd-2610150602547271, spc-2610161609350616), decided where the records leave it open, each the way that fails closed. (1) The facilitator's approval act is a flag of land, abcd land --approve, beside --record-review: it writes .abcd/.work.local/approvals/<full sha>, found from any worktree as the receipts are, and counts as an approval of that commit alone, for a contributor's pull request and in human mode alike. (2) A custom role's base is read from the same permission answer's legacy level (admin or write: a maintainer; read or none: a contributor), so no second call is made; any other level, a read that fails other than with 404, or an answer that does not parse is unverified and arms nothing. (3) A reviewer's approval counts only if it is that reviewer's latest submitted review of any state (a later comment or change request supersedes it, a pending draft does not), approves the head commit itself, is not the author's, and its reviewer reads as a maintainer; a page of 100 reviews counts none, since a later review may sit beyond it. (4) With no merge queue gating the default branch the arming is the forge's auto-merge as a merge commit (--merge), and a forge that refuses it is said, not retried. (5) The build loop reads the mode at the default branch's tip as just fetched, not at the lane's base, so a mode turned back to human after a run started holds; a lane the gate leaves open is parked as before and asked again on each step, so an approval or a review receipt given later arms it. (6) The loop mints no review receipt of its own: its pushed head carries the records commit its validators did not read, so in auto a lane arms only once a review receipt names that head, recorded with abcd land --record-review. Decided by the agent building steps 4 to 6 under the orchestrator's delegation, 2026-10-29.

  • dcn-26102913525120582026-10-29

    2026-10-29 — iss-2610261837062463 renews a build's reservation wherever its agent waits, not only at implement step. The gated waiter (implement load --wait and --race-gate) renews, at once and every five minutes while it waits and while its command runs, each due reservation of a run in progress that lives in the checkout the waiter runs in, or whose lane worktree is that checkout (found through git worktree list), through the loop's own renewal under the run lock, so a lapsed one is revived as step revives it; a run whose lock another invocation holds is skipped, since that invocation is a step that renews it. implement status renews a due reservation of each run it shows before rendering, and its help no longer says it writes nothing. A lapsed revival is judged for overlap with the same person's other copy against the files the lane's branch changed, as the landing's narrowing reads them, not the run's whole footprint; it keeps its whole footprint, an overlap with another person still backs it off on the whole footprint, and where the changed files cannot be read the whole footprint is judged, as before.

  • dcn-26102911322235522026-10-29

    2026-10-29 — iss-2610241911052191 takes the issue's second remedy, a per-binary test timeout scaled with the load as -p is, not admission on projected headroom (draft itd-2610262141001890). Each test stage's go test -timeout is the Makefile's 40m base while the one-minute load is at most one runnable per online core and twice it past that, two values only because go test hashes -timeout into its cache key and a budget moving with each reading would rerun every cached package on a busy machine, read once as the stage starts by cmd/test-parallelism -timeout <base> (machineload.GoTestTimeout, implement.PreflightTimeout). On a CI runner, or where the machine cannot be read, it is the base, so CI's race steps and the local race lane keep one declared budget. The cap of two keeps both stages inside land's four-hour run bound with room for the gates and eval lanes; a bad base is refused loudly, so the stage fails rather than running with go test's 10m default.

  • dcn-26102911300825972026-10-29

    2026-10-29 — Whole-run step 3 keeps the cloud collect script's own waiter around make preflight. The laptop's step-3 list dropped it as no longer needed, but a plain make -C <worktree> preflight lets the collected tree's own load-gate code decide when its preflight starts on this machine; the outer waiter runs from the person's checkout, and the Makefile already holds that wrapping is harmless (the inner waiter opens at once inside the outer turn). Raised by the Opus reviewer of fbee3d246.

  • dcn-26102910141358342026-10-29

    2026-10-29 — Decided by the technical facilitator on delegation, 2026-10-29: CITATION.cff and the README's citation block name the organisation ([redacted-user]) as the work's author in place of a person, under the product thinker's ruling that no member's name appears in tracked files and that LICENSE is the only exception. Putting a personal name back later is a one-line revert in each file if the product thinker wants one (iss-2610290855523061).

  • dcn-26102909391695392026-10-29

    2026-10-29 — Carry iss-2610240827243654 (the unreadable install one-liner) past the v0.15.1 anchor for this one cut: its fix documents a release asset that exists only once this release is published, so the install-docs change merges immediately after the tag, after the asset URL is confirmed, and resolves the record then.

  • dcn-26102908570204882026-10-29

    2026-10-29 — Decided by the product thinker on 2026-10-29: the copyright line in LICENSE keeps naming its holder, as the one exception to the rule that no member's login or name appears in tracked files. The MIT licence requires the notice to be kept in copies, and who it names is the copyright holder's own call. Everything else names people by role, the organisation or a standard persona (iss-2610290855523061).

  • dcn-26102907481904762026-10-29

    2026-10-29 — The product thinker ruled on 29 October 2026 that an intent's Audit Notes section carrying no reviewer's marker counts as audited only when it reads as a real audit, one that names the acceptance criteria and gives a verdict on them; a ruling's amendment line or any other note that does not is not an audit, and the intent still owes its review. The retrospective seed and the list of reviews owed judge this by one shared rule (intent.HandAudited), so they cannot disagree about a record. Carried by iss-2610241431221889 for itd-24 criterion 2.

  • dcn-26102907410943042026-10-29

    2026-10-29 — Declined part of iss-2610241414124940's remedy: once a run holds a slot, the gate does not switch to judging capacity by the slot count alone and keeps its load limit. Grounds, the timeout evidence of the two records: on 2026-10-24, with several preflights' test stages admitted together at a load near 20 on 10 cores, six packages hit their 20-minute per-binary timeouts in one run, so admitting more than one at a time made all of them fail (iss-2610241414124940); and the gate opened a whole run at load 17.8 on 10 cores, under its limit, after which three packages (claim, implement/loop, surface/cli) hit the 20-minute timeout because the load stayed near the threshold for the whole run (iss-2610241911052191). Admitting by slots past the load would admit more runs into exactly that load. The starvation that part answered came from queued runs' ungated stages feeding the load they waited on, which whole-run admission removes (itd-2610262127138979): a queued run now does no work. The idle-slot part of the same remedy is carried by iss-2610262155232329. The same record's 2026-10-25 evidence points the other way from slot-only admission too: a run admitted alone at load 8.5 on 10 cores still timed out three packages while the machine's on-access scanner used one to two cores, a cost the load average does not show, so the load is if anything an optimistic signal there; admission on measured headroom is the draft itd-2610262141001890.

  • dcn-26102905183769042026-10-29

    2026-10-29 — Spec footprint entries (iss-2610241549334990): the comma split that respects parentheses lives in spec.ReadFootprint, the one parser every reader shares, so the readiness score's package count stops counting half a note as a package; the leading-path read and the prose refusal live in the build's specPackages. Grounds: one split rule for every reader, and the score's 100-divided-by-packages part was miscounting the same entries. An entry with whitespace is kept when it names something in the working tree (a real path with a space), checked only for a path that stays inside the tree. A prose entry excludes its intent from build next at the footprint check instead of aborting the pick, which mirrors how a spec with no footprint is excluded. The remedy's 'leading path' is read as the entry up to its trailing parenthetical, not its first word, since the remedy's own refusal clause presumes whitespace can remain. An entry is first read as written, and kept whole when that names something in the tree, so docs/Archive (2019) is not cut back to a different path; and a trailing parenthetical counts as a note only when a space sets it off, so a route-group path such as app/(marketing) stays whole (review finding). Of the three open specs whose entries were prose, two are rewritten with their paths alone in the same change; spc-2609221011151661 is left to the lane rewriting its line, and a build of it is refused, naming the entry, until that lands.

  • dcn-26102900011041912026-10-29

    2026-10-29 — abcd reserve names each generated file a reservation shares with another record's live reservation (facilitator-on-delegation, iss-2610282340087862): the overlap judgement already lets a file origin's default branch declares linguist-generated through (dcn-2610170652481326), and now collects each such path with the other record, sorted by path then record; the reserve verb prints one shared: line per path on stdout, as a note rather than a stderr warning since nothing is wrong, and carries them as generated_shared in --json. Build and drain do not render it, as they render no other reservation note. The declaration stays the one root .gitattributes on origin's default branch, and freshness stays with TestReferenceMatchesCommittedPage and TestSurfaceSnapshotMatchesCommittedBaseline, so the second lander regenerates after merging. Grounds: loud staging, a stage that lets something through says so.

  • dcn-26102823410885442026-10-28

    2026-10-28 — Step 11 of spc-2610120557432880 (the live run on this repository, for itd-2610112239022766) is met by live use rather than a separate run: abcd embargo intake ran here on 16, 17 and 23 October, triage verdicts are recorded in the store, abcd embargo check --range ran before the release tags of 17 and 23 October, and abcd embargo publish showed a live plan on 17 October (the two defects it exposed are fixed). abcd embargo close ran live once on 28 October without --approve, against a record with a non-closing verdict, and refused as the spec says, sending nothing and naming abcd embargo triage as the next step. Its show-and-approve path has no live run yet, because no record carries a closing verdict; its first is due at the next release cut. Decided by the technical facilitator on the product thinker's delegation, through the coordinating session.

  • dcn-26102823362769632026-10-28

    2026-10-28 — spc-2609202134338445 gains a file-level footprint for step 11 (--auto-plan), and step 3's no-host part becomes a new step 12 needing 3 and 11, as iss-2610230935429241's first remedy says, with step 3 marked landed at 45cdd1af7 for the runner-driven part it has delivered (facilitator-on-delegation). Grounds: the build refused the spec for having no footprint; criterion 9 (a configured runner starts the lane and the run record names it) is met by 6ce51f237 and its surface wiring 45cdd1af7; the no-host drive stays inside the intent, since decision 5 says the product thinker confirmed that reversal "for the opt-in path only", so narrowing it is theirs to rule and no agent decision may drop it; it is recorded in adr-2610222222326104, which AGENTS.md keeps unbuilt until itd-2610222215485265 ships, so step 12 waits on that intent with no marker yet (iss-2609260932372448 holds the marker's ruling); until it ships, a run ends when step 11 lands, the person releasing the reservation with abcd build --release, since the loop opens step 12's lane at once and an intent lane's hand-back does not release it. The footprint names step 11's files only, step 12's joining when it can start, and names files rather than the whole cli package because other builds hold that package's other files (iss-2610150512342464).

  • dcn-26102820400854032026-10-28

    2026-10-28 — The product thinker asked on 2026-10-28 for the machine's capacity to be used, so load.preflights now takes a whole number from 1 to 4 (MaxPreflightSlots rises from the 2 of the trial in dcn-2610161814279204), and above one slot a preflight queued at its race gate takes no first-gate slot until its race run starts (iss-2610282016250805). The grounds: one race run at a time, kept by the race gate, and the load wait limit stay the bounds; each stage's go test -p is still the cores divided among the slots, never below a quarter of them; and the count is the person's own machine setting, never a repository's, one by default.

  • dcn-26102820362195032026-10-28

    2026-10-28 — facilitator-on-delegation: the coordinating session (abcd-f5), on delegation from the technical facilitator, raises the check job's macOS leg ceiling in ci.yml from 70 to 85 minutes and moves its warning line from 60 to 75, keeping it ten minutes ahead; the ubuntu leg stays at 45. On 2026-10-28 merge-group run 40752008734 (PR #1196) had check (macos-latest) cancelled after about 71 minutes, from 19:11:30Z to 20:22:05Z, and the queue dropped the group with failed_checks, while that day's passing merge-group runs took roughly 46 to 68 minutes. 85 stays below the merge queue's 90-minute check response timeout. The lasting remedy is still a faster suite: iss-2610181711260494 named it and was resolved by the raise to 70, and the faster race pass stays open as iss-2610181757540736; this resolves iss-2610282035340363.

  • dcn-26102817271513482026-10-28

    2026-10-28 — Merge-gate step 3 (itd-2610150602547271, recording the review pair's verdicts for a head) goes ahead while other copies hold files it shares, under the coordinator's narrowed rule for lapsed holds (recorded with the store-and-sweep change): a hold that overlaps only in files, on another subject, with nothing pushed, does not hold a ready change back. The laptop's iss-2610241107191205 shares only commands/land.md, has pushed nothing but its reservation ref, and is about lapsed holds and reservations in internal/core/claim. Step 3 changes no claim code and no behaviour of a lapsed hold or reservation: its change stays in internal/core/landing (a review receipt store beside the preflight receipts) and the land verb's --record-review flag. This machine's itd-2609151838312703 (sessions announce what they do) and itd-2610091010348892 (the hosted site) share land.md, 38-land.md, land.go and land_surface_test.go, but neither is about review receipts. With no shared subject, step 3 lands when it is ready, and whichever change lands second merges main. Ruled by the coordinator, abcd-f5, on 2026-10-28; applied by lane A.

  • dcn-26102813463917432026-10-28

    2026-10-28 — The setup plan screen lists the live brief session question among the questions it asks, not among its changes and not as a plan default: the answer is the owner's, so a default of none would decide for them and a decide-later default would leave it unasked on every proceed; listing it keeps the plan's promise that every question it does not list is never asked. Decided by the facilitator's agent while merging main into the hosted-sites branch, after both merge reviewers found the plan misdescribed it.

  • dcn-26102812211216062026-10-28

    2026-10-28 — iss-2610280107422462: the drafts bench is read from drafts/ and no longer committed as a generated region of the out-of-scope chapter, the remedy's first option. The second option, regenerating regions in the merge queue and letting the queue commit them, would put on main a commit no queue entry tested and needs a workflow change, so it is not taken. The commands list and the ADR index stay generated regions; they conflict the same way only when two pull requests each add a command or an ADR, which is rarer, and are left as they are.

  • dcn-26102809052072022026-10-28

    2026-10-28 — The plugin's hooks and command pages run a build of the checkout's HEAD in a checkout the person lists in ~/.abcd.noindex/dogfood-roots, and the installed release everywhere else, because iss-2610070547057816 records that the person wants exactly that, so no question was put. It does not conflict with AGENTS.md's go run rule: that rule governs the agent's own invocations in a source checkout and leaves the surface half to iss-2608230943088357, which this change addresses for the hooks and command pages (facilitator on delegation, lane D, 2026-10-28).

  • dcn-26102808575490362026-10-28

    2026-10-28 — Model-matrix step 2 (itd-2610161733316518) bounds every figure of money a matrix run names at 1,000,000 usd and makes a plan that cannot be encoded have no digest, refused at the plan and at consent. Grounds: an unbounded per-copy cost could sum to infinity, the plan then failed to encode and every such plan shared the digest of empty input, so one approval would match any of them; no real run costs near the bound. Found by the step 2 review pair.

  • dcn-26102808524716252026-10-28

    2026-10-28 — Model-matrix step 2 (itd-2610161733316518) builds dcn-2610280629294458 in two halves: a run starts only from a plan whose every cell source resolveCell derived from the cell's parsed route and this machine's provider configuration, consented to by its digest; and the run record's pinCells refuses a pin that disagrees with what the route itself fixes (the host leg pinned host and nothing else, a runner route on its own runner and <provider>/<model>). A claude-runner cell is a runner route like any other and names its model: the claude runner runs bare on its API key, so it spends and is never the host, which runs in the host's own harness (decision 10). pinCells does not re-read the provider configuration to tell openrouter, local and provider apart: that split is the configuration's, the plan already reads it, and the plan's digest binds the person's consent to what it read. Grounds: the named risk, a provider route pinned as host skipping the spending cap and provider-pin checks, is the host/route disagreement the record now refuses.

  • dcn-26102808363177392026-10-28

    2026-10-28 — A --route whose runner falls back to the host is not recorded on the fallback receipt; the build brief and the implement page now say so, instead of the fallback receipt gaining an override field. Grounds: the fallback receipt already names the runner asked, the role then ran on the host so no route ran it, and adding a field would need its own run-state refusal case for version 15 and earlier for a reading nothing yet uses. The drain's route record carries the override field only because it shares the route record with the run state; no drain flag sets it, and the drain brief and drain.go now say that (review of the route-r2 branch).

  • dcn-26102807431601342026-10-28

    2026-10-28 — Route-runner-model r2 (iss-2610161801358637), rebased onto local-pin-r2: a route record's override joins run-state version 16 with a route's pins, and drain-state version 2 with a judge route's pins, rather than taking version 17. Grounds: r2 already joined the override to the pins' version while neither was released, version 16 is still unreleased (local-pin-r2 lands just before r2), and a version holds the unreleased additions that land together; a file of version 15 or lower carrying override is refused, as before. If a release writes version 16 before r2 lands, r2 moves the override to version 17 before it lands.

  • dcn-26102806350922222026-10-28

    2026-10-28 — The check job's ubuntu leg gets a 45-minute ceiling again, with its elapsed-time warning ten minutes ahead at 35, the same lead the macOS leg has. Grounds: merge-group runs of that leg took 29, 29 and 29 minutes and a fourth was cancelled at its 30-minute ceiling a second after its race tests passed, which rebuilt every group queued behind it; the leg's time follows the change and the runner (19 to 30 minutes over the last nine runs), and 45 is the value the leg already held from 2026-10-17, still well under the merge queue's 90-minute response timeout. The warning now runs on every leg, so the ubuntu leg reports nearing its cap the way the macOS leg does, and the remedy for a leg past the warning stays a faster suite, not a further raise. Decided by abcd-0b, the coordinating session's delegate, on delegation from the technical facilitator (technical).

  • dcn-26102806292950692026-10-28

    2026-10-28 — Model-matrix step 2 (itd-2610161733316518, spc-2610161949559050), the step that first writes a procedure's records, makes the lab sweep pass over them, and step 1 leaves the sweep as it is. Grounds: the sweep exempts a probe's capture files as instrument output (its input, command line, exit status and output); a matrix declaration is a run's input and its run and trial records are what it ran and measured, never rewritten, so a retraction swept into one could never be applied and would halt the lab for good. The exemption keeps the sweep fail-closed: it covers only the regular files, within the record bound, whose paths a procedure can write under state/matrix/, so anything else there is still read or listed as not swept; and the same change adds state/matrix/ to the sweep's documented exemptions in the lab sweep help, the generated CLI reference and the lab brief. Step 1 cannot carry it: nothing writes there before step 2, and the generated reference is held by other reservations tonight. Found by the step 1 review pair.

  • dcn-26102806292944582026-10-28

    2026-10-28 — Model-matrix step 2 (itd-2610161733316518, spc-2610161949559050) derives each cell pin's source (host, openrouter, local or provider) from the cell's parsed route and refuses a pin whose source disagrees with it, because step 1's pinCells takes the source as given and a provider route pinned as host would skip the spending-cap and provider-pin checks (decisions 6 and 17). Step 1 cannot check it: the route grammar is parsed only where the run starts, in step 2. Found by the step 1 review pair.

  • dcn-26102802335753542026-10-28

    2026-10-28 — Merge-gate step 2 (itd-2610150602547271, spc-2610161609350616): until step 4 wires the merge gate to read facilitator.mode, the board names a person as the merger in every repository and draws an auto as set but not yet read, never as abcd merging. Grounds: landing's mergeGate still runs ruling AM1, so every repository is in human mode today, and a board saying abcd merges would contradict what abcd land does in the same repository; the spec has step 2 name the mode and its layer, which the line still does. Step 4 changes the wording when the gate reads the mode. Found by the round-2 review pair.

  • dcn-26102802322641982026-10-28

    2026-10-28 — When another copy's reservation on a shared file keeps being renewed past its expiry while a lane's branch waits at the pull-request step, the lane compares changed hunks instead of whole files. It fetches the other copy's pushed branch or open pull request for that reservation and diffs it against its own branch on each shared file. Where no hunk overlaps and neither side edits the same function or the same entry of a registration list, the lane opens its pull request, names the overlapping reservation in the body and states that the hunks are disjoint, and leaves a real conflict to the merge queue. Two edits in one function count as disjoint when they are separate statements with no data dependency between them (ruled 2026-10-28 for route-runner-model-r2 against #1153 in readDrain). Where hunks overlap, or the other copy's branch is not on origin, the lane keeps waiting and reports to its coordinator only if that still holds at 04:30Z. Where the other machine's hold overlaps only in files, has a different subject and has nothing pushed, the ready change lands and the second lander merges main; wait only when the subject overlaps (the same record or the same behaviour). Grounds: the laptop's holds on cli.go, pending.go, install.md and mentions.go rolled forward at 02:36Z for at least another hour, a whole-file wait would hold the store and sweep change that lane D's peers-cap major depends on for as long as the laptop keeps working, and a reservation guards against overlapping work, not against two disjoint edits to one large file. Applied first to store+sweep and ahoy-remote-refusal, then to pr-title-refs and run-1054. Ruled by the coordinator, abcd-f5, for the crash-recovery lanes on 2026-10-28.

  • dcn-26102800360194592026-10-28

    2026-10-28 — Resolve iss-2610110253059544 as fixed on main rather than landing the 12 October gitutil-probe branch. Main's iss-2610181802344551 work already does what the issue's remedy asks: the version probe runs under the caller's deadline where it has one (atLeastContext) and within 30 seconds where it has none (probeGitVersion), the lock is not held while git runs, git is killed at cancel (CommandContext with WaitDelay), a failed probe is not cached, and TestAContextBoundReadEndsAtItsDeadlineWhileTheVersionProbeHangs proves the call returns by its deadline and no git is left behind. The branch's 250ms fixed deadline conflicts with that design, and rebasing it would mean rewriting it against code that already answers the issue. The branch stays as it is, unmerged.

  • dcn-26102723522496012026-10-27

    2026-10-27 — Peers-cap review notes deferred past its landing (lane D, facilitator on delegation, 2026-10-27): the rebased review pair of fix/peers-cap-warning returned LAND-WITH-NITS from both reviewers with no blocker. Its one display gap, the ceiling's note missing from the text form, is fixed on the branch. Three notes are captured and deferred to a follow-up change: iss-2610272352153282 (one sibling named two ways), iss-2610272352168723 (clashing sibling names merged) and iss-2610272352179242 (the cap refusal drops the listing note and labels copies without a holder filter). Grounds: none changes a count, a refusal or a reservation, only how a hold's copy is named; peers-cap resolves the major that blocks the release (iss-2610231004140527); and the first needs one worktree listing shared with the default branch's sibling naming, a refactor across both that wants its own review rather than a fifth round on this one.

  • dcn-26102723454010092026-10-27

    2026-10-27 — A path to something that exists in the working directory is not withheld at the error boundary, a leading part of an argument is withheld only where a refusal visibly cut it, and build's claim-stage refusals name the --session flag instead of the session they were given. Grounds: an existing repository path is what a footprint or record refusal must name for the caller to see the overlap, and nothing secret is a path that exists in the checkout; a leading part followed by an ellipsis, a closing quote or the end of the line is a cut, while one followed by more of a path is a longer path that shares the prefix, so withholding only the first keeps overlap refusals readable. The session refusal was first kept on the premise that only a joined session reaches it. That holds for the claim itself, but opening the shared run for the session refuses any value first, one that is not a name or a name that has not joined, and repeats it; the reason goes into the refusal document build writes under --json, which the error boundary does not read, so both refusals name the flag, like build's other refusals there. Only the phrases that name the session (session followed by the id, typed or quoted, the session record for the id, and the record's file name) are replaced, in one pass, never the id wherever it appears: a session id may be one letter or a word the refusal itself uses, and replacing every occurrence made the refusal unreadable. The phrases are matched as text, never compiled from the id into a pattern, so no value given can make the replacement fail; the refusal for a claim another change holds the run lock against passes through the same replacement. The same document carries the refusals of a run id given to --run and a lane id given to --restart, so those describe the value instead of quoting it, and a refused --restart leaves the document's lane field empty. A well-formed run id is not withheld at the boundary either: abcd mints it, like a record id, and a refusal that cannot find the run must name the one it looked for. A flag whose value is drawn from a vocabulary abcd defines declares that vocabulary, and a typed word of it is not withheld: it is abcd's own word, and a refusal of a word valid elsewhere (a disposition state the item's position does not offer) must name it; a value outside the vocabulary is withheld as before. Two limits are accepted. A session id that is itself a word following 'session' in a refusal's fixed wording reads oddly once replaced, because text matching cannot tell the id from the wording; only the core returning the session as its own field would. And the session follows the boundary's floor everywhere the boundary judges it: an argument under that floor is not withheld there, a session included. Decided by abcd-0b (technical, delegated).

  • dcn-26102722135332722026-10-27

    2026-10-27 — Merge-gate step 1 (itd-2610150602547271) ships refusing a claimed namespace's case twins and its dotted form, but not a misspelt or padded namespace at a file's top level, captured as iss-2610272213410875. Grounds: both review-pair members found no way past the human-wins rule other than a top-level misspelling; that gap applies to every claimant of the layered reader alike, not to this step, and closing it needs a design choice between a top-level key registry and a near-miss check, which is its own change. Decided by the agent under the autonomous-run delegation of 2026-10-27.

  • dcn-26102722025401402026-10-27

    2026-10-27 — The stop hook's note on an unreadable continuation-cap setting gives the value's length instead of the value, in this branch. Grounds, under the abcd-fixes-what-it-adds rule: the note is abcd's own print, so the way the value reaches stderr exists only with abcd and is abcd's to change; it landed after v0.15.1, so no release carries it and it changes in the same cycle that names it, with nothing further owed for any release. Decided by abcd-0b (technical, delegated).

  • dcn-26102721401381562026-10-27

    2026-10-27 — The worktree store's steps 2 to 6 and the sweep's step 1 land as one pull request, and the sweep's entry points are unexported until its surfaces, decided by the technical facilitator's session abcd-e8 on the product thinker's standing delegation of 2026-10-27. The exported-reach audit refuses an exported core function no production code outside its package reaches: the store's PruneOne is reached only by the sweep, so a store-only pull request fails it, and the sweep's dry run, apply, probe constructor and host process lister are reached by no front door until step 5, which exports them as it wires them. Unexporting is the audit's own remedy for a function only its package uses; adding them to its baseline is refused by design.

  • dcn-26102721124014312026-10-27

    2026-10-27 — The worktree store lands with a merged, clean worktree reclaimed as planned, ignored files outside the local tier included, decided by the technical facilitator's session abcd-e8 on the product thinker's standing delegation of 2026-10-27. The second reviewer found that such files go unarchived and unmentioned; the spec adopts git worktree remove's own judgement on purpose, and changing it trades losing an ignored file against holding every worktree with build output, which is the product thinker's call. The finding and both remedies are captured as iss-2610272112319234 for that call.

  • dcn-26102721035838142026-10-27

    2026-10-27 — A refusal's last step withholds any argument the caller typed that still stands whole in it, and keeps three kinds: an argument under eight bytes, a command name, and a record id matching recordid.CitedIDRe, the one shared id grammar. Grounds: one step at the error boundary covers every verb, including a site no per-site rewording reached; shorter arguments are counts, letters and short words whose every occurrence would otherwise be rewritten; a command name and a well-formed id are what a refusal must name to be usable; and matching whole words only keeps a short argument from rewriting the inside of a longer word. A verb that writes its own --json document ahead of the error object is outside the step, so its own wording must not repeat the argument (build's key check is changed for that reason). Decided by abcd-0b (technical, delegated).

  • dcn-26102720354506722026-10-27

    2026-10-27 — The worktree store's /abcd board line says how many worktrees can be cleared, the words of the product thinker's 2026-09-30 planning ruling (dcn-2609300000000022), relayed as settled by the coordinating session abcd-f5 on 2026-10-27. The spec's line and the built line had drifted to reclaimable; both are corrected to the ruling. The --json member keeps the field name reclaimable, which the ruling does not name.

  • dcn-26102719462697592026-10-27

    2026-10-27 — The worktree store's board line keeps the peers scan's estimate for its reclaimable count, decided by the technical facilitator's session abcd-e8 on the product thinker's standing delegation of 2026-10-27. A change a crashed session left uncommitted, salvaged as commit 6f8012a0f, made the line count by prune's own judgement; it is reverted because itd-2609091014076309's acceptance criterion for the board line says rendering it starts no per-lane status read, and that judgement runs git status, the squash test and a notes read for every worktree in the lane on each render, while the 2026-09-30 planning ruling (dcn-2609300000000022) already accepts the scan's count as an estimate. The salvaged change stays in the branch's history and as a patch in the local tier. The line's words are settled separately: it says can be cleared, as that ruling names them (dcn-2610272035450672).

  • dcn-26102719462663652026-10-27

    2026-10-27 — The worktree store's notes-entry API (NewNotesEntry, NotesEntries, WriteNew, ReadFile, Flush), built ahead of its one named caller, the sweep's patch salvage in spc-2610230730269295, leaves the store stack and is kept on the local branch park/store-notes-entry until that caller is built, decided by the technical facilitator's session abcd-e8 on the product thinker's standing delegation of 2026-10-27. Grounds: AGENTS.md's wired-or-it-isn't-done rule refuses an exported API no production code calls, the review of 2026-10-27 found none on the store or the sweep branch, and dcn-2610231114308486 covers only PruneOne, PreRemove and Row.Path. The step that builds the salvage cherry-picks it back with its caller, and fixes the kind-suffix collision the review found (a worktree named x-salvage lists as x's salvage entry).

  • dcn-26102719263694252026-10-27

    2026-10-27 — Release hold, Q1 revised (facilitator on delegation, lane D on abcd-f5's ruling, 2026-10-27; supersedes Q1 of dcn-2610230328220298): a release reservation whose lease lapses with no release tag on origin ends its hold. The merges this cut recorded as withdrawn are re-armed, and only those, each with one comment on its pull request saying the cut lapsed. A merge the cut did not record is never armed. A cut that outlasts its lease renews it with abcd reserve rel-vX.Y.Z, so a live cut's withdrawals stay withdrawn. Grounds: on 2026-10-24 the person ruled that sessions do not hold merges for a lapsed release cut, which #1132 implements by naming a lapsed cut as holding no merge (iss-2610241104098581). That day two finished pull requests waited on rel-v0.15.2, a cut whose computer had crashed. Under the old Q1, merges such a cut withdrew stay withdrawn indefinitely, which contradicts that ruling. Q1's own risk, a cutter's next act re-arming merges mid-cut, is met by renewal: a cut that is still running is still renewing.

  • dcn-26102719260705232026-10-27

    2026-10-27 — Ruling by the product thinker on 2026-10-27, relayed by the coordinating session abcd-f5 and restated: the 23 Oct plans for the coordination intent itd-2610170634394993 and the terminal-drain intent itd-2610222215485265 land now, together with the checklist intent itd-2610170638184486 and its built steps 1 to 3 (spc-2610230805429429). This settles the overlap with the 24 Oct note in #1130 that the autonomy grant itd-2610240850336695, the checklist and the coordination intent are planned together as one bundle: that joint planning still happens, and it builds on what lands here rather than re-planning it. The rebase keeps every addition #1130 and the 25 Oct edits made to the three drafts.

  • dcn-26102719225024802026-10-27

    2026-10-27 — Majors ruling for the next cut, product thinker, 27 October 2026, on abcd-78's recommendations for the 17 hand-captured majors since v0.15.1. Fix before the cut: the eight recommended fixes (iss-2610251555094324, iss-2610241537197997, iss-2610241414124940, iss-2610241911052191, iss-2610241240133009, iss-2610241133284600, iss-2610241239492159, iss-2610241519088123) and five recommended for deferral that the product thinker chose to fix instead: the short install command in the docs (iss-2610240827243654), a worktree per session (iss-2610240859590333), clearing lapsed holds everywhere (iss-2610241107191205), the reflect criteria (iss-2610241431221889) and the measured home-folder receipt (iss-2610241551259104). Deferred one cycle: iss-2610241228359748, iss-2610240932215918, iss-2610241613191748. Amended and closed: iss-2610241427397332 (itd-3's obsolete criteria). The 69 consistency-pass majors are ruled on branch decisions/interview-2026-10-27.

  • dcn-26102719224932592026-10-27

    2026-10-27 — The reservation sweep joins the read-only fix for iss-2610231038335615 rather than waiting for a capture of its own. Grounds: the record names the sweep's dry run among the reads that wrote the empty tree; the sweep landed on main after the fix branch was cut, so the rebased branch would otherwise resolve the issue while one named read still wrote; and the sweep only compares chain trees with the empty tree's name and never commits on it, so the name-only form is enough. Decided by abcd-0b (technical, delegated).

  • dcn-26102719082377322026-10-27

    2026-10-27 — Release themes, product thinker, 27 October 2026: the next release cut must make abcd faster to build with, by managing the machine's resources intelligently (the self-adjusting preflight admission, itd-2610262127138979 and its two later pieces, with the load-gate issues they gather); the release after that must make it possible to work across accounts, computers and maintainers. This supersedes the earlier plan to cut the next release after 48 more hours of work (dcn-2610241420262850): the cut waits on its theme, not on a clock.

  • dcn-26102711123395162026-10-27

    2026-10-27 — The product thinker ruled on 2026-10-27 that each abcd command's behaviour is written once, in its command page, which agents follow when they run it. The brief's chapter for the command keeps why the command exists, its trade-offs and why it refuses what it does, with its sub-verb table and generated appendix, and points to the command page for behaviour. The documentation-fidelity check moves to the command pages. This reverses the behaviour half of adr-2609231028044006 and invariant 18, so a superseding ADR is owed.

  • dcn-26102711123391012026-10-27

    2026-10-27 — The product thinker ruled on 2026-10-27 that abcd's principles split in two. Design principles that shape how abcd helps a product thinker build their app ship with abcd, with one home inside what ships, and the install's orient step reads them there. Decisions and principles that are about building abcd itself stay in abcd's repository and never ship; the release rule that excludes .abcd/ stands. The platform page's statement that .abcd/ is present in marketplace installs is corrected.

  • dcn-26102711123387382026-10-27

    2026-10-27 — The product thinker ruled on 2026-10-27 that the technical facilitator signs off a new dependency, not the product thinker. The entries naming the product thinker, the glossary's among them, and AGENTS.md's sign-off line change to name the technical facilitator. In solo mode, where the facilitator is abcd itself, abcd then approves its own additions; the ruling was made with that stated.

  • dcn-26102711123346592026-10-27

    2026-10-27 — The product thinker ruled on 2026-10-27 that disciplines and design principles live in each repository, and that a person's own preferences are machine-local memory notes, allowed only where they do not contradict that repository's disciplines and principles. A lesson an agent learns is kept first as a note on the machine and reaches the project only when a person promotes it. The unbuilt user-scope curated pages are dropped.

  • dcn-26102711123315082026-10-27

    2026-10-27 — The product thinker ruled that every claim in the record has a single home, and settled the second question of the brief-size study with its recommended answers. The rule and its bounds live in every claim has one home; what the ruling means for the brief, answer by answer, is in the scope of the brief-rewrite intent, itd-2610290239150589.

  • dcn-26102711123305362026-10-27

    2026-10-27 — The product thinker accepted on 2026-10-27 the triage of the 1301 records the 2026-10-26 consistency pass filed. The duplicates, the records a later record already settles, the ones that are no contradiction and the one already fixed are closed with each reader's reason. Every other record gets its fix as its remedy, the rulings' accepted answers included, so a drain can take it. The 45 major records left open are deferred past v0.15.1, because the brief's single-home rewrite rewrites or removes most of the passages they quote. The person ruled the major rulings one at a time; the minor rulings take their recommended answers.

  • dcn-26102711123302352026-10-27

    2026-10-27 — The product thinker ruled on 2026-10-27 that the design brief shows the target design, in the present tense, with a status tag where a part is built, rather than the shipped state. With the ruling that behaviour lives in the command pages, the brief holds the product as aimed for and why, and the command pages hold what abcd does today. This reverses itd-147's currency rule, so a superseding ADR is owed, and the brief's checks are rebuilt around the status overlay.

  • dcn-26102711123300702026-10-27

    2026-10-27 — The product thinker ruled on 2026-10-27 that a repository's delete-branch-on-merge setting is the technical facilitator's: where the repository's facilitator mode is autonomous, abcd sets it; where it is human, abcd reports it as a gap and changes nothing. The ahoy chapter's stance that abcd mirrors merge-hygiene settings and never sets them gains that one exception, owned by itd-118 and cited by itd-106.

  • dcn-26102616515902562026-10-26

    2026-10-26 — Defer the fix for iss-2610261651489204 (the consistency ingest writes a summary past the reviews charter's 1 MiB) out of the low-CPU run of 2026-10-25. It needs a Go change proven by a test watched fail and then pass, and this run's rules allow no go test on the shared machine. This pass's report was split by hand instead: its findings table stays in 00-summary.md and the full findings are in 01-findings.md.

  • dcn-26102616172452312026-10-26

    2026-10-26 — Defer the fixes for iss-2610261616580903 (abcd capture writes a body the site renderer refuses) and iss-2610261617079475 (the drain test that fails when two run ids share a second) out of the low-CPU run of 2026-10-25. Each needs a Go change proven by a test watched fail and then pass, and this run's rules allow no go test on the shared machine. Both records carry their remedies, for the next build lane to take up.

  • dcn-26102611523294512026-10-26

    2026-10-26 — The product thinker adopted the remedies of iss-2609061525437969 (narrowed to pull-request bodies), iss-220 (its compose half only) and iss-2610241424265464, and asked for them and the newly filed iss-2610261151381604, iss-2610261151481013 and iss-2610261152125261 to be built first. Grounds: of 32 failed hosted CI runs between 2026-10-18 and 2026-10-26, 13 were deterministic checks that could have run before the push (a pull-request body without its Assisted-by line 7, an undeclared issue id on the pull-request form 4, gitleaks 2), and 10 more were one govulncheck finding that stood on the default branch itself. Each check moves to the earliest local point that sees its input: the commit-msg hook, the shell guard before gh pr create, abcd land's composed body, or the preflight before its test stages.

  • dcn-26102515554760982026-10-25

    2026-10-25 — Ruling by the product thinker on 2026-10-24, after no preflight could pass on one machine running seven sessions: quiet hours for landing. While one session's preflight runs, the other sessions pause CPU work (no preflight and no go test), so branches land in turn. The first to land is the fix that gives the unit stage a 40-minute budget and splits the three slowest packages into test shards, joined with the fixes for the tests that fail under load, since every other preflight needs both. The overnight cut planned in the release-plan decision did not run: it waits until that fix has landed.

  • dcn-26102501090703422026-10-25

    2026-10-25 — The records branch docs/review-set-and-planning-autonomy is parked, unpushed, from 2026-10-25 01:15 UTC. Four preflights failed on tests the branch does not touch: two timed out at the load gate, and two failed in main's suite. Those failures were the deadline and forge-budget tests under the live reservation iss-2610241911001655, three packages past their 20-minute timeout, and the stop-hook tests in the daylight-saving fold (iss-2610250107576049). The release cut's merge hold starts at 02:30 UTC. The branch is rebased and gets one gated preflight once that fix is on main and the hold has lifted.

  • dcn-26102415173366902026-10-24

    2026-10-24 — Rulings by the product thinker on 2026-10-24 for PR #982 (memory pages join the recall), on the three choices its reviewers sent to a person: a page larger than the whole per-turn budget is set aside with a warning, as built, rather than retried each turn; machine-wide memory pages are labelled as ingested from outside sources, not as the person's own memory, which needs a change to the PR before it merges; and ties go to the page ingested most recently, as built. The PR stays held until after the overnight release.

  • dcn-26102414501553472026-10-24

    2026-10-24 — Reservations refuse while any embargo store under the home cannot be read, by design: abcd reserve and the build and drain reservations ask the same outbound embargo check abcd announce does, which reads every embargo store under this account's home, so one store whose state cannot be read refuses every reservation, renewal and take-over on the machine until it is settled. A release is not checked, so a reservation that stands can always be ended. The refusal names the store's path and the reason's own repair, so the fault is found from any checkout. Failing open would read a store that cannot be read as holding nothing, as every other outbound check refuses to; the cost of failing closed is one repair, and it lands on the person who owns every store under that home

  • dcn-26102414202628502026-10-24

    2026-10-24 — Release plan from the product thinker, 2026-10-24: sessions keep building for about 12 more hours, then this machine cuts the next release overnight (from about 02:30 UTC on 25 Oct), and work then continues for another 48 hours before the release after it. Sessions park their landings while the cut's rel-vX.Y.Z reservation is live on origin, which tests the GitHub-carried hold. The crashed computer's v0.15.2 cut is not resumed as such: the overnight cut carries everything merged since.

  • dcn-26102413041870322026-10-24

    2026-10-24 — The disembark graveyard, principles and press-release ingests secret-scan what they write with the bundled rules on the lifeboat directory, not the source repository's scanner settings; only disembark review, which already takes the source repository, scans with the source's settings. Those settings only add detection: the review runs the built-in scan over the lifeboat, as the other ingests do, and the scan under the source's settings beside it, and refuses what either refuses, so its scan is the union of the two and nothing the source declares can clear a built-in hit. Those three verbs are given only the lifeboat, their text comes from the person's own agent, and the bundled rules cover the common token shapes, so adding a source operand to each is not worth its surface. Revisit if a custom pattern or the gitleaks augmenter is ever needed for lifeboat prose.

  • dcn-26102412565473452026-10-24

    2026-10-24 — The build of itd-2610240922461281 (spc-2610240951109420, the review set as a setting) waits until two things hold: this records branch has merged, because the build's brief stage refuses an intent that main does not carry as planned; and the drain's live reservation on internal/core/implement/loop (iss-2610142134353345) is released, because the spec's footprint names that package and two builds whose footprints overlap back off. It is deferred, not dropped: the session that planned it starts it once both hold, with one sub-agent at a time and one preflight at a time, as the 2026-10-24 machine-load rules require.

  • dcn-26102412285984852026-10-24

    2026-10-24 — Held for the product thinker: criteria 3 and 5 of itd-2610240823055889 conflict when the assistant's settings file exists. Criterion 3 makes the status line (the assistant's settings) its own person-approved question, and criterion 5 allows four questions (download, shell settings, plan, identity) plus one per tool, so a fresh account can be asked five. The build keeps the status-line question separate, the side on which nothing changes without a yes, and the spec close records criterion 5 as not met in that case until the product thinker rules: count the status line in the budget, fold it into the download question, or move it onto the plan screen.

  • dcn-26102411583084872026-10-24

    2026-10-24 — Deferred out of the setup redesign: iss-2610241157493381 (the session-end retry test fails under machine load because its retry budget is wall-clock). It lies outside the redesign's footprint (internal/surface/cli/hook_subagent.go, history capture), fails on an unchanged branch, and is recorded so it is fixed on its own rather than stepped over; the redesign's checks report it as a known failure, not a pass.

  • dcn-26102411104632522026-10-24

    2026-10-24 — Deferred by drain session abcd-0d on 2026-10-24, while clearing pull requests a crashed computer left open: #1116 (refuse the host's approval prompt while a build or drain runs) conflicts with main and is deferred until it is rebased; #1105 (dependabot go-deps) fails its required checks and waits on the dependency re-author workflow; #996 says in its own title to merge after v0.16.0; #1010 and #982 are drafts their author has not marked ready; #1120 belongs to live session abcd-78, which lands it. #1117, #1119, #1110, #1111 and #1114, each reviewed by an Opus and Sonnet pair with every required check green, were put in the merge queue on the product thinker's instruction to auto-merge what is sensible.

  • dcn-26102410162081642026-10-24

    2026-10-24 — dcn-2610181016510153 is reversed in whole by adr-2610240850193281: the away mode no longer grants nothing, and a session no longer sets it on the person's word. A person-set autonomy grant now permits pushing a session's own branches, opening their pull requests and answering its own questions as a named role, set only by the person's explicit command; dcn-2610181003456444's person-only guard is reinstated with that wider grant (itd-2610240850336695). The reversal's grounds: a grant only removes a stop and needs no fence, which the reversed decision's boundary argument did not separate.

  • dcn-26102408455487762026-10-24

    2026-10-24 — Tool installs default to a verified download, on macOS and Linux alike: abcd fetches the tool's official release, checks it against the release's published checksums (and its signed build record where the project publishes one), and puts it in ~/.local/bin, needing no admin rights; this is the route abcd already uses to install itself. Homebrew is not the default, because a supported Homebrew for one non-admin account cannot be created by abcd on a Mac (Homebrew's installer refuses a prefix longer than /opt/homebrew, so no home-folder prefix fits) and a shared Homebrew is often not writable by the person. Decided by the product thinker on 2026-10-24 after the Homebrew-without-admin research (iss-2610240824571059).

  • dcn-26102311143084862026-10-23

    2026-10-23 — The worktree store's PruneOne, its PreRemove hook and Row's absolute path land in step 2 with no production caller, as the API the sweep (spc-2610230730269295) calls: its removal is the store's prune core called per worktree, with its liveness probe as the last check before each removal, and its rows need each worktree's absolute path. They stay uncalled only until the sweep lands, which the merge order puts after the store's step 2; if the sweep's plan changes so that nothing calls them, they are removed rather than left as scaffolding. Facilitator, on the technical delegation.

  • dcn-26102310335162932026-10-23

    2026-10-23 — Release hold (iss-2610222014550692), round 6, ruled by the coordinating facilitator on delegation while the product thinker is away. A person's record on a release reservation is the newest commit the forge's record of pushes shows that person pushed. Commits above it that another login pushed are never read: they are reported, by count and pusher, to the cutter and on peers. If that person's newest push cannot be found or placed, abcd acts on nothing for them (no re-arm, no withdrawal, no admission), names why on a line the cutter sees, and peers shows the same. A renewal over a later commit renews from the person's own newest commit, keeping what it records, admissions included, and the lost-withdrawal window never applies to a person's own record. Rejected alternative: checking each later change entry by entry, which five review rounds showed has to be extended for each new shape of later commit: one entry dropped and re-added as settled, two changes in a row, a change beneath an unreadable commit, a change beneath more commits than the walk reads, a tombstone dated outside the window, and a renewal over another login's tombstone. One rule covers all six, and honest use is unchanged, because a person's own record is always their newest push. The admit refusal's remedy reads: the withdrawer takes the release back with --take-over and admits it; a test runs that remedy end to end.

  • dcn-26102310115326592026-10-23

    2026-10-23 — The worktree store's steps 3 and 4 land with the merged judgement reading a branch's own commits from its reflog, after four review rounds closed every reflog shape that gives a false merged except one (iss-2610231011465325): a copy of a created branch, force-reset and left until its reflog expires. It is deferred to step 2 rather than chased further, because each closed shape exposed another and the sound fix is a different source, not a better reflog read: step 2's add records the branch's start commit in the lane, and the judgement then reads the branch's own commits from that. The case needs three rare acts together, every commit it holds is already on the default branch, and the store never deletes the branch. Facilitator, on the technical delegation.

  • dcn-26102309282719392026-10-23

    2026-10-23 — The finding in iss-2610230927379322 is deferred out of the release-hold change (iss-2610222014550692), ruled by the coordinating facilitator on delegation while the product thinker is away: the merge hold that abcd land respects still reads any tombstone on a release reservation as the release's end, whoever pushed it, so land and the launch check can disagree about one release. Reason: the land hold already ends when its lease lapses, so it is a time-boxed courtesy; the withdrawal the release-hold change adds is what keeps merges out; and a change to every land check deserves its own review. The same session fixes it as its first work once the release-hold pull request lands, not at a later date.

  • dcn-26102308574110932026-10-23

    2026-10-23 — Decided by the technical facilitator on delegation (coordinator ruling, 2026-10-23), on iss-2610230016561927 (a build run serialises every lane on the previous lane merging): the finding's cause is authoring, not code. A spec step's needs line is already honoured, and a step with none waits for every earlier step (ruling DR6b), but only 5 of 169 specs on the default branch declared any needs line, so nearly every run defaulted to fully serial. Remedy, in order: first, intent ready and the spec's record-lint warn on a spec of two or more steps with no needs line on any step, saying the steps run fully serial and naming the fix, and the planning page and interviewer ask for each step's needs; a warning, never a refusal. Second, stacked readiness (a dependent lane starting once its predecessor is reviewed and landed on the run's own branch) is captured as its own record and draft intent for planning, not built now. Rejected: a default derived from footprints, running a step with no needs line in parallel when its packages are disjoint from every earlier step's, because file overlap misses logical dependencies (step 3 calls a function step 2 adds, in another file) and a wrong parallel step costs more than a serial one. Backfilling needs lines on the open specs is captured separately.

  • dcn-26102308401609142026-10-23

    2026-10-23 — The technical facilitator on the product thinker's delegation (merge gate step 3, spc-2610161609350616, itd-2610150602547271, 2026-10-23): a review receipt is recorded with a repeatable --record-review <return> flag on abcd land, not a land sub-verb, because land's positional argument is a branch name and a sub-verb such as review would shadow a branch of that name; recording lands nothing. A receipt is written only when at least two returns each name the head's first nine characters and state SHIP or APPROVE, so a review of an earlier head cannot be recorded for a later one, and it lives in .abcd/.work.local/review-receipts/<full sha>, found from any worktree through the same lookup the preflight receipts use. The verdict parser in landing is the shared one the build loop's validator parser can move onto later; landing cannot import the loop.

  • dcn-26102308333679842026-10-23

    2026-10-23 — Release hold (iss-2610222014550692), round 5, ruled by the coordinating facilitator on delegation while the product thinker is away. A person admitting a pull request that another person withdrew, after taking over their release, is refused, with the reason and the remedy named: the withdrawer admits it, or takes the release over themselves. This matches the rule that another person's copy never re-arms, and a refusal can be relaxed later, where an arm made across accounts cannot be undone. Every real disarm abcd makes gets a comment, including a first withdrawal made on a retry and a second one after the owner re-armed by hand. The comment sentences are fixed: re-armed reads 'abcd release hold: the merge of #N is re-armed; the hold for release vX has ended.'; already armed reads 'abcd release hold: the merge of #N is armed; the hold for release vX has ended.'; not re-armed reads 'abcd release hold: the merge of #N is not re-armed; the hold for release vX has ended.' followed by one clause: head moved 'Its head changed while it was held, so its owner needs to re-arm it.', no merge queue 'It can merge now and there is no merge queue, so its owner can merge it.', refused 'GitHub refused to re-arm it five times, so its owner needs to re-arm it.', closed 'It was closed.', merged 'It was merged.'. Any other state posts nothing, and neither does a mismatched node id or a partial withdrawal. The withdrawn and admitted sentences are unchanged. The pull request lists every sentence so the product thinker can review the posted wording before the first real cut posts it. A change to a withdrawal's state counts only when the withdrawer's own push carried it, and a tombstone ends the hold only when the holder pushed it; anything else is reported and not acted on.

  • dcn-26102308130640582026-10-23

    2026-10-23 — The product thinker's walk and sign-off of itd-2610222215485265 on 2026-10-23 (09:00 to 09:15 BST, in abcd-ae's session), restated. The six person-visible stories are kept, both parts of the technical list are accepted, and the press release's two parts, the mechanism (how we will know it worked), the scope conditions (where it holds) and the reason for doing it now with what comes with it are signed off with no wording change. That last part accepts, with the plan, the record that lets abcd start agents itself on this opt-in path: adr-2610222222326104 is accepted, and AGENTS.md's host-delegated boundary names it as the one written exception, not built until the intent ships. The record's text was aligned to what the product thinker was shown: the scope now says the fence and the login check apply to the helpers abcd starts, with a drive the person starts and watches possibly counting as attended; the live test asks its own yes because it spends the person's usage, not API money; and the ADR, which still said the drive runs only on an API key and that a subscription-only person cannot drive, now carries the earlier rulings that the runner defaults to the person's subscription behind a wall, with an API key optional per configuration (dcn-2610230716408975, dcn-2610230710469123). The intent is planned on this sign-off.

  • dcn-26102308053253962026-10-23

    2026-10-23 — The product thinker's walk and sign-off of itd-2610170638184486 on 2026-10-23 (about 10:05 BST, in abcd-ae's session), restated. The eleven person-visible stories are kept and the technical list is accepted in full. The press release is signed off in its four parts with one wording fix, shown to the product thinker before they signed: the kinds of choice the checklist carries are those decided overnight and listed for the morning (security, performance, compatibility), not those still raised with a person, matching their ruling of 2026-10-22 that such trade-offs are decided and listed. The grounds, the scope conditions, and the reason for doing it now with its build order (the checklist file first, from the compaction issue iss-2610222026223032, then the waits, promises, wakes, blocker sweep and return lists) are signed off. The intent is planned on this sign-off; abcd mints one spec per plan, so the second half is carried in the first spec as its remainder and split off with spec close --remainder when the first lands.

  • dcn-26102307575562832026-10-23

    2026-10-23 — The product thinker's walk and sign-off of itd-2610170634394993 on 2026-10-23 (about 09:50 BST, in abcd-ae's session), restated. The shared model budget is per computer: sessions on one computer share one pool, and a session on another computer or account draws on that computer's own pool, which narrows the draft's scope condition that the budget spans every account of an organisation. The ten person-visible stories are kept, the budget story in its per-computer form. The eight-hour key of a cloud run is kept: asked why eight, the product thinker was told that GitHub sets eight hours for an app's user access token and that its renewal stays on the person's computer, and kept it. The technical list is accepted in full. The press release, the mechanism and its grounds, the scope conditions and the reason for doing it now are signed off as written. Choice 1 had been ruled earlier (dcn-2610230710469123). The intent is planned on this sign-off.

  • dcn-26102307164089752026-10-23

    2026-10-23 — The product thinker's ruling of 2026-10-23, restated, narrowing ruling RN2 (dcn-2610020000000016) for the terminal drive (itd-2610222215485265): a drive runs the person's own unmodified claude CLI on their subscription by default, walled off from their own setup, and on an API key only when their configuration asks for it. The wall on the subscription route is a dedicated CLAUDE_CONFIG_DIR the person logs into once, CLAUDE_CODE_DISABLE_CLAUDE_MDS=1, CLAUDE_CODE_DISABLE_AUTO_MEMORY=1, --strict-mcp-config with an empty --mcp-config, --settings with disableAllHooks true, and --no-session-persistence, with ANTHROPIC_API_KEY unset; abcd never reads, stores or forwards the login token. The API-key route keeps --bare. Grounds: a check of the vendor's current docs on 2026-10-23 found that an end user may sign in to the unmodified CLI with their own subscription, that only other apps may not use or handle that login, and that --bare, the one documented full seal, reads no OAuth login and so needs an API key. The docs are silent on settings.json under --bare, claude.ai connectors under --strict-mcp-config and plugin hooks under disableAllHooks, so the walls are proved in a live run before anything else is built, and a drive refuses to start when any wall fails. Whether the build runner takes the same default is a follow-up for the product thinker.

  • dcn-26102307120840992026-10-23

    2026-10-23 — Release hold, Q2, the product thinker's ruling of 2026-10-23, relayed by the coordinating session abcd-ae, superseding dcn-2610230328230097 (which kept it off by default): when abcd withdraws someone's armed merge for a release, it posts a fixed-form comment on that pull request, and posts again when the merge is re-armed, admitted into the cut, or skipped, naming the reason. This is on by default. Each comment is one fixed sentence naming the release, judged by the outbound policy before it is posted and read back from the forge after; a comment is posted once for each change of state a push records, and one that fails is reported and never holds up or undoes the withdrawal or the re-arm.

  • dcn-26102307104691232026-10-23

    2026-10-23 — The product thinker's ruling of 2026-10-23, restated, narrowing their 2026-10-22 C1 answer (dcn-2610222025104969): only the helpers abcd launches on its own, the build and drain lanes, must run away from the person's GitHub login. The person's own sessions working while they are away keep running on their own computer under their login, and a drain the person starts and watches may count as attended. It settles choice 1 of the coordination intent (itd-2610170634394993) and choice 2 of the terminal-drain intent (itd-2610222215485265), and the login check before an unattended run (dcn-2610222030477927) covers abcd's own launches only.

  • dcn-26102306305067262026-10-23

    2026-10-23 — The memory-recall spec stays open when steps 3 and 4 land, with no close and no remainder (facilitator, on abcd-ae's question of 2026-10-23; spc-2610111627213138, itd-2610091918433290): PR #982 delivers steps 3 and 4, so steps 1 to 4 have landed, but steps 5 to 8 (how full the session is, context brackets, the docs and brief, and the live session with the doc-fidelity review and the close) are not built, so the spec is not closed and the intent stays planned; a --remainder close would only move those four steps into a new spec under the same intent, which adds a record and changes nothing, so the open spec keeps them and the change carries no Delivers trailer (grounds: AGENTS.md definition of done, a change that delivers part of an intent carries no trailer; commands on spec close --remainder)

  • dcn-26102306093004452026-10-23

    2026-10-23 — Live brief sessions lands its code on Sunday but its intent stays planned, because one acceptance criterion is not met (abcd-ae's ruling as coordinator on 2026-10-23, recorded on the product thinker's delegation; itd-2610091016262335, spc-2610141709430146): the intent-fidelity audit (Opus with a Sonnet second, receipt rcp-a260a0a30612) found ac-21 NOT MET, since cloud setup takes about six steps and abcd never records the relay's address itself where the product thinker's criterion promises two one-click steps with the address recorded, and ac-6 INCONCLUSIVE, since a guest from another tailnet was never exercised; of the rest 5 are met and 16 met with concerns, mostly on tests that read the page's source; so the spec is closed with a remainder, spc-2610230609005313, which carries the setup gap as a draft, the code still lands, and the intent ships only when the remainder closes; changing the criterion instead is the product thinker's own choice and is put to them as an information item, never made here

  • dcn-26102305214884022026-10-23

    2026-10-23 — Release hold, reading of Q1 (facilitator on delegation, iss-2610222014550692 round 3; reads dcn-2610230328220298): after the tag, or any tombstone, each withdrawal is re-armed by a copy of the person who recorded it (its By, the holder of the reservation commit that first recorded it, as the branch's history and the forge's record of pushes show), not by the reservation's current Abcd-Holder. Grounds: under the letter of Q1, another person's take-over followed by their --release would leave the first holder's withdrawals with nobody able to re-arm them, since a re-arm runs under the re-armer's own GitHub account and only the withdrawer's own copies re-arm. The tag sweep's every-act scope is unchanged.

  • dcn-26102303282429292026-10-23

    2026-10-23 — Release hold, Q4 (facilitator on delegation, abcd-ae ruling 2026-10-23): withdrawals an older binary dropped by renewing without the Abcd-Withdrawn trailers are recovered by walking the reservation's ancestry for unsettled withdrawals and reporting them as lost.

  • dcn-26102303282300972026-10-23

    2026-10-23 — Release hold, Q2 (facilitator on delegation, abcd-ae ruling 2026-10-23): abcd does not comment on other people's pull requests when it withdraws or re-arms their merges; peers and the tombstone carry the trace. A fixed-form comment writer is built behind a seam, off by default, pending the product thinker's decision, since posting on others' PRs is new outward-facing behaviour.

  • dcn-26102303282300962026-10-23

    2026-10-23 — Release hold, Q3 (facilitator on delegation, abcd-ae ruling 2026-10-23): when the forge refuses a re-arm because the repository has no merge queue and the PR is already mergeable, abcd records a terminal needs-manual-merge state and reports it to the PR's owner. abcd never merges someone else's pull request outright.

  • dcn-26102303282202982026-10-23

    2026-10-23 — Release hold, Q1 (facilitator on delegation, abcd-ae ruling 2026-10-23; supersedes the amended 2A trigger): a release counts as ended only when the reservation holder runs --release (including after a same-person --take-over) or when the release tag is seen on origin. A lapsed lease is reported on peers and in launch, never acted on. The tag sweep still runs from any copy whose holder equals the reservation's Abcd-Holder. Grounds: with lapse-as-ended, three round-1 reviewers reproduced the cutter's own next act re-arming withdrawn merges mid-cut, because nothing renews a release lease.

  • dcn-26102302161945942026-10-23

    2026-10-23 — The technical facilitator on the product thinker's delegation (lane-1 review of run-2610230129496303, abcd-43, 2026-10-23): a model-matrix run's record (run.json) and the declaration it was read from (declaration.json) stay in the person's local tier, inside the run's lab, until a way to publish them exists that checks them for keys and paths first. Until then nothing publishes them, and both pass the repository's secret scanner before they are written.

  • dcn-26102302161399612026-10-23

    2026-10-23 — The technical facilitator on the product thinker's delegation (lane-1 review of run-2610230129496303, abcd-43, 2026-10-23): in a model-matrix run (itd-2610161733316518), a copy carrying a fallback receipt counts as a failure of its cell, as the intent's acceptance criterion on fallback copies says. A copy the compliance check excluded is named and counted apart, neither a pass nor a failure: it broke a rule of the run rather than failing the task, and the intent's SOTA line says rule-breaking runs are rejected before ranking.

  • dcn-26102301293312322026-10-23

    2026-10-23 — The model matrix's build footprint is step-wise and by file (abcd-ae's ruling as coordinator of 2026-10-23 for spc-2610161949559050, itd-2610161733316518, following dcn-2610222227336378 and dcn-2610222356532638): the spec's packages line named whole packages (internal/core/implement/loop, internal/core/runner, internal/core/oracle, internal/surface/cli and others) that the merge gate's, the worktree store's and abcd-f1's pin and route builds also change, so a directory reservation would hold them all for the days the matrix takes. The build reserves at start only step 1's sixteen files (the new internal/core/matrix package, internal/core/lab/procedure.go and its test, internal/core/lab/preflight.go, internal/README.md and ACKNOWLEDGEMENTS.md); each later step's files join the packages line when that step begins, and abcd build then reserves the widened footprint, judged for overlap. Generated output is reserved by no one.

  • dcn-26102300583331772026-10-23

    2026-10-23 — The merge gate reads the repository's declaration from the default branch, never from the branch being landed (the technical facilitator on the product thinker's delegation, from the lane-1 review pairs of run-2610222359421510, ruled by abcd-ae as coordinator, 2026-10-23): readMode(o.Roots) takes o.Roots.Repo, which is the landing branch's own worktree when abcd land runs there, so a branch that commits facilitator.mode auto, or deletes a repository-level human, would decide the gate for itself. Step 4 therefore resolves the mode from the default branch's committed .abcd/config.json together with the machine layer, human from either winning, and tests both directions. Every front door that prints a facilitator.mode refusal (the board in step 2, land and the loop in step 4, the guard in step 5) passes it through termsafe.Sanitize, as land already does (land.go:124), because the layered reader returns a hostile key's raw bytes.

  • dcn-26102300042637112026-10-23

    2026-10-23 — The technical facilitator on the product thinker's delegation (planning step 1 of spc-2610161609350616, abcd-43 for abcd-ae, 2026-10-23): the key stays facilitator.mode, the product thinker's own name for it in itd-2610150602547271, and the clash with abcd mode's facilitator state is settled in wording. abcd mode answers whose answer the loop is waiting on right now; facilitator.mode declares who merges. So the bare board names it by outcome, for example 'merges: a person (facilitator.mode human, from the bundled default)' or 'merges: abcd (facilitator.mode auto, from .abcd/config.json)', never a bare 'mode: human'; and commands/mode.md and commands/land.md each say in one sentence how the two differ.

  • dcn-26102223565326382026-10-22

    2026-10-22 — The merge gate's footprint is step-wise (abcd-ae's ruling as coordinator of 2026-10-23, spc-2610161609350616, itd-2610150602547271, following the worktree store's dcn-2610222227336378): the build reserves at start only the files steps 1-3, 5 and 6 change, leaving out internal/core/implement/loop/land.go and its test, which only step 4 changes and which the drain's reservation of iss-2610120138028442 holds while that lane waits for its preflight, and internal/surface/cli/cli.go, which only step 2 changes and which iss-2610171110154902 and iss-2610171200535090 hold until 2026-10-23T08:40Z; when the step that changes a left-out file begins, the spec's packages line widens to name it and a re-run of abcd build reserves the widened footprint (the verb reserves again when the spec has widened, per commands/build.md), judged for overlap like any reservation. Steps 4 and 6 still land as one change.

  • dcn-26102222282518882026-10-22

    2026-10-22 — The technical facilitator on the product thinker's delegation (ruled by the coordinating session, abcd-ae, 2026-10-22): spc-2610161609350616 (the merge gate) narrows its Footprint packages line from directories to the files its six steps change, because a directory footprint over-reserves and serialises unrelated work (it collided with the worktree store spec spc-2609301811532881 on internal/core/implement/loop and internal/surface/cli). Files still named by both specs (internal/core/board/board.go and its test, internal/surface/cli/cli.go, internal/surface/cli/board.go) are the merge gate's first; the store sequences its steps on them after the merge gate lands. Generated output (docs/reference/cli/commands.md, .abcd/development/release/surface.json and any other linguist-generated file) is reserved by no one and regenerated by whoever lands second.

  • dcn-26102222273363782026-10-22

    2026-10-22 — The worktree store's footprint is narrowed to the files its steps change (abcd-ae's ruling as coordinator of 2026-10-22, spc-2609301811532881, itd-2609091014076309): the spec's footprint named whole packages, among them internal/core/implement/loop and internal/surface/cli, which the merge gate's spec also names, so the first to reserve would have held the other off for days; each spec now names the files its steps' packages and tests lines change, read from those lines and never guessed narrow, and a file still in both after narrowing goes to the merge gate first, the store sequencing its step on that file after the merge gate lands; agreed with abcd-43 the same night: internal/core/board/board.go and its test, internal/surface/cli/cli.go and internal/surface/cli/board.go are the merge gate's first, so the store's footprint leaves them out until the merge gate lands and its steps 2 and 6, which need them, are not driven before then, the footprint then widening to take them; and the generated docs/reference/cli/commands.md and .abcd/development/release/surface.json are reserved by neither spec, since they derive from the code and whoever lands second regenerates them; and since other live lanes hold the brief and command-page files only step 7 needs, the footprint names step 1's files first and widens as each step is reached, which the build's reservation supports by reserving again with the widened footprint (grounds: AGENTS.md concurrent sessions, reserve with the footprint the work will change; the reservation's overlap rule)

  • dcn-26102222240567002026-10-22

    2026-10-22 — A runner fallback while driving hands the lane back as stuck, and runner failures in a row are an outage the drive waits through (facilitator, on delegation, itd-2610222215485265): a fallback hands its role to a host that does not exist, so the driver turns it into the existing stuck hand-back with the runner's reason and releases the reservation; three failures in a row, or a judge that fails, are treated as an outage, waited through at 1, 5 and 10 minutes then hourly and ended after eight hours, handing nothing back, since a hand-back makes an issue a person's for every account and a passing outage must not do that (grounds: drive.go; commands/drain.md on hand-backs and origin_wait)

  • dcn-26102222240558762026-10-22

    2026-10-22 — A drive runs a lane's preflight itself when its landing waits for a receipt (facilitator, on delegation, itd-2610222215485265): the landing pushes only on a preflight receipt naming the lane's head, which only make preflight mints and which a host runs today; the driver runs it in the lane's worktree through abcd implement load --wait, one at a time behind the machine's load gate, inside the person's yes (grounds: internal/core/implement/loop/land.go; the load gate)

  • dcn-26102222240546662026-10-22

    2026-10-22 — Ctrl-C or a hang-up stops a drive's running agent and leaves the open lane resumable (facilitator, on delegation, itd-2610222215485265): the runner's process group is stopped, the open lane keeps its worktree, branch and reservation, and the drive prints the run, the lane and when the reservation lapses, so the next drive or any host resumes it; nothing is handed back for an interruption, and a second signal exits at once as today (grounds: commands/drain.md on signals; the stuck hand-back's meaning)

  • dcn-26102222240497992026-10-22

    2026-10-22 — A drain drives itself only when --drive is given, never because no host was detected (facilitator, on delegation, itd-2610222215485265; revised after review round 1): a terminal inherited from a Claude Code shell carries its environment and a host that runs commands in a terminal sets none, so detection would start a drive by accident or block a host's call on a prompt; --drive is the one way in, abcd drain without it does one move per call as today, and the host's command page always calls it that way (grounds: the Opus and Sonnet reviews of 2026-10-22; brief invariant 16, a control asserts only what it can prove)

  • dcn-26102222240409672026-10-22

    2026-10-22 — While driving, a role the person left unrouted runs on runner.fallback_host, and a role a repository pins to the host refuses the start (facilitator, on delegation, itd-2610222215485265; revised after review round 1): runner.fallback_host is the existing key for the runner that runs a role when abcd has no host session, so no second default is added; when it is unset the person's yes may name the claude runner for that one drive, which is the person's own invocation and so a personal route under RN2; a repository's pin to the host has nowhere to run without one, so the drive refuses before its first move and names the role (grounds: internal/core/runner/config.go; RN2; commands/build.md on host pins)

  • dcn-26102222240407562026-10-22

    2026-10-22 — A drive asks before its first move, naming the cap, the estimated agent runs, the runner and its API key, and the answer is never remembered (facilitator, on delegation, itd-2610222215485265; revised after review round 1): asked at the first launch the question came after a reservation, which is the incident iss-2610222000271964 recorded; the default cap while driving is eight, the cap the product thinker's own drains use, and --drive --yes is the scripted yes where there is no terminal (grounds: RN2, a runner spends the person's paid key; the setup-consent rule; the 2026-10-22 recovery plan's drain at --max 8)

  • dcn-26102222224529602026-10-22

    2026-10-22 — Decided by the technical facilitator on delegation (coordinator ruling, 2026-10-22): the sweep command's liveness probe (itd-2610222214476887) reads /proc/<pid>/cwd on Linux and runs /usr/sbin/lsof by absolute path on macOS, with a deadline, a bounded read and defensive parsing, never cgo, because the released binaries are cross-compiled per platform; it fails closed, so when lsof is missing, times out or cannot be read every worktree it could not clear counts as possibly live and is left in place, named with the reason.

  • dcn-26102222192976512026-10-22

    2026-10-22 — Withdrawn merges are re-armed by the cutting copy when it ends the release reservation (on --release, or on its next abcd act once the tag is on origin), and as a fallback by any copy whose holder is the same person as the reservation's Abcd-Holder, on any machine or account of theirs, when its reservation fetch sees an ended release with withdrawals not yet re-armed; it writes a tombstone, and re-arming is idempotent. A copy of another person never re-arms: it reports the stranded withdrawals on its peers line and in a tombstone note naming the holder (iss-2610222014550692, choice 2A as amended). Grounds: a cut that dies mid-way, as on 2026-10-18, would otherwise strand every withdrawn pull request with nothing pointing at it; and re-arming runs under the re-armer's own GitHub identity, so a second contributor's machine would otherwise arm someone else's pull requests in its own name. Decided by the coordinating session on the product thinker's delegation while the product thinker is away, amending the technical facilitator's recommendation.

  • dcn-26102222192974872026-10-22

    2026-10-22 — A withdrawn merge is re-armed in the form it was taken from (auto-merge with its merge method, or a merge-queue entry), pinned with expectedHeadOid to the head it had when withdrawn; one whose head moved, or that was closed or merged meanwhile, is skipped and named on the tombstone and in peers for its owner to re-arm (iss-2610222014550692, choice 3A over re-arming the current head). Grounds: the re-arm then merges exactly the commits its author armed, never commits pushed while the cut held the branch that nobody armed. Decided by the coordinating session on the product thinker's delegation while the product thinker is away, on the technical facilitator's recommendation.

  • dcn-26102222192895252026-10-22

    2026-10-22 — A release reservation withdraws every merge already armed or queued on the default branch, and the cutting session keeps one in only by re-arming it with abcd reserve rel-vX.Y.Z --admit <pr>, which records it as admitted (iss-2610222014550692, choice 1A over a --keep list given at reserve time). Grounds: the cut then starts from a frozen branch and every merge into it is a recorded act; a keep list asks for the ruling before the cutter has seen what is armed, and a forgotten keep is a lost merge. Decided by the coordinating session on the product thinker's delegation while the product thinker is away, on the technical facilitator's recommendation.

  • dcn-26102222163502282026-10-22

    2026-10-22 — The plain-terminal drain's driver is a loop inside abcd drain, entered only by --drive, not a new verb and not a background service (facilitator, on delegation, itd-2610222215485265): the loop repeats the moves a host repeats, so the move logic stays one code path, and the terminal session is its lifetime, so nothing runs that the person did not start and cannot see (grounds: dcn-2610180720366282, no process that must stay alive; commands/drain.md, one move per call)

  • dcn-26102222163464482026-10-22

    2026-10-22 — The plain-terminal drain is one intent that refines the shipped drain bundle (facilitator, on the product thinker's delegation of 2026-10-14 and 2026-10-16, itd-2610222215485265): the decomposition table routes it FILE-AS-IS, since its fence (itd-2610161621364075), its routed judge's isolation (commands/drain.md) and the consent to start agents are rules already in force, cited rather than restated; it refines itd-2610161016401115, whose press release promised a plain-terminal drain and which delivered the routed judge but no loop, rather than reopening a shipped record; revised after review round 1: the path reverses the host-delegated boundary for an opt-in use, as itd-2609201916151817's decision 5 flagged, so that reversal is recorded as adr-2610222222326104, proposed until the sign-off (grounds: the decomposition-calibration note under 2026-10-22; itd-84)

  • dcn-26102222162802142026-10-22

    2026-10-22 — Decided by the technical facilitator on delegation (coordinator ruling, 2026-10-22): the sweep command (itd-2610222214476887) is a dry run by default; --apply acts only on provably spent items (merged by ancestry or patch-equivalence, clean, unlocked, held by no live session, not the embargo store); an origin branch is deleted only with --remote; a live session is proven by a live reservation footprint, a running process's working directory or build-loop run state, with recent activity a hint that also keeps the item; a dead session's dirty worktree has its diff saved as a patch and is kept. Grounded in the 2026-10-22 crash triage.

  • dcn-26102222162709382026-10-22

    2026-10-22 — Decided by the technical facilitator on delegation (coordinator ruling, 2026-10-22): the sweep command (itd-2610222214476887) never deletes a reservation branch itself, since only the reservation-sweep App may; under --apply it dispatches the reservation-sweep workflow and reports the run, and where it cannot it says when the daily run clears them, following the 2026-10-15 ruling that abcd resolves a gap itself rather than hand the person a manual step.

  • dcn-26102222162644212026-10-22

    2026-10-22 — Decided by the technical facilitator on delegation (coordinator ruling, 2026-10-22): the sweep command (itd-2610222214476887) refines and is blocked by the worktree store (itd-2609091014076309) and calls the store's prune as its one reclaim primitive, never a second copy, on the one-canonical-primitive principle.

  • dcn-26102221552385152026-10-22

    2026-10-22 — Decided by the technical facilitator on delegation (coordinator ruling, 2026-10-22): an explicit implement step --route that names the claude runner for a model the machine pins, given in the flag or as claude's own model, is refused before anything is written (exit 2), naming runner.opencode.model as the route that holds a pin. This matches how --route already refuses every condition the configuration shows it cannot run (a runner the machine does not enable, a model its provider does not list, a tier route), and keeps the person's explicit request from being handed to the host behind their back. A machine route to claude for a pinned model, which nobody asked for on that step, keeps claude's launch-time refusal and the recorded fallback to the host (iss-2610161801358637).

  • dcn-26102221050368442026-10-22

    2026-10-22 — The status-branch ruleset is applied by the person by hand, by design, and C15 is corrected to say so (facilitator, on the delegation of 2026-10-14; iss-2610222040438015, itd-2609151838312703): every ruleset in .abcd/work/rulesets is applied by the person with the README's gh api command and refreshed into the mirror, and invariant 10 lets abcd change a remote only through a dedicated, confirmed apply verb, which no record ever planned for rulesets; so C15's last clause, 'applied through the rulesets' own apply verb', was a drafting slip, not a promise owed, and becomes 'applied by the person from that mirror'. The outcome C15 asks for (the forge refuses deletion and force-push under abcd-status/) is unchanged and live as ruleset 25302453. A verb that applies or verifies rulesets would belong with the branch-protection doctor draft (itd-92), not here (grounds: .abcd/work/rulesets/README.md; brief invariant 10; adr-44)

  • dcn-26102220480692842026-10-22

    2026-10-22 — A session's own token is a user access token from the device flow, and its refresh token stays on the person's computer (facilitator on the product thinker's delegation of 2026-10-14 for technical choices grounded in the state of the art, itd-2610170634394993; keeps dcn-2610180723332655, the person's name marked as made through abcd, which the product thinker accepted in the 2026-10-22 C3 question): the person authorises abcd's GitHub App once through the device flow (a code entered in the browser), which needs only the App's client id, so no client secret is shipped to any machine, and a device-flow token is refreshed without the secret; the refresh token, which lasts six months and is replaced at each refresh, is the only issuing secret, and it is kept on the person's computer in the system's credential store (the macOS keychain, or a file only the person's account can read under ~/.abcd.noindex on Linux), outside every session and on the fence's read-deny list; at each unattended launch abcd on that computer refreshes and hands the session only the eight-hour access token, through abcd's own credential channel; a container or a separate user account on the same computer is handed a fresh token before the old one lapses, and a cloud session cannot be reached after launch, so its pushes stop when its token lapses and its remaining pushes are queued as owed work for the person's return or a relaunch, which the walk states; the token reaches only the repositories the App is installed on, so abcd asks for the App to be installed on the one repository; the installation token stays the fallback behind the forgecred seam, with the commit author still the person, should the device flow be withdrawn (grounds: docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app; docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/refreshing-user-access-tokens; docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/best-practices-for-creating-a-github-app)

  • dcn-26102220414399512026-10-22

    2026-10-22 — abcd signs a fenced lane's commits when it hands the work in (product thinker's ruling of 2026-10-22, spc-2610161751056096 step 2 question d): lane commits are made unsigned inside the fence, with commit.gpgsign=false in the launch's seal; at land, outside the fence, abcd rewrites each lane commit with the same tree, message and order, signed under the person's own configuration, and the judged-head check compares the rewritten chain tree for tree with the head its validators judged, so the agent never holds the signing key

  • dcn-26102220414340562026-10-22

    2026-10-22 — The sandbox intent's promise is narrowed to what holds (product thinker's ruling of 2026-10-22, spc-2610161751056096 step 2 question e, itd-2610161621364075): a fenced agent changes nothing outside its own work, and cannot read the person's passwords, keys and sign-ins (the credential stores the spec denies, the macOS keychain included); the press release is rewritten to say that, and no longer says the person's other projects and settings stay out of its reach, since a fenced agent can still read most of what the person can

  • dcn-26102220414272412026-10-22

    2026-10-22 — A fenced agent may reach the derived host list, and the list is not announced at every run (product thinker's ruling of 2026-10-22, spc-2610161751056096 step 2 question c): the runner's model endpoint; with a go.mod, the GOPROXY and GOSUMDB hosts and the hosts GOPRIVATE and GONOPROXY name; and the hosts the person adds in runner.sandbox.hosts on that machine; the run record keeps the list, but the run does not print it at its start

  • dcn-26102220414240272026-10-22

    2026-10-22 — When srt is missing, abcd offers to install it and installs only after the person's explicit yes (product thinker's ruling of 2026-10-22, spc-2610161751056096 step 2 question b): the refusal before a run names the install it would make and asks; a yes runs the install with everything the person's account can reach, which the product thinker accepted; anything short of a yes installs nothing, and the run stays refused with the install command and the off switch named

  • dcn-26102220414179342026-10-22

    2026-10-22 — Anthropic's sandbox (srt) is required for the agents abcd starts on its own (product thinker's ruling of 2026-10-22, spc-2610161751056096 step 2 question a, itd-2610161621364075): every agent the runner launches runs inside srt, on macOS and Linux, and on a machine without it no such agent starts; this is adr-22's first declared exception, scoped to the runner route alone, and the per-machine off switch runner.sandbox.off stays the person's way out. The proposed marks on adr-22's consequence and on the dependencies chapter's paragraph come off

  • dcn-26102220304779272026-10-22

    2026-10-22 — abcd looks for the person's forge login before it starts an unattended run, and refuses to start where it finds one (facilitator, on state-of-the-art grounds, applying the product thinker's 2026-10-22 ruling C1 on itd-2610170634394993): before an away-mode run, build or drain starts unattended, and before abcd issues the session a token of its own, abcd checks only signals that carry no secret: the forge CLI's login status for the host by exit code alone, with its output discarded (the CLI prints no token unless asked with --show-token); whether the token variables the forge CLI and git read (GH_TOKEN, GITHUB_TOKEN and their enterprise forms) are set, never their values; and whether the stored-credential files hold an entry for the host (the forge CLI's hosts file and ~/.git-credentials), by the host line alone. It never asks a git credential helper for the host, since a helper answers with the token itself and on macOS may raise a keychain prompt that hangs an unattended start; so a login kept only in a keychain is out of the check's sight, and the refusal says so rather than claiming the machine is clean (brief invariant 16). It refuses to start, naming each place it found a login, and never removes or hides one; the guarantee rests on where the run is started (a cloud session, a container or a separate user account), which abcd states as the person's setup step. The session's own token, issued after the check, never travels in those variables (grounds: cli.github.com/manual/gh_auth_status; cli.github.com/manual/gh_help_environment; git-scm.com/docs/gitcredentials; adr-2610222026262980 rule 4)

  • dcn-26102220252306802026-10-22

    2026-10-22 — Waiting holds up one item, never a whole session, and this is written up as a standing principle (product thinker's ruling of 2026-10-22, itd-2610170638184486 K-split ii): routed through the decomposition table as a stance, so it becomes a principle under .abcd/development/principles/; the principle states the stance behind dcn-2610180905291297, that a declared dependency holds only the landing

  • dcn-26102220252252772026-10-22

    2026-10-22 — While the person is away, sessions keep deciding trade-offs of security, speed and compatibility, and list each with how to undo it (product thinker's ruling of 2026-10-22, itd-2610170638184486 K-confirm): this confirms the 2026-10-17 ruling that nothing waits on the person overnight over the earlier framing that such trade-offs are raised with the technical facilitator; the list is shown on the person's return

  • dcn-26102220252249932026-10-22

    2026-10-22 — A checklist never holds a password, token or anything that retrieves one, only its kind, scope and expiry, and this is written up as its own trust rule (product thinker's ruling of 2026-10-22, itd-2610170638184486 K-split i): routed through the decomposition table as a trust rule, so it becomes an ADR and a clause of the brief's invariants rather than a line inside the checklist intent

  • dcn-26102220252174952026-10-22

    2026-10-22 — Sessions list what could stop them overnight when the person says they are away, and the unattended run starts once the person has answered the list (product thinker's ruling of 2026-10-22, itd-2610170638184486 K2): the person has nothing to remember to say beforehand, at the cost of a few minutes' wait before leaving; chosen over a warning ahead of leaving and over every session keeping its list current all day

  • dcn-26102220252123382026-10-22

    2026-10-22 — The phone and the shared copies of each checklist become their own intent in the bundle, and no question was put (facilitator, recorded on the product thinker's 2026-10-22 ruling C2, itd-2610170638184486 K1): once the product thinker chose to upload full checklists later, the shared copies are wanted later, and the phone needs them, so keeping them inside the checklist intent would hold its sooner parts back for nothing; splitting them off is the only answer consistent with the record, so asking would have offered a choice already made. The checklist intent keeps the on-disk checklist, waits, wakes and the blocker check

  • dcn-26102220251169372026-10-22

    2026-10-22 — The model budget is shared across sessions, not a fixed count for each abcd run (product thinker's ruling of 2026-10-22, itd-2610170634394993 C-confirm; a typed reversal: reverses dcn-2610180720379757 and the product thinker's 2026-10-10 answer 'each abcd run' in itd-2610100704270254): the sub-agent budget the repository sets is one pool that every abcd session draws on, so the draft's press release keeps 'a share of the model budget' and is not narrowed; the product thinker accepted that one busy session can slow the others. dcn-2610180720379757's narrowing of the press release and the model-budget scope condition is withdrawn

  • dcn-26102220251168352026-10-22

    2026-10-22 — Agents' own limited access ships in the same release as the coordination (product thinker's ruling of 2026-10-22, itd-2610170634394993 C3): autonomous sessions get short-lived tokens for one job from abcd's GitHub App from the first release of this intent, not in a later piece; the person registers the App once in the browser before that release is usable, a step only they can take. This is what makes C1 work: a run kept away from the person's login needs those tokens to push

  • dcn-26102220251148052026-10-22

    2026-10-22 — Only the short status line is shared for now; full checklist uploads come later (product thinker's ruling of 2026-10-22, itd-2610170634394993 C2): this intent publishes one short line per session and no full checklist, public or private; uploading a session's whole checklist so another computer could resume it is later work. This settles the two rulings of 2026-10-17 that disagreed, in favour of later, and keeps the intent's decision 3 as written

  • dcn-26102220251049692026-10-22

    2026-10-22 — Unattended agent runs happen only where the person's forge login is absent (product thinker's ruling of 2026-10-22, itd-2610170634394993 C1): an agent left to run overnight or while the person is away runs in a cloud session, a container or a separate user account, where the person's saved forge login cannot be reached, so the promise that agents cannot use the person's admin rights is a guarantee, set up once, rather than a caveat that the login is still within reach on their own computer; asked after an example, this was chosen over saying the limit plainly and leaving the login reachable

  • dcn-26101817563282492026-10-18

    2026-10-18 — The check job's macOS leg takes a 70-minute ceiling, with its warning at 60, raised from 60 and 50 by the coordinating session on delegation from the technical facilitator, who is away until 2026-10-23 (iss-2610181711260494). Across ten merge-group runs on 2026-10-18 the leg took 35.1 to 49.3 minutes, and one came within 0.7 minutes of its 50-minute warning. Its one race-enabled pass keeps a steady 2.80 to 2.85 of the runner's three test slots busy, so the leg is set by its total work rather than by one package: the slowest, internal/core/implement/loop, starts 8 to 12 minutes in and ends 2.5 to 4.2 minutes before the pass does. Its time varies with the runner, since the same tree's package times summed to between 5,738 and 8,050 seconds. The new ceiling stays under the merge queue's 90-minute check response timeout, and the warning keeps its 10-minute lead. The per-package -timeout stays at 40 minutes: the slowest package under race took at most 1,901 seconds, 31.7 minutes, a margin of 8.3. release.yml's verify job is not touched, since it runs the ubuntu race lane, about 21 minutes, under its 55-minute ceiling, not this pass. Starting the loop package first was not taken (at most 2 to 3 minutes, against a list pinned in three files), nor was running it without the race detector on macOS (the macOS-only flakes seen so far came from the race leg). Cutting the pass's total work is the longer lever, captured on its own.

  • dcn-26101816062230442026-10-18

    2026-10-18 — A sub-agent stage retries a transient failure and marks a final one, but queues no unresolved transcript (facilitator-on-delegation, iss-2610051434156079): the hook retries resolving the repository when the payload's cwd carries a .git entry but git gave no root commit, re-reading the session note between tries, since burst siblings write it as they resolve; it retries a stage refused by lock contention, waiting longer as the record's remedy asks; both within a bound well inside the host's hook timeout, saying each retry on stderr. A stage that still fails for a known store leaves a counted marker that abcd history staged reports, so the loss is visible to the person and not only in a debug log. No machine-level queue is added for a transcript whose repository cannot be resolved at all, because it would keep unredacted transcripts in a new location outside any store, and the retries remove the transient case the record names (grounds: the cause established on the record on 2026-10-18; gitutil.RepoShaped; the existing sub-agent gap marker's pattern; principles/loud-staging.md)

  • dcn-26101810353619972026-10-18

    2026-10-18 — A qualifying wake releases an unchanged set of work the session can do itself at most twice in a row (facilitator-on-delegation, itd-2610180912189125 plan review round 3, finding F2; refines dcn-2610180936577720 and dcn-2610181003455731): while away, a stop whose owed set is unchanged is allowed with a qualifying wake at most twice while any capped item stays unchanged, and the third such stop is blocked naming the next item; the block counts toward the host's cap, whose forced stop is recorded. The capped items are the kinds the session can act on itself: a pull request that is behind or failing, an unpushed branch, a stacked branch the clearing rule still owes, and a reservation whose work no pull request carries, which the review's list did not name but which is the same kind of act as a push. A renewal that is only due, and an item waiting only on the forge, such as checks still running, keep releasing on a qualifying wake. The count compares the capped items alone, so a renewal falling due or done neither resets it nor adds to it, and a change in the capped items resets it; the count and a fingerprint of the capped items are kept in the session's state file in the local tier (.abcd/.work.local/autonomy/sessions/<session-id>.json), and TestWakeReleasesUnchangedSetTwice shows the third consecutive unchanged stop with a wake blocked. Repeated identical recorded stops are kept as one entry with a count and the last time, so a cron that wakes the session every ten minutes cannot grow the away record past its 64 KiB check, which would read as not away (grounds: plan review round 3, finding F2: with a */10 cron set once, each wake found the set unchanged and was allowed, and a behind pull request stayed behind for eleven hours, meeting the intent's falsifier)

  • dcn-26101810353557412026-10-18

    2026-10-18 — A queued push hands nothing back unless the person said pushes wait, and then only the unpushed item of a verified branch (facilitator-on-delegation, itd-2610180912189125 plan review round 3, finding F1; refines dcn-2610181016510153, whose grant of no push rights stands): by default a step queued with abcd mode queue hands nothing back, so the item stays owed and the stop stays blocked; the reason for an item that needs a push says to push if the standing instruction allows and to queue only if the person has said pushes wait, and a session with no instruction to push ends at the host's cap with the stop recorded for the person. A hand-back happens only when the away record carries the person's word that pushes wait, set with abcd mode autonomous --hold-pushes. The flag narrows what sessions do and grants nothing, so set on a relayed word it can at worst make sessions queue pushes they could have sent. Even then a queued step naming an own branch, on word boundaries, removes only that branch's unpushed item, and only while the disk shows the rest clear: its head contains its base's last-fetched tip, and a preflight receipt names the head where the repository mints receipts; where none are minted the clearing rule's equivalent, passing checks in the listing, can name only a pushed commit, so nothing is handed back there. It never removes a pull request that is behind or failing, a stacked branch the clearing rule still owes, a review outstanding, a reservation named by its record id alone, or a renewal, so a behind pull request whose merge is committed locally stays owed with pushes held and ends at the cap, recorded. The stop check records each hand-back in the away record under its lock, abcd mode back prints them, and the every-prompt line counts the queued steps and the handed-back items. TestQueuedPushHandsItemBack covers each case, the no-flag case handing nothing back (grounds: plan review round 3, finding F1, raised by both reviewers: the hand-back as written let a session exempt itself, replaying the first instance of iss-2610170619247185, where a behind pull request stayed behind all night; and it crossed the coordination intent's decisions that a stacked branch is cleared only by its merge and receipt and that a reservation's renewal must not lapse)

  • dcn-26101810170563072026-10-18

    2026-10-18 — The overnight-stall slice is trimmed to what closes iss-2610170619247185 and nothing else (facilitator-on-delegation on the release orchestrator's ruling, itd-2610180912189125 after plan review round 2; refines dcn-2610180937181929): it keeps (i) a session with owed work cannot end its turn silently, through the Stop hook stop check with the ownership rules, the qualifying wake and the cap handling the reviews required; (ii) questions rerouted by the act, every other question decided with abcd decide and the person-only acts queued; and (iii) the away record set, ended, lapsing after at most seven days, re-injected at start, compaction and every prompt, under its lock. Moved to itd-2610170638184486 as named remaining work: the person-only guard step (dcn-2610181016510153), with the guard's reading of go run ./cmd/abcd and built binaries as abcd; the ten-minute reuse cache of the away forge listing and its stale-cache fallback, so each away check makes at most one listing under its ten-second deadline and a failed read judges from disk naming the pull requests as not read (adr-2610181003541997, still proposed, amended to match); abcd mode back printing more than one plain line per queued step and per recorded stop (any grouping, formatting or window summary); and the refused-attempt lines on the prompt. Kept despite the trim, because a review finding's fix rests on each: the created-branch list recorded in any mode (round-2 blocker 3, the drain's stacked branches, instance 2 of the issue); the Refs rule and word-boundary matching (blocker 4); the stale-ownership bounds (blocker 5); the wake deadline with the host's lateness and the cron cases (blocker 1); the forge's merge state for behind, with the one bounded listing and invariant 7's clause (blocker 2); the person-only acts list (blocker 6); the every-prompt line and the lapsed-window line naming abcd mode back (blocker 7); the block count and its possibly-forced label (round-2 (b)); the clearing rule's review and receipt terms (round-2 minors); the record's lock, ownership checks and seven-day cap (round-1 findings 6 and 7); the recorded ender (round-1 finding 13); the StopFailure record and the prose-question block (round-1 finding 11); and the badge verbs refused while away, which keeps a question from waiting on the person through the badge (dcn-2610180913431493). Re-estimated at 5.75 working days over seven steps, down from eight; about four is not reachable without reopening blockers 1 to 5, since the owed-work reading and the stop verdict with its cron parser carry 3.5 days between them and every rule in them answers a finding; the verdict is pure over the owed set, so two lanes could bring the elapsed time to about four days if the release orchestrator chooses (grounds: the release orchestrator's ruling of 2026-10-18 and the reviewer's addendum listing what stays; the spec's review rounds 1 and 2; AGENTS.md wired or it isn't done)

  • dcn-26101810165101532026-10-18

    2026-10-18 — The away mode grants no push rights: the person's own standing instruction stays the authority to commit, push, and open or merge a pull request, exactly as before the mode existed (facilitator-on-delegation on the release orchestrator's ruling, itd-2610180912189125 after plan review round 2; supersedes dcn-2610181003456444, round 2's choice (a), and with it the guard entries that made setting the mode the person's act alone). The OS sandbox of spc-2610161751056096 fences only the agents abcd's runner launches, never the person's own interactive sessions, so for the sessions that actually stalled on 2026-10-16 the guard entries would never become a boundary, and their two days would buy a trust claim the plan cannot make. The fallback dcn-2610181003456444 already named is taken now, not on the live capture's evidence. Where the stop check finds owed work that needs a push (an unpushed branch, a reservation whose work no pull request carries, a behind or failing pull request once its local fix is committed), its reason tells the session to push if its standing instruction allows, and otherwise to queue the push with abcd mode queue for the person's return; a queued step that names the item's branch or record id, on word boundaries, hands that item back to the person for the rest of the window (a branch only while it holds commits its upstream lacks, so only the push waits), and the stop check stops naming it. The away mode is never treated as permission. The person-only acts gain pushing, opening or merging a pull request without a standing instruction that allows it. Who sets the mode returns to dcn-2610180913399042: the person, or a session on their word in that session; since the mode grants nothing, a mode set on a relayed word only keeps sessions working and deciding instead of asking, and the person sees who set it, from which working copy, and the literal abcd mode back on their next prompt. Making the mode the person's act alone moves to itd-2610170638184486 as named remaining work: the guard entry refusing an agent's abcd mode autonomous, its other routes (sh -c and script files), the shell-write and file-tool refusals on the away store, the refused attempts recorded and shown, the capture's checks of the person's ! command and of a relayed !, and the guard reading go run ./cmd/abcd and built abcd-<goos>-<arch> binaries as abcd for every entry, the ledger flip included, a security-relevant widening that gets its own review there (grounds: the release orchestrator's ruling of 2026-10-18 and the reviewer's addendum, both recommending the fallback; spc-2610161751056096 and adr-2610161621415708, which fence launched agents only; iss-2610170619247185, whose standing instruction already allowed pushes and auto-merge; the fallback clause of dcn-2610181003456444)

  • dcn-26101810034883552026-10-18

    2026-10-18 — A stacked branch's clearing rule includes review and works without abcd's preflight (facilitator-on-delegation, itd-2610180912189125 review round 2, minor findings; refines dcn-2610180936571036): a stacked branch whose base is still open is also owed while a review of its head is outstanding, that is, while the away listing shows the forge's review decision as CHANGES_REQUESTED or, for a run's lane, its run state records no passing review of its head, since the coordination prep's decision that a declared dependency constrains only the landing says its review runs now. Verified means a preflight receipt naming its head where the repository mints receipts (a receipt folder exists in one of its worktrees); in a repository without them, its pull request's checks passing in the away listing; and with no pull request there either, the branch is judged on being behind and on review alone, and the reason says it was not verified (grounds: plan review round 2, minor findings; the receipt lookup in internal/core/landing)

  • dcn-26101810034846312026-10-18

    2026-10-18 — abcd's count of blocks resets only when the host is not already continuing (facilitator-on-delegation, itd-2610180912189125 review round 2, choice (b); refines dcn-2610180936577720): the count is set to one on a block with stop_hook_active false and adds one with it true; a change in the owed set no longer resets it, since the host's count does not, and a reset abcd made on one could leave a stop the host forced unrecorded. A stop recorded at the cap is labelled "possibly forced by the cap", because the host's count also resets on a tool call abcd cannot see, and the live capture checks where the host's count resets (grounds: plan review round 2, choice (b); the host's hooks page on the Stop cap)

  • dcn-26101810034771942026-10-18

    2026-10-18 — The acts only the person may approve are completed, end in a catch-all, and are classified by the agent (facilitator-on-delegation, itd-2610180912189125 review round 2, blocker 6; refines dcn-2610180937177502): the list the question reroute queues gains the embargo triage verdict (commands/embargo.md), the drain's hand-back (commands/drain.md), the confirmed apply verb for remote configuration (brief invariant 10), a push or merge beyond the session's own branches (the default branch, a tag, a release cut, another person's pull request, a branch only checked out to review), and a comment or message posted outward other than the session's own pull request, and it ends with any act a command page or a brief invariant names as the person's. A release sign-off is a cut, or a step of one, that asks for the person by name or that no standing instruction of theirs allows; a standing permission for automatic cuts stands, and the away mode adds none. Nothing detects the act mechanically: the agent classifies its own question from the refusal's list, and the guard's existing entries enforce only what they name, a force push and a skipped hook among them (grounds: plan review round 2, blocker 6; commands/embargo.md; commands/drain.md; brief invariant 10)

  • dcn-26101810034747652026-10-18

    2026-10-18 — A window that lapsed with anything unread points the person at abcd mode back (facilitator-on-delegation, itd-2610180912189125 review round 2, blocker 7; refines dcn-2610180937181736): while a record whose end has passed is not yet closed and holds a queued step, a recorded stop or a refused attempt, the prompt hook shows the person one line on every prompt that counts them and names the literal abcd mode back, until that verb closes the record; the line shown while away carries the literal abcd mode back too, so the person never has to recall the verb (grounds: plan review round 2, blocker 7; dcn-2610180937181929, which kept the queue's print in the slice so that no queued step goes unread)

  • dcn-26101810034672332026-10-18

    2026-10-18 — A pull request carries a reservation's work only through its head branch or a closing trailer (facilitator-on-delegation, itd-2610180912189125 review round 2, blocker 4; refines dcn-2610180936568358): the link is the record id in the pull request's head branch name, or on a Resolves: or Delivers: line of its body, matched on word boundaries so that iss-5 never matches iss-50. A Refs: line, which the issue-resolution gate requires of any pull request that only names an issue, carries the work only when the head branch is already this copy's own by another route, and never makes a branch own, so a sibling copy's pull request that mentions the record neither leaves this session waiting nor becomes its branch (grounds: plan review round 2, blocker 4; the RS004 rule in scripts/check-issue-resolution.sh)

  • dcn-26101810034643792026-10-18

    2026-10-18 — While the person is away, a pull request is behind when the forge says so (facilitator-on-delegation, itd-2610180912189125 review round 2, blocker 2; refines dcn-2610180936571036): the stop check reads "behind" from the merge state (mergeStateStatus BEHIND) in its one pull-request listing, not from the last-fetched default branch, which nothing refreshes overnight, so a pull request that fell behind after the last fetch still reads as owed. Only a branch with no pull request is compared on disk, and the reason names when that ref was last fetched (grounds: plan review round 2, blocker 2; the pinned pull-request fields in internal/ghcontract)

  • dcn-26101810034633672026-10-18

    2026-10-18 — A branch is the session's own only while it is live and this copy's, and a branch the session creates is recorded as its own (facilitator-on-delegation, itd-2610180912189125 review round 2, blockers 3 and 5 and choice (a)'s exclusions; refines dcn-2610180936568358): when the guard's pre-tool hook sees this session run git worktree add -b|-B <b>, git switch -c|-C <b> or git checkout -b|-B <b>, it records <b> under this copy's key in the away store, under its lock, and only when no branch of that name exists yet, whether or not the person is away, because the stacked drain branches of 2026-10-17 were cut with a plain git worktree add before any window and carried no upstream, reflog entry, run state or record id. Stale ownership is bounded: a run's lane counts only while its run's reservation is live under this copy's key, and a finished or abandoned run's lanes never count; a branch owned through the reflog or a recorded creation counts only while it holds a commit authored by this checkout's user.email within the last 14 days, or a live reservation under this copy's key links it. Never own: the default branch, a tag, a branch whose open pull request another person authored, and a branch this copy only checked out to review, which the authorship rule leaves out (grounds: plan review round 2, blockers 3 and 5; lanes are cut from the default branch; the 60 run states and the five unlanded lanes of 2026-10-12 in this checkout)

  • dcn-26101810034564442026-10-18

    2026-10-18 — Only the person sets the away mode, its push rights are narrow, and the guard's refusal is a mistake filter (facilitator-on-delegation, itd-2610180912189125 review round 2, choice (a); refines dcn-2610180913399042, replacing its clause that an agent sets the mode on the person's word): the prompt hook cannot tell the person's message from one another session relays, and its input names no origin, so a relayed word could let an agent grant itself, and every copy, push rights. So the guard refuses every route to setting the mode that it reads: abcd mode autonomous by the binary on PATH, the plugin root's binary or a built abcd-<goos>-<arch>; a go run of a package ending in cmd/abcd; any of them inside sh -c or in a script file a shell runs (adr-2610091150447054); a shell write into the away store under ~/.abcd.noindex/away/; and an Edit or Write tool call on a path inside it. The person sets the mode with their own ! command, which the host runs directly without going through Claude and so without the pre-tool hook, or at a terminal. A refused attempt is recorded in the store and shown to the person on the next prompt. What the mode grants is the session committing and pushing its own branches and opening their pull requests; never the default branch, a tag, a release cut, another person's pull request, a branch this copy only checked out to review, or a force push; merging follows the repository's own rule. This is chosen over the fallback, and is enough for now, because the grant only governs an agent that follows refusals: one that ignores them can push without any mode, so no shape of the mode adds a boundary inside the person's own session; the guard stops a refusal-following agent from granting itself on a relayed word; the rights are narrow, and every push is reversible and visible on the forge; and the record (who set it and from which copy) and the recorded refusals leave a trail the person reads on return. The guard stays a mistake filter (adr-42, and the decision of 2026-10-17 on the default branch that keeps the headless approver one, naming the OS fence as the boundary). That fence (spc-2610161751056096) is the boundary only for agents abcd's runner launches, whose writes to abcd's home it confines to their own worktree; it does not fence the person's own interactive session, where the stall happened, so there the narrow grant and the trail are the mitigation. The fallback (the mode grants no push rights, and the person's own standing instruction stays the authority to push) applies instead if the live capture shows that a message relayed from another session can run as a ! command, or that an agent's tool call can reach the host's shell mode (grounds: plan review round 2, choice (a), and the coordinator's two addenda; the host's interactive-mode page, which says shell mode runs commands directly without going through Claude and outside the sandbox that applies to Claude's commands; the abcd-source-ledger-flip guard entry; adr-2610161621415708)

  • dcn-26101810034557312026-10-18

    2026-10-18 — A wake qualifies only when it fires, the host's lateness included, within a short ceiling (facilitator-on-delegation, itd-2610180912189125 review round 2, blocker 1 and choice (c); refines dcn-2610180936579498): the deadline is the earlier of the earliest renewal due among this copy's live reservations minus lease.Skew, and now plus a ceiling of 30 minutes while work is owed or one hour when none is, because a release reservation's 24-hour lease put its renewal 12 hours on and let a 07:00 cron seen at 21:00 qualify. The fire time compared with it is the next match, read in the machine's local time, plus the latest the host may run it: for a recurring task, half the gap to its following match, at most 30 minutes, and nothing for */5 * * * *; a one-shot task is taken as matched, since the host only ever runs one early. The parser follows vixie cron, as the host says it does: a day field written from * (*/n) counts as unrestricted for the either-day rule, 7 is Sunday as 0 is, and a-b/n steps a range. The live capture compares the computed fire time with the next run the host lists (grounds: plan review round 2, blocker 1 and choice (c); the host's scheduled-tasks page on jitter, local time and day-of-week; the release reservation's default lease in the reserve verb)

  • dcn-26101809371819292026-10-18

    2026-10-18 — The person's return report, the status line and the bare abcd mode print move from the slice back to the checklist draft (facilitator-on-delegation, itd-2610180912189125 review round 1; supersedes dcn-2610180913431985 for the slice, and the status-line and bare-print halves of dcn-2610180913445272): both reviewers of 2026-10-18 recommended the split, so the security and bug-fix cut waits only on the away record, the stop check and the question reroute. The spec's step 6 and the return half of its step 5 leave the slice: the report shown once on the first prompt after the window ends (the queue, the window's decisions and the recorded stops); the window's decisions gathered from every working copy by abcd decide appending each id to the away record under its lock (review finding 8); showing on return who ended the mode (finding 13); the status line naming the away mode and its end; a bare abcd mode printing the record, the queue and the owed items; and the brief's surface text for them. They become named remaining work in the scope of itd-2610170638184486. The slice keeps what its own behaviour needs: abcd mode back prints the queue and the recorded stops as it ends the record, so a queued step is never unread; brief invariant 7 gains the away mode's forge listing; and the plugin page and the brief's surface chapters describe the verbs and hooks the slice ships, so nothing it ships is undocumented. The slice is re-estimated at five working days (grounds: the plan review of 2026-10-18, size and split; the coordination prep's decision that the cut waits on this slice alone; AGENTS.md wired or it isn't done; brief invariant 7)

  • dcn-26101809371817362026-10-18

    2026-10-18 — The away record is changed only under a lock, read only when it is safely the account's, and capped at seven days (facilitator-on-delegation, itd-2610180912189125 review round 1; refines dcn-2610180913399042): every read-modify-write of the record (setting, ending, queueing, a recorded stop) holds fsutil.WithFileLock on a lock file beside it and re-reads the record inside the lock, so a stop check that read away before a slow forge listing cannot write away back after the person ended it, and two queued steps cannot lose one; the forge listing runs outside the lock, and a lock not had within two seconds allows the stop and says so on stderr. The record and its lock are used only when each is a regular file this account owns that no one else can write, within 64 KiB, the checks rules.json already gets; a record failing them, or failing to parse, reads as not away, failing open, and a verb asked to change it refuses naming the file. An open-ended record ends seven days after it was set, and --until may name no later time, so a forgotten record lapses while a run of several days, such as the standing run of 2026-10-15 through 2026-10-17, still fits; a 24-hour cap would have ended that run midway, and requiring --until would contradict the product thinker's ruling that the mode may be open-ended. While the record holds, the prompt hook adds a one-line systemMessage the person sees on every prompt naming the away mode, its end, who set it and how to end it; the away block tells the agent to run abcd mode back only on the person's word in its session; and abcd mode back records who ended the mode and from which working copy (grounds: the plan review of 2026-10-18, findings 6, 7 and 13; internal/fsutil file lock; AGENTS.md rules.json ownership checks; iss-2610170619247185 standing run; the draft's ruling that the state is always shown plainly)

  • dcn-26101809371775022026-10-18

    2026-10-18 — While the person is away a question is routed by the act it asks about, not by its chip (facilitator-on-delegation, itd-2610180912189125 review round 1; supersedes the chip routing in dcn-2610180913431493): the guard still refuses every question on the host's question tool while the away mode holds, now with one reason whatever the chip. It tells the agent to queue with abcd mode queue, and carry on with other work, a question about any act only the person may approve: an approval the repository binds to the person per act (an embargo close's --approve digest, which commands/embargo.md says is never supplied unless the person has read the text and said yes in that session; a release sign-off); publishing anything or changing a repository's visibility; adding a dependency; a secret, a credential or an App; a step only a website or a browser can do; a destructive act (deleting what the session did not create, overwriting uncommitted work, a force push, discarding a peer's work); and anything that spends money. Every other question is decided and recorded with abcd decide, with its grounds and how to reverse it. The away mode, set on the person's word, is their ask for the session to commit and push its own branches and open their pull requests, which is the owed work itself; merging follows the repository's own rule. The Setup chip marks the setup interview's questions (visibility, keys, oracles), not a step only the person can take, so routing by chip would have sent an embargo approval, or the creation of a new App asked under a Product chip, to be decided by the agent (grounds: the plan review of 2026-10-18, finding 4; commands/embargo.md approval one per act; brief invariant 22; AGENTS.md new dependencies and commits; internal/surface/cli guard question chips)

  • dcn-26101809371756292026-10-18

    2026-10-18 — An API-error stop is recorded, and a turn ending on a prose question while away is blocked once (facilitator-on-delegation, itd-2610180912189125 review round 1): the plugin's hook manifest gains a StopFailure entry, which the host fires instead of Stop when a turn ends on an API error such as a rate limit and whose output it ignores, so it cannot continue the session; while the person is away abcd records the stop and the host's error type in the away record, and the slice's scope conditions name that such a turn is recorded, not resumed, except by a wake the session had already scheduled. While away, a stop whose last_assistant_message ends on a line ending in a question mark is blocked once per message with the reroute's reason (decide and record it, or queue it when it is an act only the person may approve), before the verdict's other rows apply (grounds: the plan review of 2026-10-18, finding 11; code.claude.com/docs/en/hooks StopFailure and Stop input; iss-2610170619247185, whose session ended its turn on a question)

  • dcn-26101809365794982026-10-18

    2026-10-18 — A wake qualifies only when its next fire time falls before the session's earliest renewal due, and a background task never counts (facilitator-on-delegation, itd-2610180912189125 review round 1; refines dcn-2610180913421109): a session_crons entry qualifies when the next time its cron expression matches after now, read in the machine's local time, is no later than the earliest renewal due among the live reservations under this copy's key minus the lease skew allowance, a renewal being due halfway between a reservation's claim or last renewal and its expiry; with no live reservation it must fire within half the default lease. The next fire time comes from a small five-field cron parser of abcd's own (minute, hour, day of month, month, day of week, with lists, ranges, steps and the wildcard), since the host documents schedule as a cron expression and a new dependency would need sign-off; an expression it cannot parse never qualifies. A background task does not count on its own while the person is away, since a shell task such as a long sleep or a tail that never ends reports as in flight however distant its wake. So a cron at 09:00 seen at 21:00, or a wake that fires after a lease lapses, no longer passes (grounds: the plan review of 2026-10-18, finding 3; code.claude.com/docs/en/hooks session_crons and background_tasks fields; internal/core/lease; AGENTS.md new dependencies need sign-off)

  • dcn-26101809365777202026-10-18

    2026-10-18 — While the person is away a session is only working or waiting, and abcd never allows a stop with work owed (facilitator-on-delegation, itd-2610180912189125 review round 1; supersedes the bound in dcn-2610180913413137 and refines dcn-2610180913421109): while away a stop is allowed only when the session has a qualifying wake and either nothing is owed or the owed set is unchanged since this session's last block; it then reads waiting, and the wake's next fire time is kept as its next look in the session's own state file in the local tier, beside the owed-set fingerprint and a count of consecutive blocks. Every other stop while away is blocked, whatever stop_hook_active says, naming the next item, or with nothing owed asking the session to take the next ready item first and only then schedule its next look. The host's cap of eight consecutive continuations, or the cap its documented environment variable sets, is the outer bound, and the block abcd counts as reaching it records stopped with work owed in the away record. The old row that allowed an unchanged owed set once stop_hook_active was true reproduced the stall, since a reply of awaiting the person with no tool call ended the turn until morning. This matches the coordination prep's decision that while the person is away a session with work never stops and one with nothing it can do is waiting with its next look, and the draft's ruling that stopped is allowed only while the person is present (grounds: the plan review of 2026-10-18, findings 2, 5 and 12; code.claude.com/docs/en/hooks Stop input and continuation cap; itd-2610170638184486 decisions)

  • dcn-26101809365710362026-10-18

    2026-10-18 — A stacked branch is owed only while it needs work, and the forge is read only while the person is away, under a deadline (facilitator-on-delegation, itd-2610180912189125 review round 1; refines dcn-2610180913416683): an own branch is stacked when its open pull request's base is not the default branch, or, with no pull request, when the nearest other own branch whose tip is an ancestor of its tip is not contained in the last-fetched default branch. A stacked branch whose base is still open is owed only while it is behind its base's tip or the last-fetched default branch, its checks are failing, or no preflight receipt names its head in any worktree (the receipts the landing step already reads); otherwise it is waiting on its base, which is not owed. An unpushed branch has commits not on its upstream or, with none configured, not in any remote-tracking ref; a branch whose upstream is gone (merged and deleted on the remote, a squash merge included) is never counted. While the person is present the check reads disk only (a reservation's renewal due and unpushed own branches) and never calls the forge, so brief invariant 7 holds on every turn. While away it makes at most one pull-request listing under a ten-second deadline; a listing younger than ten minutes is reused rather than repeated, and on a failure or timeout one younger than half the default lease is used with its age named, else the disk kinds alone with the pull requests named as not read (grounds: the plan review of 2026-10-18, findings 1 and 9; brief invariant 7; internal/core/landing receipt lookup)

  • dcn-26101809365683582026-10-18

    2026-10-18 — A session's own branches are named by three facts with no window bound, and only this copy's reservations count (facilitator-on-delegation, itd-2610180912189125 review round 1; refines dcn-2610180913416683): a branch other than the default branch is the session's own when (a) this working copy's HEAD reflog has checked it out at any time, (b) it is the branch of a lane recorded in a run state this copy's local tier holds (the implement loop's lanes, which build and drain cut with git worktree add, so they never reach the coordinating copy's reflog), or (c) it is the head branch of an open pull request linked to a live reservation held under this copy's key. A reservation counts only when its copy key is this copy's, so a sibling copy's reservation never holds this session. A pull request carries a reservation's work when the record id appears in its head branch's name or on a Refs:, Resolves: or Delivers: line of its body. The window bound is dropped because both instances of iss-2610170619247185 escaped it: the pull requests that fell behind were opened and last checked out before any window began, and the stacked drain lanes lived in worktrees of their own (grounds: the plan review of 2026-10-18 by an Opus and Sonnet pair, findings 1 and 10; internal/core/claim copy key; internal/core/implement/loop lane worktrees; iss-2610170619247185)

  • dcn-26101809145439002026-10-18

    2026-10-18 — The go-public report from a managed repository (iss-2610180913363115) is filed at minor, not at the sender's major: it asks for a capability abcd lacks, a staged go-public flow, and reports no defect in what abcd does. Major and critical records are what the release cut holds on, and that guard exists for confirmed defects, so a feature request at major would hold every cut until a multi-day feature ships. Decided by the technical facilitator on the product thinker's delegation, while the product thinker is away.

  • dcn-26101809134664362026-10-18

    2026-10-18 — The pre-run blocker sweep asks four fixed kinds and reports the run likely autonomous only when none is open (facilitator-on-delegation, itd-2610170638184486 planning prep): before or as an autonomous run starts, the orchestrating session asks each session by message, as the product thinker chose, for (1) a design decision not yet made, (2) a step only a person's hands can do, (3) work it depends on from another session, and (4) a credential missing or expiring within the window; each session writes its answers into its checklist, the orchestrator puts them to the person together, and says the run is likely to stay autonomous only once every session reports none open. The kinds are the four the draft's press release names; the message route stays within the coordination prep's bound that a question put to a person may travel by message (grounds: itd-2610170638184486 press release and scope split; the coordination prep's stance-bound decision; iss-2610170619247185, every blocker known at 20:48)

  • dcn-26101809134558282026-10-18

    2026-10-18 — A promise tied to a trigger is a checklist entry checked when the session looks, never a watcher (facilitator-on-delegation, itd-2610170638184486 planning prep): a promise such as 'when that pull request merges, add the wrapper' is written into the checklist with its trigger, read by the session at each start, wake and stop check, and its wake is the host's scheduled wake that the slice's stop check already reads; abcd keeps no process alive for it. The two-hour watcher of 2026-10-16 ended with the promise unkept, and the coordination prep settled that every deadline is derived when records are read, with no process that must stay alive (grounds: iss-2610170619247185; the coordination prep's on-demand pass decision; code.claude.com/docs/en/hooks Stop input session_crons)

  • dcn-26101809134452722026-10-18

    2026-10-18 — The slice keeps the core host-agnostic and is reachable without a host (facilitator-on-delegation, itd-2610180912189125 planning): the away record, the owed-work reading and the stop verdict are a core package returning data, and the front doors format it: abcd hook stop maps the host's Stop payload and answers in its decision format, and a bare abcd mode prints the away record, the queue and the owed items, so the check runs with no plugin host present. The plugin's hook manifest gains a Stop entry with the same bootstrap and home checks as its other hooks, and the status line names the away mode and its end, so the person never wrongly believes agents are working or waiting. Nothing is written under the host's own settings directory (grounds: brief invariant 3; AGENTS.md transport-agnostic core and wired or it isn't done; the product thinker's ruling of 2026-10-05 that nothing in the host's settings calls abcd beyond the consented status line; itd-2610170638184486 decisions)

  • dcn-26101809134449712026-10-18

    2026-10-18 — A session's checklist is one JSON file per working copy in its local tier (facilitator-on-delegation, itd-2610170638184486 planning prep): the checklist the draft describes is kept per working copy, since the checkout is the unit of isolation and the coordination prep keys one central-view line per working copy, in that copy's local tier, never in a tracked folder, and its re-injection reuses the slice's session-start and prompt-hook path; the away mode itself is not copied into it but read from the repository's one away record (grounds: AGENTS.md concurrent sessions and working-tree layout; the draft's format decision; the coordination prep's per-working-copy decision; itd-2610180912189125)

  • dcn-26101809134319852026-10-18

    2026-10-18 — The person's return shows two lists derived from what already exists (facilitator-on-delegation, itd-2610180912189125 planning): when the away mode ends, by its time passing or abcd mode back, the next prompt shows once the steps queued for the person's hands and the decisions recorded in the window, each with its text, which the reroute asks to carry its grounds and how to reverse it, plus any stop recorded with work owed. The decisions are the decision records whose time-ordered ids fall inside the window, so no second store of decisions is kept; the queue is the only new list and lives in the away record. The draft's richer lists for the person's return stay in itd-2610170638184486 (grounds: principle one-canonical-primitive; adr-45 time-ordered ids; itd-2610170638184486 press release)

  • dcn-26101809134314932026-10-18

    2026-10-18 — While the person is away no question waits for them (facilitator-on-delegation, itd-2610180912189125 planning): while the away mode holds, the guard refuses every question on the host's question tool, abcd's or another tool's, because a question nobody is there to answer stalls the session. A product or technical question is refused with a reason telling the agent to decide it, record it with abcd decide marked as decided on delegation with its grounds and how to reverse it, and carry on; a step only the person's hands can do (a browser step, a secret, a new App) is refused with a reason telling the agent to queue it with abcd mode queue "<step>" and carry on with other work. abcd mode product-thinker or facilitator is refused the same way. Decisions in the window are not asked first, technical trade-offs included, since the product thinker ruled on 2026-10-17 that in an autonomous run the agent decides and records and only steps that need them on the website wait (grounds: iss-2610170619247185 remedy; itd-2610170638184486 framing; internal/surface/cli guard question check)

  • dcn-26101809134211092026-10-18

    2026-10-18 — A session with nothing owed stops only with its next look scheduled (facilitator-on-delegation, itd-2610180912189125 planning): while the away mode holds, a stop with no owed work is allowed when the host reports a scheduled wake for the session or a background task in flight, and is then waiting; otherwise it is blocked once, asking the session to schedule its next look sooner than half its reservations' lease (under an hour for the two-hour lease) through the host's own scheduling, and the bound in the stop-check decision applies. The host documents that its Stop input carries session_crons (wakes from CronCreate, ScheduleWakeup and /loop) and background_tasks so a hook can tell a finished session from one paused for work that will wake it. abcd starts no process of its own and schedules nothing itself. The check covers the overnight gap after the two-hour watcher ended; the checklist draft's own timed wakes and trigger promises stay there. It matches the coordination prep's decision that a waiting session wakes before half its lease, and the product thinker's ruling that a waiting session records when it looks again and is never kept spinning (grounds: code.claude.com/docs/en/hooks Stop input; itd-2610170638184486 decisions; iss-2610170619247185 idle spans)

  • dcn-26101809134166832026-10-18

    2026-10-18 — Owed work is four kinds, read from disk and one forge listing (facilitator-on-delegation, itd-2610180912189125 planning): a session owes work it can do alone when it has (1) a live reservation whose renewal is due or whose work no open pull request carries yet; (2) an open pull request of its own that is behind the default branch or failing its checks; (3) a branch of its own with commits not pushed; (4) a branch of its own stacked on a change that is still open, whose merge from the default branch, fixes, review and preflight are owed now, since a declared dependency holds only its landing. A branch is the session's own when its working copy's own HEAD history has had it checked out since the window began, so a sibling copy's branches never count. The reservations are read as last fetched, behind against the last-fetched default branch, and the pull requests' states from one listing of the person's open pull requests through the forge client per stop check, which becomes part of the away mode's documented meaning in brief invariant 7, as the drain's listing is; a failed listing falls back to the disk kinds and says so. The next item is the first of: a renewal due, a failing pull request, a behind one, a stacked branch, an unpushed branch, unhanded work (grounds: iss-2610170619247185 remedy and second instance; the coordination prep's decision that a declared dependency constrains only the landing; brief invariant 7; internal/core/claim)

  • dcn-26101809134131372026-10-18

    2026-10-18 — The stop check refuses only while the person is away and is bounded so it never spins (facilitator-on-delegation, itd-2610180912189125 planning): a plugin Stop hook asks abcd, which blocks the stop with the host's decision block and a reason naming the next owed item and how many remain, only while the away mode holds and owed work exists. While the person is present the stop is allowed and, with work owed, pointed out in one line through the host's systemMessage. If the host says the session is already continuing because of a stop hook and the owed set is unchanged since this session's last block, the stop is allowed and recorded as stopped with work owed, shown on the person's return; the host's own cap of eight consecutive continuations, reset by each tool call, is the outer bound. The host documents stop_hook_active as the field to check so a hook never blocks on a condition that will not resolve. The session states are the bundle's: working, waiting, stopped. This restates the product thinker's 2026-10-17 stop-check ruling (grounds: code.claude.com/docs/en/hooks Stop input and Stop decision control; itd-2610170638184486 decisions)

  • dcn-26101809134069722026-10-18

    2026-10-18 — The away mode is repeated to the session at every start, after every compaction and with every prompt (facilitator-on-delegation, itd-2610180912189125 planning): while it holds, the session-start hook says it on every source, compact included, and the prompt hook says it with every prompt, outside the rule loader's once-per-session ledger, as one short block: away until when and set by whom, the rule to decide and record rather than wait, and the next owed item. The host documents that a SessionStart hook fires with source compact after compaction and that its plain stdout or additionalContext, like a UserPromptSubmit hook's, is added to Claude's context. The instruction of 2026-10-16 was lost because it lived only in the context a compaction summarised (grounds: code.claude.com/docs/en/hooks SessionStart matcher compact and UserPromptSubmit additionalContext; principle durable-state-lives-where-the-platform-says-it-survives; iss-2610170619247185)

  • dcn-26101809133994992026-10-18

    2026-10-18 — The away mode is held once per repository on the machine, not per working copy (facilitator-on-delegation, itd-2610180912189125 planning): the record lives in abcd's machine store under the repository's root commit, beside the worktree store's key, so every working copy of the repository and every session in it reads the same record; the issue's remedy words it per checkout, but the stall began with an instruction relayed by a peer between sessions in separate working copies, and the person's absence is a fact about them, not about one copy. It is not machine-wide, so a repository the person never left running is unaffected. A session on another computer or in the cloud does not see it until the checklist draft's shared options land (grounds: iss-2610170619247185 what happened; AGENTS.md worktree store; principle the-users-directory-is-theirs)

  • dcn-26101809133990422026-10-18

    2026-10-18 — The away mode is a record of the person's absence, set by a verb and ended only by its time or by their word (facilitator-on-delegation, itd-2610180912189125 planning): abcd mode autonomous [--until <time>] records who set it (the holder name reservations already resolve from caller-local facts), when, and when it ends, where --until takes a clock time (its next occurrence, local time) or a full timestamp and a time already past is refused; without --until it is open-ended until abcd mode back. It sits beside the waiting-on badge, whose three words stay a closed set, and is not a fourth word. A human prompt during the window does not end it, since a brief return overrode the instruction on 2026-10-16 and a prompt from a peer looks the same. An agent sets it on the person's word in its session, and one set covers every working copy, so no peer has to relay it. This restates the product thinker's 2026-10-17 ruling that they say they are away, until a set time or open-ended, and say when they are back (grounds: itd-2610170638184486 decisions; iss-2610170619247185; brief invariant 10; internal/core/mode)

  • dcn-26101809133884452026-10-18

    2026-10-18 — The stall fix is its own intent, not a spec of the checklist draft (facilitator-on-delegation, itd-2610180912189125 planning): the slice (the away mode held by abcd, the stop check, and the question reroute) is filed as itd-2610180912189125, which builds on itd-2610170638184486, rather than planned as a first spec of that draft closed with a remainder; planning the draft would move it to planned before the product thinker has walked its criteria on Thursday, and its open trade-offs (the phone, the shared options) would then sit inside a planned record. A separate intent keeps the split with the coordination intent unchanged, since the slice touches nothing on the shared remote, and follows the precedent of itd-2610150602547271, filed as the first slice of itd-97. The idle time a coordinator sees stays out of the slice and comes with the coordination intent's central view (grounds: brief invariant 17; itd-2610150602547271; itd-2610170638184486 scope split; the coordination prep's ship-first decision)

  • dcn-26101809133790492026-10-18

    2026-10-18 — The overnight stall is fixed first, not deferred (facilitator-on-delegation, iss-2610170619247185 and itd-2610170638184486 planning prep): the critical record of the session that sat idle overnight is not given a one-cycle deferral; the security and bug-fix release waits for the smallest slice that removes its core cause, filed as itd-2610180912189125. This rests on the product thinker's standing rulings, restated: of 2026-10-11, that a major finding is fixed before a cut, never deferred, and building carries on; of 2026-10-12, that when a deferred question is all that stands between an intent and its plan, the facilitator decides it on delegation and plans it; of 2026-10-17, that in an autonomous run the agent decides and records rather than ending on a wait for the person. The stop check itself is the product thinker's settled design, in the checklist draft's decisions of 2026-10-17: a stop with work owed is refused only while they are recorded as away, and while they are present it is allowed and pointed out. It agrees with the coordination prep's decision that this fix ships as the bundle's first slice without waiting on the coordination intent (grounds: iss-2610170619247185 remedy; itd-2610170638184486 decisions; the coordination prep's ship-first decision of 2026-10-18)

  • dcn-26101809052912972026-10-18

    2026-10-18 — A declared dependency constrains only the landing (facilitator-on-delegation, itd-2610170634394993 planning prep): a branch that waits on an open pull request is held only from being queued; its merge from the default branch, its fixes, its review and its preflight run now, and only its landing waits for the dependency, so the stop check counts a stacked branch with an open base as owed work (grounds: iss-2610170619247185, second instance; the draft's first acceptance criterion; the decision that a waiting branch is rebuilt by merging)

  • dcn-26101809052838062026-10-18

    2026-10-18 — The overnight-stall fix ships first, ahead of the coordination intent (facilitator-on-delegation, itd-2610170634394993 planning prep): the fix for the critical overnight stall (an autonomous mode abcd holds, and a stop check that refuses to end a turn with owed work) sits in the checklist draft, which owns a session's modes, waits and stop check; it needs nothing on the shared remote, so it ships as the bundle's first slice, without waiting on this intent, and the security and bug-fix cut waits on that slice alone; this intent then adds what the stall's record asks for across sessions, the idle time a coordinator sees, through the central view's derived state and last-seen time in abcd status rather than in abcd peers as the record's remedy words it, per the decision naming abcd status as the central view (grounds: iss-2610170619247185 remedy; itd-2610170638184486 scope split; the draft's decisions 3 and 6)

  • dcn-26101807233425962026-10-18

    2026-10-18 — The central view is abcd status (facilitator-on-delegation, itd-2610170634394993 planning prep): the view of what every session holds, does and waits on is shown by abcd status, which the product thinker named the people's view of what everyone else is doing; abcd peers keeps the meaning they reserved for it, the sessions running now seen locally and later over a private network, which this intent's decision 4 dropped (grounds: itd-2609151838312703 decision 21; the draft's decisions 3 and 4)

  • dcn-26101807233326552026-10-18

    2026-10-18 — An autonomous session acts on the forge as the person, through the App (facilitator-on-delegation, itd-2610170634394993 planning prep): every commit stays authored by the person, since the attribution gate refuses a machine as author or committer; the session pushes and opens pull requests with a token the repository's App mints for the person, limited to the permissions both the App and the person hold and expiring after eight hours, so its work shows the person's name marked as made through the App; the App's own bot identity is not used, because the forge's who-am-I endpoint does not answer for it, so a cloud session could no longer resolve its reservation holder; this meets the product thinker's ruling of a weaker credential of the session's own, which concerns the credential, not the name (grounds: the draft's decision 5; AGENTS.md attribution; scripts/check-attribution.sh; brief invariant 10; docs.github.com generating-a-user-access-token-for-a-github-app; docs.github.com endpoints-available-for-github-app-installation-access-tokens)

  • dcn-26101807205480662026-10-18

    2026-10-18 — A waiting session wakes before half its lease (facilitator-on-delegation, itd-2610170634394993 planning prep): since no process stays alive and a branch is rebuilt only when its agent asks to land, a session waiting on a dependency wakes, through the checklist draft's timed wake, at an interval shorter than half its reservations' lease, so an idle waiter's reservations are renewed rather than lapsing after two hours and being taken over (grounds: itd-2609091034175565 two-hour lease, renewed at half; itd-2610170638184486 timed wake; the draft's take-over criterion)

  • dcn-26101807205412062026-10-18

    2026-10-18 — A session's mode shows on its central-view line (facilitator-on-delegation, itd-2610170634394993 planning prep): the line carries the session's state from the checklist draft's fixed set: working; waiting, with what it waits on and when it next looks; or stopped, which is allowed only while the person is present and is flagged. While the person is away a session with work never stops, and one with nothing it can do is waiting with its next look, so no session reads as idle. This follows the product thinker's ruling that the person must never wrongly believe agents are working or waiting (grounds: the draft's decision 6; itd-2610170638184486 modes)

  • dcn-26101807204274372026-10-18

    2026-10-18 — The coordination stance has a bound (facilitator-on-delegation, itd-2610170634394993 planning prep): the principle that coordination never lives only in conversation governs facts one agent relies on from another (holds, waits, turns, budgets); a question put to a person, such as the pre-run blocker sweep the product thinker placed in the checklist draft, may travel by message and lands in each session's checklist (grounds: the draft's decision 2; itd-2610170638184486 scope split)

  • dcn-26101807204156262026-10-18

    2026-10-18 — Refusing a newer coordination record starts with the release that adds a version (facilitator-on-delegation, itd-2610170634394993 planning prep): readers already shipped ignore an unknown trailer, so the criterion's refusal can hold only from the release that adds a version field, and the criterion says so (grounds: internal/core/claim/message.go; kubernetes.io version-skew-policy)

  • dcn-26101807204156252026-10-18

    2026-10-18 — Branch deletion is refused by rulesets, not by the token (facilitator-on-delegation, itd-2610170634394993 planning prep): a token able to push can also delete branches, so the criterion that a session cannot delete a branch it did not create is narrowed to the protected prefixes the rulesets already guard, and other branches stay deletable (grounds: docs.github.com permissions-required-for-github-apps; brief invariant 16; .abcd/work/rulesets/reservations-protection.json)

  • dcn-26101807204129792026-10-18

    2026-10-18 — The mechanism's baseline is the shipped coordination (facilitator-on-delegation, itd-2610170634394993 planning prep): the falsifier compares a run of three or more headless agents against the same run with only reservations and the load gate, not against agents coordinating by message, which headless agents cannot do (grounds: the draft's Mechanism and Why This Matters sections)

  • dcn-26101807204074592026-10-18

    2026-10-18 — A re-submitting agent is given the merged pull requests that touch its footprint (facilitator-on-delegation, itd-2610170634394993 planning prep): the draft's criterion asking for a summary of what landed becomes the list of pull requests merged since the branch's merge base that touch its footprint, which a test can check (grounds: the draft's research note on multi-agent coding, Xia et al.)

  • dcn-26101807204023612026-10-18

    2026-10-18 — A session's line carries its own expiry (facilitator-on-delegation, itd-2610170634394993 planning prep): a line is renewed and expires on its own, counted from its first fetch, so a session that holds no reservation still shows as live or gone (grounds: itd-2609151838312703 C9; kubernetes.io node leases)

  • dcn-26101807204020072026-10-18

    2026-10-18 — A session's state line is fixed-form (facilitator-on-delegation, itd-2610170634394993 planning prep): the line's state is a stage from a fixed list plus the record ids it waits on, carried on the person's existing abcd-status branch, never free text, and no branch per session is added (grounds: itd-2609151838312703 C3 and decisions 1 and 9; internal/core/claim/stage.go)

  • dcn-26101807203979702026-10-18

    2026-10-18 — The claim's generation number is its tip commit (facilitator-on-delegation, itd-2610170634394993 planning prep): every act goes through a fast-forward push, which is already a compare-and-swap, and a take-over moves the tip, so no separate counter is added; the forge enforces the fence only on a push, so for queueing and tagging the criterion says abcd refuses the act, and whether one atomic push can carry the work branch and the renewal together is left to probe at planning (grounds: internal/core/claim/claim.go; internal/core/implement/loop/reservation.go; Chubby section 2.4; git-scm.com/docs/git-push --atomic)

  • dcn-26101807203977742026-10-18

    2026-10-18 — One central-view line per working copy (facilitator-on-delegation, itd-2610170634394993 planning prep): a session in the view is a working copy, keyed on the reservation's existing copy key, since the checkout is the unit of isolation (grounds: itd-2609091034175565 decision 33; AGENTS.md concurrent sessions; internal/core/claim/message.go)

  • dcn-26101807203901662026-10-18

    2026-10-18 — Pushes stay well inside the forge's rate (facilitator-on-delegation, itd-2610170634394993 planning prep): renewals stay at half the two-hour lease, hourly, the short status line is pushed only when it changes, and a refused push backs off, so ten sessions stay far below six pushes a minute (grounds: itd-2609091034175565; internal/core/claim/renewdue.go; docs.github.com repository-limits)

  • dcn-26101807203896282026-10-18

    2026-10-18 — Registering the App takes one step in the browser (facilitator-on-delegation, itd-2610170634394993 planning prep): creating a GitHub App needs the person on the website once, through the manifest flow, so the draft states it as a step only the person can take, as the checklist draft already lists it, and never promises setup without manual steps (grounds: docs.github.com registering-a-github-app-from-a-manifest; itd-2610170638184486)

  • dcn-26101807203893522026-10-18

    2026-10-18 — A hold is a reservation; a merging announcement informs (facilitator-on-delegation, itd-2610170634394993 planning prep): the pass enforces holds only through reservations and reads a merging announcement as information, so the short status line carries no hold field (grounds: itd-2609151838312703 decisions 2 and 4)

  • dcn-26101807203824722026-10-18

    2026-10-18 — The release cut's hold is the announcements intent's reservation (facilitator-on-delegation, itd-2610170634394993 planning prep): this intent adds no lease of its own for a release being cut; the merge path already reads the release reservation (grounds: itd-2609151838312703 C7 and decision 2; internal/core/landing/releasehold.go)

  • dcn-26101807203797652026-10-18

    2026-10-18 — An autonomous session's credential is a GitHub App token (facilitator-on-delegation, itd-2610170634394993 planning prep): each session gets a token the repository's App mints for it, short-lived and scoped by repository and permission; a fine-grained personal token is not used, because none can be created through an API and none expires with the session (grounds: docs.github.com authenticating-as-a-github-app-installation; docs.github.com managing-your-personal-access-tokens)

  • dcn-26101807203797572026-10-18

    2026-10-18 — The model budget stays a fixed count per abcd run (facilitator-on-delegation, itd-2610170634394993 planning prep): the sub-agent budget remains itd-2610100704270254's count per run from the repository's config, neither shared across sessions nor sized from rate-limit headers, since the product thinker ruled 'each abcd run' on 2026-10-10 and agent work is delegated to the host, so abcd never sees the provider's headers; the draft's press release and model-budget scope condition are to be narrowed to match, which is put to the product thinker to confirm because it edits their confirmed text (grounds: itd-2610100704270254; AGENTS.md host-delegated by default)

  • dcn-26101807203761532026-10-18

    2026-10-18 — The machine budget is the load gate's slots, weighted per job (facilitator-on-delegation, itd-2610170634394993 planning prep): preflights, race runs and every other heavy job draw on one pool, the load gate's existing slots (load.preflights), each job weighted, with a dead holder's slot reclaimed as it is now; no second pool is added (grounds: principles/one-canonical-primitive.md; airflow.apache.org pools; internal/core/implement/load_slots.go)

  • dcn-26101807203698602026-10-18

    2026-10-18 — A waiting branch is rebuilt by merging, not restacking (facilitator-on-delegation, itd-2610170634394993 planning prep): once its dependency lands, the dependent branch takes the default branch merged in and is never rewritten, because the merge queue lands by merge so the dependency's commits keep their ids, and a restack would break the reachability of resolved_by stamps (RS002, RS003); a restack is used only when the dependency was squash- or rebase-merged by hand, which the review ruleset allows; each rebuild needs a fresh preflight receipt and so takes a load slot (grounds: .abcd/work/rulesets/main-protection.json; main-review.json; AGENTS.md RS002 and RS003; git-spice)

  • dcn-26101807203662822026-10-18

    2026-10-18 — The coordination pass runs on demand (facilitator-on-delegation, itd-2610170634394993 planning prep): land, build, drain and status run the pass from the records they have just fetched before they act; there is no timer lease and no process that must stay alive, and every deadline and expiry is derived when the records are read, as a reservation's release already is (grounds: the draft's research note on controllers; kubernetes.io/docs/concepts/architecture/controller; brief invariant 7; itd-2609151838312703 decision 14; itd-2609091034175565 decision 13)

  • dcn-26101807203626922026-10-18

    2026-10-18 — A dependency is a Depends-On line in the pull request's body (facilitator-on-delegation, itd-2610170634394993 planning prep): a branch's wait on another change is written as Depends-On: #N, which land writes from the agent's declaration and the pass enforces, and the session's short status line mirrors it as a hint only; a field on the claim is not used, since a reservation is per record and per person while a dependency belongs to a change, and the line's exact spelling is plumbing for the brief (grounds: docs.mergify.com/merge-protections/builtin; Zuul's Depends-On footer; itd-2609091034175565)

  • dcn-26101805443518692026-10-18

    2026-10-18 — The check job's ubuntu leg stops rerunning the race lane's tests in its plain pass, decided by the coordinating session on delegation from the technical facilitator, who is away until 2026-10-23 (iss-2610171803053186). The race step's CPU was saturated, at about 3.4 of the runner's four cores, so sharding its slowest package would not have shortened it. The plain pass reran 106 of its 111 tested packages, the ones under ./internal/... that the race lane runs anyway, at 7 to 9.3 minutes of a leg that reached 31. The precedent is the macOS leg's single pass (iss-2610110938293273). The condition: the tests that assert only without the race detector, cost guards that skip under -race or drop their CPU bound there, must still run in CI. So where the race lane runs, the plain pass covers ./cmd/... and, by name, the 43 such tests, a list derived from the test files and held by a test. On an inert change the plain pass still runs the whole module, since the race lane stands down there. The ceiling returns to 30, and macOS keeps its 40-minute race -timeout, which nothing here changes.

  • dcn-26101721350326562026-10-17

    2026-10-17 — A comment outside ASCII leaves the declaration plain (facilitator-on-delegation, drain-many-accounts step 11 follow-up, refines dcn-2610170900575176): the ASCII rule is judged only on the lines of the root .gitattributes that git reads, so a blank line or one whose first non-blank byte is '#' decides nothing, as git's attribute parser skips both whole; a byte-order mark, which git skips, still voids the declaration, since leaning to not generated only shares less (grounds: git 2.52 check-attr reads an indented comment naming -linguist-generated as no line at all; abcd's own .gitattributes has em dashes in its comments and so shared nothing; iss-2610172133042562)

  • dcn-26101718030569312026-10-17

    2026-10-17 — The check job's ubuntu leg takes a 45-minute ceiling, raised from 30 by the coordinating session on delegation from the technical facilitator, who is away until 2026-10-23. The v0.15.1 release run on the ubuntu leg was cancelled at the 30-minute ceiling inside the race step, and the merge-group run before it reached the race step's failure at 28 minutes: the drain bundle grew the implement loop package's race run. The macOS leg keeps 60, both stay under the merge queue's 90-minute check timeout, and the remedy the workflow names for a leg near its cap, a faster suite, is the captured follow-up, after which the leg returns to 30.

  • dcn-26101711123847122026-10-17

    2026-10-17 — The headless approver closes the arithmetic routes a review found by reading the text as bash will read it where that is cheap: it joins a backslash-newline before scanning, refuses an alias or alias expansion turned on, a $'…' string that writes a byte by its code, and a builtin whose operands bash may read as arithmetic spelled with a quote or a backslash in its name; it reads a substring offset on any parameter and an array index only in an assignment, an expansion or a name a builtin is handed, so a regular expression's character class is no longer refused. It stops there by decision, not by oversight: on the default branch a launched role is granted the shell with no approver at all, so every route the approver misses is one the run has today; reading a shell line well enough to refuse every hidden command is not finite; and the approver stays a mistake filter (adr-42), with the boundary for launched agents the OS sandbox spec (spc-2610161751056096). Grounds: the default branch grants Bash in the implementer and reviewer roles (internal/core/implement/loop/drive.go). Refines dcn-2610170944153720.

  • dcn-26101710094982182026-10-17

    2026-10-17 — A lane its landing's sync sends back reserves its whole found_at again before the sync merges, not after (facilitator-on-delegation, drain-many-accounts step 12, refining dcn-2610170947246937): once the sync knows it will merge origin's default branch into an issue lane, it makes the overlap-checked widening first, before the merge commit or any other local change, so a widening refused by another's reservation or by the cap refuses the step for a person with the branch and the worktree left at the judged head, nothing merged and nothing pushed; the re-sync from the arming or the merge wait takes the same path; the move keeps the check only for any other way a lane leaves its landing, and takes no act when the sync already made it in the step (grounds: a widening judged after the merge left the loop's own merge on the branch when it was refused, and once the default branch moved again the retry read that merge as a foreign move of the branch and stayed refused until a person reset it, each refusal counting towards a drain handing the lane back as stuck; final review of the fix round on spc-2610161044461448 step 12)

  • dcn-26101709483568822026-10-17

    2026-10-17 — A drain's re-reserve carries a lane's stage only for a concurrent build, and never under --take-over (facilitator-on-delegation, drain-many-accounts, spc-2610161044461448 step 18 fix round; corrects the premise of dcn-2610170809478944): a drain move passes over every issue with a live run in this checkout before it reserves, so its reservation reaches an issue whose lane here holds it live only when abcd build started that run after the move read the runs, and only then does the stage it names keep the lane's stage on origin; under --take-over the drain's reservation names no stage, since a take-over is never a renewal and claim refuses a stage beside it (grounds: the earlier record's ground that the drain re-reserves its lane's issue at each move does not hold; a take-over is consent to one act, which a stage would refuse for an unrelated reason; review finding 7 of the step 14 to 18 fix round)

  • dcn-26101709472469372026-10-17

    2026-10-17 — A lane that leaves its landing reserves its whole footprint again before it goes on, and a resumed issue run reads its tip as narrowed only at the landing (facilitator-on-delegation, drain-many-accounts step 12, refining dcn-2610170919040486): when a landing's sync (the first land step's, or the re-sync from the arming or the merge wait) sends an issue lane back to a fresh round, the step reserves the record's found_at again, with the overlap-checked widening a resumed run makes, before the lane's state moves on, since the landing's renewal may already have narrowed the hold and a fix round after the fresh round can change any file of the found_at; a widening refused by another's reservation or by the cap refuses the step for a person, naming what it met, the lane left at its landing with its sync unpushed; a resumed issue run renews a tip within its found_at as it stands only while its lane is at the landing, and anywhere earlier reserves the found_at again, judged for overlap, so a found_at widened mid-run is published; a narrowing that was due and could not be made (a changed path no reservation may carry, a default branch, merge base or diff git could not read, or a narrowing claim dropped) is said once in the renewal's record line, as reservation kept at its full footprint with the reason (grounds: lock de-escalation is safe only while the held set cannot grow, and leaving the landing lets it grow again; final review of spc-2610161044461448 step 12)

  • dcn-26101709453789772026-10-17

    2026-10-17 — A re-admitted issue's newer run is the issue's run for every verb (facilitator-on-delegation, drain-many-accounts, spc-2610161044461448 step 16 fix round; refines dcn-2610170750411628): an issue run whose lane was handed back and that a newer run of the same issue has followed is superseded, so abcd build <iss-N> resumes the newer run, and a step or a run record read with no run named addresses it, the superseded run no longer counting as one in progress; a handed-back run with no newer run is resumed by build as before; and a drain passes over every run of an issue that was not handed back, complete runs included, so it never opens a second run or a second pull request for an issue whose pull request may still be open (grounds: once re-admitted, the newer run holds the issue's work and reservation, and the handed-back one has nothing left to run; a complete run's pull request settles the issue; review findings 4 and 5 of the step 14 to 18 fix round)

  • dcn-26101709441537202026-10-17

    2026-10-17 — The headless approver refuses arithmetic on anything but written numbers. Bash evaluates a name it meets in an arithmetic context as arithmetic in turn, so a value the line does not fix can hold an array index that runs a command the line never names. The approver reads the whole command text, quotes and here-documents included, and refuses a name, a quote or an expansion in (( )), $(( )), $[ ] and a for (( )) header, the number tests and -v of [[ ]], let and integer or name-reference declarations, a non-numeric array index or substring offset, ${!name}, and a variable name not written in the line handed to read, unset, printf -v, wait -p, test -v or a declaration. [ and test compare numbers without evaluating them and stay approved. Reading the text whole over-refuses a script that only quotes such a construct, which the agent can write another way; a reader that tracked quoting could be misled by what a quote hides. This refines dcn-2610170937000859.

  • dcn-26101709370008592026-10-17

    2026-10-17 — Refines dcn-2610170805446355: the text an approval hands back is cd -- '<dir>' && /bin/bash --noprofile --norc -p -c '<command>'. It drops exec, because the host joins its own text after the approved one (&& pwd -P >| <file>, its record of the shell's working directory), which must still run, and exec guards nothing the agent controls. It adds -p after the long options, since bash 3.2 refuses a long option after a short one, so bash ignores BASH_ENV, functions exported as BASH_FUNC_* and SHELLOPTS from the environment, and the approved command runs under /bin/bash with its profile, rc and environment start-up files ignored. The check of the text handed back accepts exactly that shape and nothing else. And a command holding a NUL byte is refused under the new id command-holds-nul before the guard reads it, since the guard's reading removes a NUL before it reads a word, so the command it would judge is not the one sent.

  • dcn-26101709190404862026-10-17

    2026-10-17 — A lane's reservation narrows only at its landing, once its validators have passed, and a resumed issue run keeps the narrowing (facilitator-on-delegation, drain-many-accounts step 12, refining dcn-2610170734071361): the narrowing is taken at the first due renewal while an issue lane is at StageLand, never during its validate stage, since a fix round there can still change a file of the reservation's footprint that a narrowing would have freed; the narrowed set is the lane's own changes, git diff --name-only from the merge base of its head and origin's default branch to its head, so a merged default branch's files are left out and a conflict resolved in a sync's merge commit counts; a changed file within the footprint that no reservation may carry (claim.ValidFootprintPath) means no narrowing at all, since leaving it out would free a file the lane still changes; claim drops a Narrow naming such a path and renews anyway, as it does one over the message cap, so a renewal never fails over its narrowing; a resumed issue run whose reservation tip lies within the record's footprint renews the tip as it stands, the widening re-reserve kept for an intent's record alone (grounds: lock de-escalation is safe only once the held set can no longer grow; a renewal that fails lets the reservation lapse while the lane lives; review of spc-2610161044461448 steps 8, 12 and 13)

  • dcn-26101709005751762026-10-17

    2026-10-17 — abcd shares only on a plain declaration (facilitator-on-delegation, drain-many-accounts step 11, refines dcn-2610170652475517 and dcn-2610170831290823): generatedFiles declares nothing, and names the rule, when the root .gitattributes holds a byte outside ASCII, quotes a pattern or names a macro (a bare [attr] included), or when the tree holds a .gitattributes named or placed outside ASCII or a second root one in other capitals; a file whose path is not ASCII is never generated; within those bounds the ASCII case rules stand, and every line visited costs budget steps (iss-2610152125101468).

  • dcn-26101708312908232026-10-17

    2026-10-17 — Unsetting lines match regardless of case and setting lines only where every clone would (facilitator-on-delegation, drain-many-accounts step 11, refines dcn-2610170652476743): a line that unsets linguist-generated matches wherever git's would on a clone that ignores case or on one that does not, and a line that sets it matches only where git's would on both, so abcd never calls a file generated that git on some clone calls unset; the only cost is less sharing. Within a class, git ignoring case lowers the text byte but not the class's own bytes, so the two readings are judged separately (grounds: git check-attr under core.ignorecase true and false agreed on 303,104 comparisons; iss-2610152125101468).

  • dcn-26101708155094922026-10-17

    2026-10-17 — The reservation sweep's workflow runs the latest published release of abcd, verified by checksum and build-provenance attestation, never the default branch's code, so only released code ever holds the App's one-hour bypass token. Chosen by the technical facilitator on 2026-10-17 over leaving the residual or requiring code-owner review of all code; the cost is that a sweep fix reaches the job only with the next release.

  • dcn-26101708094789442026-10-17

    2026-10-17 — A drain's re-reserve that renews its own live reservation carries the lane's stage (facilitator-on-delegation, drain-many-accounts, step 18, asked for by the loop's owner): a drain's reservation may name a lane stage, which is written when the act renews this copy's own live hold and left off, without a refusal, when the act reserves afresh over no tip, a released or lapsed one, or by a take-over; every other act naming a stage is still refused (grounds: the drain re-reserves its lane's issue at each move, so that commit is a lane's renewal and would otherwise clear the stage; only a renewal carries a stage; refines dcn-2610170757253644).

  • dcn-26101708054463552026-10-17

    2026-10-17 — Refines dcn-2610170739186543: an approved command runs under bash, because the guard reads every command in bash's grammar, so the command it judged is the command that runs. The approval hands back cd -- '<dir>' && exec /bin/bash --noprofile --norc -c '<command>', the command one single-quoted word, so the person's login shell, zsh or bash, only changes directory and, when that succeeds, starts bash, with its profile and rc files switched off. A construct only zsh gives a meaning to (glob qualifiers, (:A) modifiers, { … } always { … }) is a syntax error to bash, and bash runs nothing of that line. The check of the text handed back reads it with the guard's own parse and approves it only when it is exactly that change of directory joined by && to that one bash call, with the whole command as its last word and nothing else, refused as tree-group-broken otherwise. It no longer reads the command's own groups, ifs, loops and cases, since nothing in the single-quoted word can end it early: a } or a fi with nothing open is bash's syntax error inside the working tree, not a refusal. The refusal of a command where an unquoted ( stands in a word, and the reading of a quoted } as a command's name, stay as a second layer.

  • dcn-26101707591808942026-10-17

    2026-10-17 — Every lane renewal names its stage (facilitator-on-delegation, drain-many-accounts, spc-2610161044461448 step 18, the loop's half; refines dcn-2610161040394970): each renewal the loop pushes for a run's reservation, a drain move's, a lane step's, the land fence's and a resumed build's alike, sets claim's Request.Stage to the stage the run's current lane is in, spelled as the loop's Stage values worktree, brief, implement, validate and land, which are claim's LaneStages; a lane done, handed back, held or discarded names no stage, since it performs none; a loop test holds every Stage the loop renews with to claim.ValidLaneStage, since claim cannot import the loop (grounds: a run's state does not mark a drain's lane, and a build lane's stage is as useful to a peer and costs no act; the stage a worker reports is the one it is in, as job dashboards read it from the record each worker writes; iss-2610161015434746)

  • dcn-26101707572677912026-10-17

    2026-10-17 — The lane stage and the hand-backs ride the reservation listing that abcd peers and abcd status share (facilitator-on-delegation, drain-many-accounts, step 18): the stage is a stage field on each reservation row and the hand-backs a hand_backs_by_holder list, each holder with its hand_backs and a more count, so status shows them too (grounds: the listing block is one shape for both surfaces by design, and dcn-2610161040394970 has the people's status view inherit the same rows; a list per holder keeps the order a map would lose).

  • dcn-26101707572563742026-10-17

    2026-10-17 — A hand-back's last day is judged by the tombstone's Abcd-Released-At (facilitator-on-delegation, drain-many-accounts, step 18): abcd peers lists a hand-back released within 24 hours of the reader's clock, and never one dated more than lease.Skew ahead of it, which is left out rather than counted from when it was fetched (grounds: the release stamps Abcd-Released-At on every tombstone it writes, so it is the time the hand-back was made; a date ahead is not trusted, and leaving it out means a fast clock cannot keep it on show past its day, while the drain's own reading of the hand-back is unchanged; refines dcn-2610161040394970).

  • dcn-26101707572536442026-10-17

    2026-10-17 — A bad Abcd-Stage makes the reservation tip unreadable, as a bad hand-back does (facilitator-on-delegation, drain-many-accounts, step 18): two stages, a value outside the five lane stages, or a stage on a tombstone read as unreadable with one fixed reason, never as a stage, while an inexact spelling of the key reads as the key's, as for every reservation trailer (grounds: one consistent fail-closed rule across the family's closed-vocabulary trailers; only a renewal writes a stage, so a stage anywhere else is hand-made; refines dcn-2610161040394970).

  • dcn-26101707572515472026-10-17

    2026-10-17 — abcd peers shows at most ten hand-backs per holder (facilitator-on-delegation, drain-many-accounts, step 18): the newest ten of the last day, newest first, with a count of the rest, never dropped silently (grounds: ten keeps one holder's block to a screenful while a session reading it before a pick still sees the latest of a busy day; refines dcn-2610161040394970).

  • dcn-26101707553034512026-10-17

    2026-10-17 — A lane's merge of the default branch is an issue run's, and re-enters its sync only over generated-file conflicts (facilitator-on-delegation, drain-many-accounts step 13): only an issue run's sync (a drain's lane, or a person's build of an issue) fetches origin's default branch and merges it whenever it moved, since an intent's run already syncs its own landed siblings and its other conflicts stay the sibling brief's; the generated-file conflict goes to the sync's fresh implementer, whose brief says to regenerate, and like every sync counts no fix round, a regeneration being no failed attempt; any other conflict is a final refusal naming the files, so the drain's stuck rule hands the lane back at once with nothing pushed; a pull request the forge reports conflicting at the arming or the merge wait re-enters the sync when a driver-free merge of the default branch and the pushed head, as the forge merges, conflicts in declared generated files alone or in none, withdrawing an armed merge first and keeping the records commit and the pull request, the push and arming made again after a fresh round; the drain's move takes that step itself for a parked lane, reads it as syncing and drives the lane again; the generated set is claim.GeneratedFiles, the matcher step 11 exports, with no second reader (grounds: GitHub's update branch and merge queues test a pull request merged with its base; the forge ignores local merge drivers, iss-2609240646538011; a stale forge verdict with nothing to merge stays a wait; iss-2610161015410527)

  • dcn-26101707504116282026-10-17

    2026-10-17 — A running drain's new pace and its re-admissions (facilitator-on-delegation, drain-many-accounts, spc-2610161044461448 step 16; refines dcn-2610161040399117): every lane a drain opens starts on the pace stored in the drain's state, with the layer and origin the drain resolved, never on what the configuration resolves at the lane's start; a running drain takes --fix-rounds as well as --pace and --sub-agents, since the fix rounds are the pace's fourth number set alongside it (ruling DR1), each number named replacing the stored one and the rest kept, written to the drain's state and to each in-progress lane's run pace, which that lane's next stage reads; a route keeps the blob of the issue's record on origin's default branch, and the drain re-admits a handed-back issue once that blob differs, an answer taken before the hand-back deciding nothing; an issue run whose lane was handed back is over for the drain alone, so the drain neither passes the issue over for it nor resumes it and opens a new run, while abcd build keeps resuming it as before; without origin nothing records a change, so a handed-back issue and an issue whose run here is over stay passed over (grounds: a setting the person gives is the drain's for its whole life; a changed record is a new question, read from the same blob the tombstone carries; a change confined to the drain leaves build's resume untouched; iss-2610161015417715, iss-2610161015457468)

  • dcn-26101707491207342026-10-17

    2026-10-17 — A file under a nested .gitattributes is never generated (facilitator-on-delegation, drain-many-accounts step 11, refines dcn-2610170652464473): generated files are declared in the root .gitattributes of origin's default branch alone, and since a nested .gitattributes could unset the attribute below it, every file at or below a directory holding one is left out of the generated set, found from the same file listing with no extra git read (iss-2610152125101468).

  • dcn-26101707391865432026-10-17

    2026-10-17 — Refines dcn-2610170726383253: a command where an unquoted ( stands in a word, glued to it or opening one after the command's name, is refused whole as one whose targets the line does not fix, whatever the command is, not only for the targets the guard reads. The words after the ( are not read as the command's own, so a flag there that makes it write (sed x(.) -i, cp a(.) -t dir) is not seen, and zsh may read the ( as glob qualifiers or modifiers that change the path a word names (echo hi(:A), ls x(/) are refused too). bash refuses every such line as a syntax error, so nothing a bash user runs is lost. A function definition's () after its name (f() { … }, f () { … }, function f() { … }) is not such a word and stays allowed, as does a quoted or escaped (.

  • dcn-26101707360626492026-10-17

    2026-10-17 — A drain's --take-over is the move's alone (facilitator-on-delegation, drain-many-accounts, spc-2610161044461448 step 15; refines dcn-2610161040398791): abcd drain --take-over lets this person's own live reservation from another copy through the move's view (Snapshot.Contention takes the holder a take-over reserves as) and the reservation act takes it over, as abcd build --take-over does; the flag is given per move and never kept in the drain's state, so a later move without it passes such an issue over again, naming the flag; it never moves another person's reservation, and a holder this copy cannot name from disk lets nothing through (grounds: a take-over is consent to one act, as build's and reserve's are; a flag kept for a drain's life would later take over a copy the person still works in; iss-2610161015422306)

  • dcn-26101707340713612026-10-17

    2026-10-17 — A lane's reservation narrows by a renewal that carries the narrower footprint, never by a fresh reservation (facilitator-on-delegation, drain-many-accounts step 12): claim.Request gains Narrow, honoured only with Renew and only when the fetched tip's footprint covers every path of it, so the compare-and-swap that refuses a released, lapsed-and-taken or another copy's tip refuses a narrowing too, and a hold never widens; the narrowed set is the files the lane's own non-merge commits changed from its base to its head that lie within the tip's footprint, taken at the first due renewal once an issue lane is past its implement stage; a narrowing too long for the message cap is not made and the renewal still is; an intent's run never narrows, since its one reservation covers lanes not yet opened; a later fix that changes a file outside the narrowed footprint is not re-reserved by a renewal (grounds: lock de-escalation, which only ever weakens a held lock; a plain reserve over one's own tip would re-reserve a record a person released; iss-2610152125101468)

  • dcn-26101707284535152026-10-17

    2026-10-17 — The routed drain judge is a loop role, asked and taken in one move (facilitator-on-delegation, drain-many-accounts, spc-2610161044461448 step 14; refines dcn-2610161040390001): drain-judge joins the implementer as a role outside the agent roster, so it needs no agents/ definition and the runner routing accepts it by name; the move that writes the host's request also writes the runner a brief of its own whose answer carries no digest, which abcd fills in from the remedy the brief showed, and takes that answer in the same move as --judgement would, so a no opens the lane on the reservation the drain took to ask it; the runner gets Read and Write alone, runs under the drain's lock and is bounded at fifteen minutes, a small part of the lease it is asked under; a runner that does not answer is a fallback receipt kept in the drain's state, and the host's request stands (grounds: one dispatch and one fallback rule for every model-run role, as the build roles use; a strict answer read once and validated by the same gaps as the host's; a bounded worker inside a lease, as lease-holding job queues bound their workers; iss-2610161015422306)

  • dcn-26101707282530952026-10-17

    2026-10-17 — Only the reserve verb warns over one's own other copy (facilitator-on-delegation, drain-many-accounts step 11, refines the step's own-overlap decision): the warning is a positive opt-in on the request, WarnOwnOverlap, which only abcd reserve sets; a build's, a drain's and the land fence's reservations are automated and keep the back-off over the same person's other copy, so two automated lanes never edit the same files (iss-2610152125101468).

  • dcn-26101707280748672026-10-17

    2026-10-17 — A drain move reads its parked lanes from one listing of the person's own latest pull requests (facilitator-on-delegation, drain-many-accounts step 8): gh pr list --state all --author @me --limit 100, one page of the forge's API, matched to each parked lane by number and head branch; gh's pr list names no merge-queue field (ghcontract pins gh 2.100.0's list), so the arming (autoMergeRequest) stands for the queue entry; a pull request the listing does not show, or a listing that fails, keeps its lane renewed as before, so only an answer the forge gave changes a lane; one merged by a squash or rebase, its head not on the default branch, is named and no longer renewed; a lane handed back as closed keeps its worktree and branch for implement step --discard, which then closes nothing (grounds: one request a move, as dcn-2610161040380948 sets; fail-safe reading, where absence is never evidence of closure; iss-2610161015381750)

  • dcn-26101707263832532026-10-17

    2026-10-17 — Refines dcn-2610170704288549: the guard counts a { or } as opening or closing a group, for what a pipe into the group reaches, only where the line leaves that word wholly unquoted, the same test the approver's own reading of the text it hands back uses. A } with a quote in it, even an empty pair (}"" or }''), is a command's name to the shell, so the commands after it still read the group's piped input, and a shell among them is refused as one reading a stream (echo 'touch ran' | { }""; bash; } is refused, as the same line with true in place of the } is). And a removal or a write in a command where an unquoted ( stands in a word, glued to it (build/l(:A), x(.), a/b(/), a redirection's target) or opening one after the command's name, is refused as a target the line does not fix, whatever follows the (. zsh reads such a ( as glob qualifiers or modifiers that can change the path the word names: build/l(:A) is the real path a symlink leads to, outside the working tree; bash refuses the line. A find or an rsync in such a command is read as removing, since the words after the ( are not read as its own. A quoted or escaped ( is text and stays allowed (rm -f 'a(b)').

  • dcn-26101707144888972026-10-17

    2026-10-17 — A lane held by another person's release cut is waiting, not stuck: a drain never counts a release hold at the push or arming fence towards handing the lane back, because the cut is a pause someone chose and lifts when the release is tagged. Refines dcn-2610170116582725.

  • dcn-26101707042885492026-10-17

    2026-10-17 — Refines dcn-2610170618185599: when the headless approver reads the text it hands back, it counts a { or a keyword as opening, closing or leading a command only where the line leaves that word wholly unquoted, with no quote, escape or empty quote pair in it, the same test it already applies to a }. A quoted { ("{", '{', {, {"") or a quoted keyword ('then', !, "time", 'function') is a command's name to the shell, and the words after it are arguments, so a line of one, then a }, then a command, is refused under tree-group-broken, since under bash and sh that } closes the group and the command after it runs outside the change of directory. And a glob removal is refused as a target the line does not fix when its pattern holds a /: a wildcard in a directory part (build//, ./build//, build//x.o) or a trailing / (build//). Such a glob lists directories the line never names, any of which may be a symlink out of the working tree, which the shell would expand into. This refusal was chosen over following every matching directory through symlinks, as the simpler rule; a glob whose wildcards stand only in its last name, such as rm -rf build/*, is judged as before.

  • dcn-26101707041911292026-10-17

    2026-10-17 — abcd land announces merging for each issue, intent or pull request that the branch's own commits, those not on origin's default branch, name in a Refs:, Resolves: or Delivers: trailer; a branch whose commits name none announces nothing, and its land says so. A build or drain lane announces its own record. An item whose announcement by the same person still stands for a minute more is not announced again. Decided by the facilitating agent on 2026-10-17: those trailers are how abcd's changes already name the records they work (AGENTS.md), so no new flag or input is needed (iss-2610161645224876, dcn-2610170655202547).

  • dcn-26101707041897122026-10-17

    2026-10-17 — When abcd cannot publish the announcement it owes before one of its own pushes (abcd land, or a build or drain lane's landing), it refuses that push with the reason and pushes nothing, and running the verb again resumes; it never pushes and warns afterwards. A record not yet on origin's default branch is not announced, since an announcement names only a public record, and the push goes on with a line saying so. Decided by the facilitating agent on 2026-10-17 under dcn-2610170655202547: a push that is made and then flagged has already broken the promise a colleague reads, land and the loop are built to be run again, and a person who must push regardless can still push by hand, which posts nothing (iss-2610161645224876).

  • dcn-26101706552025472026-10-17

    2026-10-17 — Only abcd's own pushes post an announcement before they push (abcd land, and a drain lane's landing); a push a person types by hand with git posts none, and the docs say so. The product thinker chose this on 2026-10-17 over posting from the pre-push hook or refusing an unannounced push there. Refines dcn-2610161645360719 and settles how iss-2610161645224876 keeps the messaging promise.

  • dcn-26101706524977342026-10-17

    2026-10-17 — The generated-file reader's own choices (facilitator-on-delegation, drain-many-accounts step 11, builder): a file counts as generated only when origin's default branch holds it as a blob, which is how a directory is never generated; .gitattributes is located with ls-tree -l, so absence, its type and its size are read before its blob; matching is case-sensitive whatever core.ignorecase says; a line git ignores (a negated pattern, an invalid or reserved attribute name) is ignored, and a line git reads but abcd does not understand voids every line before it when it could unset the attribute; a macro naming linguist-generated decides not generated; the reader stays inside the claim package, and the drain's conflict check reaches it through the reservation view, which carries the set as Generated with its Is method (grounds: git 2.52 check-attr agrees on every supported row of the differential test; iss-2610152125101468).

  • dcn-26101706524911352026-10-17

    2026-10-17 — abcd declares two of its own files generated (facilitator-on-delegation, drain-many-accounts step 11, builder): docs/reference/cli/commands.md and .abcd/development/release/surface.json, which go generate writes whole; the brief's surface chapters are not named, since each mixes hand-written prose with a generated appendix and the surfaces register is hand-written (iss-2610152125101468).

  • dcn-26101706524887702026-10-17

    2026-10-17 — A person's own reservation that overlaps their other copy warns and is made (facilitator-on-delegation, drain-many-accounts step 11, refines dcn-2610161040385152): a reservation that is not a drain's goes ahead over a live reservation with the same holder from another copy and names the shared path, the other record and its expiry; a drain's reservation and the drain's pass-over still back off, another person's overlap still backs off, and the cap is unchanged (iss-2610152125101468).

  • dcn-26101706524813262026-10-17

    2026-10-17 — A shared path that is a generated file is no overlap, and a directory never is (facilitator-on-delegation, drain-many-accounts step 11): two footprint paths overlap as sharedPath says unless the deeper of the two is a generated file; the rule holds in both the reservation act and the drain's pass-over, through one matcher loaded once per view (iss-2610152125101468).

  • dcn-26101706524767432026-10-17

    2026-10-17 — Generated-file patterns follow git's gitattributes rules for the subset abcd reads (facilitator-on-delegation, drain-many-accounts step 11): a pattern with no slash matches the basename at any depth, one with a slash is anchored to the root with a leading slash stripped, star, question mark, classes and double star are supported, a trailing-slash pattern matches nothing, later lines win, and only linguist-generated set or =true means generated (iss-2610152125101468).

  • dcn-26101706524755172026-10-17

    2026-10-17 — Reading generated files fails strict (facilitator-on-delegation, drain-many-accounts step 11): every misreading leans towards not generated, so an overlap is still refused; an absent file or no default branch declares nothing, a file that cannot be read, is not a regular file or is over the cap declares nothing and the act says why, and a line the reader does not understand (a macro, a C-quoted pattern, a negated pattern) is skipped (iss-2610152125101468).

  • dcn-26101706524644732026-10-17

    2026-10-17 — Generated files are read from one shared declaration (facilitator-on-delegation, drain-many-accounts step 11, refines dcn-2610161040385152): the files origin's default branch, as last fetched, marks linguist-generated in its root .gitattributes, read as stored from disk with a 256 KiB cap and never fetched; nested .gitattributes files, .git/info/attributes and the working tree are not read, because the declaration must be one every account shares (iss-2610152125101468).

  • dcn-26101706224962372026-10-17

    2026-10-17 — The reservation sweep also deletes a reservation branch that lapsed without ever being released, once its lapse is seven days old. A lapsed lease already lets any session take the record over, so the branch protects nothing, and keeping it only adds to the pile-up the sweep exists to clear. Decided by the facilitator during the autonomous run of 2026-10-17, in place of asking the product thinker.

  • dcn-26101706191271932026-10-17

    2026-10-17 — A local brief session reads its GitHub App's public client id from .abcd/relay/github-app.json ({"client_id": "…"}), which repository setup writes beside relays.json; the file holds nothing secret, and abcd session start refuses to start without a client id rather than offering no sign-in (facilitator, on delegation, on 2026-10-16; adr-2610161400542916, itd-2610091016262335).

  • dcn-26101706181855992026-10-17

    2026-10-17 — Refines dcn-2610162040034117: the headless approver judges a glob removal's directory where it leads and approves the text it hands back only when it is intact. A glob removal is approved, as dcn-2610161930191632 narrows it, only when its fixed directory lies inside the working tree both as written and followed through symlinks, read by the same resolution the check of removals outside the tree uses, and only when no earlier part of the line writes or removes a file, since such a part (an ln, a cp -s or cp -l, a mkdir) could make that directory a link after the line was judged; otherwise it is refused as a target the line does not fix, as before. And the text an approval hands back, cd -- '<dir>' && {, a newline, the command, a newline and }, is read again with the guard's own parse and approved only when its top level is exactly that change of directory joined by && to one group holding the whole command, with nothing after it. A command that would close the group before its end or leave the text unparsable as one group (a } or ) with nothing open for it to close, a fi, done or esac with nothing open, a } after a command's words, which zsh reads as a close, or a backslash at its very end) is refused under the new id tree-group-broken, so the agent is told why rather than handed a shell error, and no part of the command runs outside the change of directory.

  • dcn-26101701494326652026-10-17

    2026-10-17 — Refines dcn-2610161814279204, the two-preflights trial (iss-2610161639025702), on a lone race run gated with --wait -- go test -race. With two slots a live race run does not shut the first gate by itself, and the command form's hold ends once its race run starts, so a second such run saw one unit of two busy and opened, two race runs at their full -p together. Chosen: a command-form waiter whose command is a race run (go, then test with -race, read as a race run's arguments are) is gated as a race run for both gates. Above one slot it stays shut while another race run is live, judges and takes the race gate's hold as well as the first gate's (its hold record is written to both), and every race gate and every other such waiter counts it as a race run from the moment it opens, its mark showing it running before its go test is in the table. With one slot nothing changes: the first gate is already shut by every race run and every running waiter, and the race gate opens at once. Rejected: letting a live race run shut every command-form first-gate waiter. It closes the same gap, but it also holds --wait -- make preflight shut through every other preflight's race stage, which is the overlap the trial exists to measure. A shell or make that runs a race run is not read into; only a command whose program is go is judged one.

  • dcn-26101701445917422026-10-17

    2026-10-17 — Refines dcn-2610161814279204, the two-preflights trial (iss-2610161639025702), on a machine config.json that cannot be read for load.preflights. The load gate now reads past it: a file that others can write, that is not valid JSON, or whose load is not an object gives the default of one preflight at a time, and the waiter prints one line on stderr naming the file, the cause and how to fix it; a key under load that nothing reads is named on that line, and a usable load.preflights beside it still counts. Only a load.preflights that is there and unusable (out of range, or not a whole number), or an unusable ABCD_LOAD_PREFLIGHTS, refuses the wait. Reason: with one slot the gate never read that file before the setting existed, so refusing made a file that holds other machine settings stop every make preflight of a person who never set the count, a regression against main. This departs from the layered reader's rule that an unreadable file fails loudly; the note is what stays loud, and what a read past drops is only a count the file could not be trusted to carry, falling back to the setting's safe default. Rejected: keeping the refusal with a clearer message, which the branch had, since a person who never set the count still could not run a preflight without editing a file they did not know mattered.

  • dcn-26101701411392862026-10-17

    2026-10-17 — Refines dcn-2610161814279204, the two-preflights trial (iss-2610161639025702), on how the two gates share the hold. Each gate now keeps its own hold record, the first gate's in load-wait.json, the name it had before the race gate existed, and the race gate's in load-wait-race.json, and a wait judges and takes only its own gate's record. A first gate's command hold, taken by --wait -- make preflight, lasts until its preflight starts its race run, up to sixty minutes. While it also shut the race gate, an earlier preflight's race waiter on the same account waited on it, and the holder's own race waiter, which the hold does not shut because the holder is its ancestor, queued behind that earlier race waiter, which started earlier and has the lower pid; neither moved until its timeout. Even without the cycle, the earlier preflight's race stage waited out the holder's whole test stages. Rejected: letting a race waiter beneath a holder jump the race queue, as the first gate's waiter beneath one does. It breaks the cycle but keeps the stall, and since the queue is read across accounts, it would let that race waiter open beside another account's race waiter queued ahead of it, two race stages at once. Cost of the chosen fix: the first gate is no longer shut for two minutes after a race gate opens, nor the race gate after a first gate opens; with two slots each running preflight still takes a slot, and the load limit still applies, so nothing the trial relies on is lost. An abcd released before the race gate reads only load-wait.json, as before.

  • dcn-26101701264054122026-10-17

    2026-10-17 — A drain move renews only a lane its run still has in progress (facilitator-on-delegation, drain-many-accounts; refines dcn-2610170028405029): a lane the run has handed back, by its own step or as stuck, is renewed by no move, even while the drain has not yet routed it because its pace window is paused, so a reservation whose release origin refused is left to lapse or to the routing's release rather than kept alive by every move; a lane parked at land stays the merged-lane finish's to renew (grounds: a lease keep-alive belongs to work still being done, as Chubby and etcd sessions end with their client; review of spc-2610161044461448 step 7)

  • dcn-26101701185062732026-10-17

    2026-10-17 — A drain lane's sixty-minute stuck bound counts only the time across which its refusals kept coming (facilitator-on-delegation, drain-many-accounts; refines dcn-2610170005357588): the minutes run from the first refusal at the stage to the last one logged, never to the move that reads them, so a lane that refused once and then sat idle is not handed back by a move that came only to renew it; a refusal more than fifteen minutes after the lane's last, the drain's look-again time, starts the time afresh at that stage, as a quiet that long is not refusing; the count of identical refusals in a row is unchanged (grounds: the dead-letter bound counts receives, not wall time, so time without a receive is not evidence the lane cannot finish; the drain's fifteen-minute look-again as the cadence a host stepping as told keeps; review of spc-2610161044461448 step 5)

  • dcn-26101701165827252026-10-17

    2026-10-17 — A land fence that cannot read the reservation from origin is a wait by design, never a refusal a drain counts toward a stuck lane (facilitator-on-delegation, drain-many-accounts; refines dcn-2610170005357588 and dcn-2610170028405029): at the push and at the arming alike, any fetch the fence makes that fails is never logged as the lane's refused, whatever git says, since the drain's own read of origin at every move already waits on an origin it cannot read and gives up on one that stays unread through the outage schedule; a failure that reads as a lost network (implement.IsNetworkFailure) also waits on the shared outage probe, as the push's own failure does, and any other failure does not, because the network probe proves only the network back (grounds: one bound for an unreadable origin, the drain's, rather than a second one at the lane; the push's netFailure as the existing shape; review of spc-2610161044461448 steps 5 and 7)

  • dcn-26101700284050292026-10-17

    2026-10-17 — The landing's push fence renews with the tip's own term, and a lane it stops on another person's hold is handed back as stuck (facilitator-on-delegation, drain-many-accounts): the check before the push is the land fence's own act, a fetch and a live renewal of this person's reservation from this copy, made for every run that holds a reservation, an intent's included, since a duplicate pull request is as wrong there; it renews with the tip's own term (renewalTerm) rather than the fence's day, so the push neither cuts nor stretches the lease the arming later sets; its refusals are the fence's, contention, worded for the push; a hold now another person's, or released as finished on origin's default branch, is a refusal that cannot change, so the drain hands the lane back at once through the stuck lane's route, kind stuck, with no new hand-back kind; and the drain's renewal of the lane in progress reads the move's own view, renews only a lane not parked at land (the merged-lane finish renews those), and names a renewal that failed or found the hold another's in the move's next step (grounds: lease keep-alives as Chubby and etcd keep them, fencing before a write, and one canonical primitive for the stuck route; spc-2610161044461448 step 7; iss-2610161015393523)

  • dcn-26101700183078692026-10-17

    2026-10-17 — A drain's wait at the cap and on held work is a look-again time, not a gate (facilitator-on-delegation, drain-many-accounts): a move before waiting_until still looks, since passing over held work in the move's view fetches and pushes nothing, takes any issue freed since, and keeps the time first written while the same wait stands, so polling early never pushes the wait out; the cap is counted in the move's view for the holder this copy reserves as, read with no network act (claim.ReaderHolder), and where only the forge could name that holder, the reservation act's own count refuses with the typed claim.CapError, which the drain reads as the same wait; the cap's refusal stays an ErrRefused refusal, so abcd reserve still exits 2 on it, and only its advice changes, to waiting for a pull request to merge; held work is an issue passed over because another holds it or a footprint it shares, while an issue handed back on origin or one this checkout already has a run for is a person's and never keeps the drain alive; and the drain's state keeps schema version 1, its waiting_until and waiting being added as steps 1 to 3 added origin_wait and pending_hand_backs (grounds: a bounded poll as the standard consumer wait, the drain's pace window as its existing wait, and a closed vocabulary for what the state names; spc-2610161044461448 step 6; iss-2610161015371794, iss-2610161015422836)

  • dcn-26101700053575882026-10-17

    2026-10-17 — A drain lane's refusals are logged on the lane of an issue run only, and a stuck lane is discarded by the step verb (facilitator-on-delegation, drain-many-accounts): only an issue run, the run a drain or abcd build <iss-N> opens, logs a refused step, on its lane as the state's refused (the stage, the check, the reason, a count of the same refusal in a row, since when it has refused at that stage, and why it cannot change), so an intent's run still writes nothing on a refusal; the run record gains a line only when a new count starts or a refusal turns final, so a host polling a refusing lane does not grow it; the state's schema goes to version 13, which version-12 releases refuse as a newer abcd's file; the bounds are pace.stuck_refusals (bundled 3) and pace.stuck_minutes (bundled 60), claimed in the pace's namespace and read through its layers at every drain move rather than stored in the drain's pace, so a changed bound applies from the next move; a refusal that cannot change is a brief refused for an issue resolved or wontfix at the lane's base, and a land fence finding the reservation another person's or released as finished on origin's default branch; and implement step --discard takes a lane handed back as stuck, after which the issue run is complete (grounds: dead-letter redrive after a maximum receive count, as Amazon SQS maxReceiveCount, with the refusal contract of the loop kept where no drain reads it; spc-2610161044461448 step 5; iss-2610161015368630)

  • dcn-26101622574775712026-10-16

    2026-10-16 — Refines dcn-2610162239308903, the load gate's queue (iss-2610161634043273), on the gap it accepted and on how far its no-cycle claim reaches. The gap is larger than that record says. Two waiters whose start and pid disagree, as after the process ids wrap, wait on neither, and across accounts no hold keeps them apart, so re-checks that fall in one moment, before either shows in the process table as running its command, both open, and their commands overlap. Under --wait -- make preflight the overlap becomes a stall: each preflight's own gate, the inner waiter that takes its running ancestor's place, still counts every other waiter running its command as ahead, so each waits on the other's outer waiter and both stand until their two-hour timeouts. It needs a pid wrap, two accounts and coinciding re-checks. The mitigation uses no shared file, which iss-2610140638074587 still rules out. The command form shows itself in the table as running its command from the moment it opens, by a short-lived child of the waiter (a /bin/sleep, its mark, stopped once the command has started), waits two seconds (WaitOpenPause) and reads the table once more before it starts its command. If another waiter is then running its command, opened within that pause and the start tolerance, and has the lower pid, this waiter stands back: it stops its mark, gives up its hold, re-draws its jitter and waits again, while the lower pid keeps going. Because each opener is marked from the moment it opens, two that open at the same instant each see the other, and exactly one runs. A waiter stands back at most three times (WaitBackoffCap) and then opens without the look, so no wait goes round for ever. The plain form starts no command and neither marks nor looks. Within one account nothing changes: the hold already admits one. What stays open: a mark that cannot be started, a table that cannot be read at the look, the cap, and a process start slower than the pause. Rejected: having only the lower pid look, since an opener cannot tell that it is the lower of a disagreeing pair; and closing the stall in the inner gate alone, which leaves two plain race runs overlapping. The earlier record's 'whatever mix of code' covers this code and the pid-only waiters built before the start-order change, and nothing else. A waiter still running the branch's first version, which ordered the queue by start alone, waits on a higher pid that started earlier and can deadlock against pid-only waiters, and no change here can break that, since that waiter never runs it. So when this lands, any waiter running that start-only build is stopped and requeued.

    A further case stays open, named by the re-check review: the window the look uses (the pause plus the start tolerance) is measured from the look, not from the waiter's own re-check read. A waiter whose path from its re-check to its mark is slow under load can therefore discard a concurrent opener it did see, and both run; it is captured as iss-2610162306239284, with measuring the window from the re-check read as the fix.

  • dcn-26101622393089032026-10-16

    2026-10-16 — The load gate's queue (iss-2610161634043273) counts a queued waiter as ahead only when it is ahead by start time and also has the lower pid. Rejected alternatives: start order alone, as the branch had it, deadlocks against waiters built from code that predates the fix, which wait on every lower pid; on the night of 2026-10-16 a young low-pid waiter and two older high-pid ones each saw the other ahead for hours. Reverting to pid order alone also meets the no-mutual-wait property, but brings back the starvation after a pid wrap that the issue fixed. Telling old waiters from new ones in the process table is not possible, since both run the same arguments, so any safe rule may only wait on lower pids. Within that limit, start order AND lower pid keeps the most of the fix, and it is the smallest change: queueOrder and its chained-tie grouping are unchanged, and the pid check is one condition on top. Every wait from either code now points at a lower pid, so no cycle of any length can form, whatever mix of code and whatever each waiter's own read of the table. The grouping no longer prevents cycles; it only fixes the order within a chain of ties. After a wrap, an early high-pid waiter is held only behind waiters that started before it. Two waiters whose start and pid disagree wait on neither. Within one account the flock-serialised hold keeps them from opening together. Across accounts there is no shared hold: only the settle jitter of 15 to 60 seconds and the re-check keep them apart, and a re-check that reads the table in the moment between the other's open and its command showing in the table can still open. That gap is narrow and rare, since it needs a pid wrap, two accounts and coinciding re-checks. A pair in pid order has no such gap. It is accepted rather than closed with a cross-account file, which iss-2610140638074587 rules out.

  • dcn-26101620400341172026-10-16

    2026-10-16 — Refines dcn-2610161930191632: an approved command comes back as cd -- '<dir>' && {, a newline, the command, a newline and }, so nothing of it runs when the change of directory fails. The approver's list of agent launches (the program names, the flags that turn a harness's own checks off, the wrappers and package runners it reads through, the packages that ship a harness and the variables a harness reads its settings from) is a mistake filter in adr-42's sense: it steers an agent that starts another harness by an ordinary route. A harness started by a route outside that list, such as another program name, a copied binary or a configuration file it reads, is bounded by the OS sandbox for launched agents (spc-2610161751056096), not by the list. So a further form is added to the list when it is common, not to close the class.

  • dcn-26101620324462862026-10-16

    2026-10-16 — The status intake splits a branch's share between its newest and its oldest unread commits whenever the last intake left the branch unread: one the cap cut short in a walk, and one left without a walk once the cap was spent. The newest side takes the rounded-down half and the oldest the rest, so a share of one takes the oldest unread commit and every walk of a branch left moves its read mark. No tip is kept as asked because an app pushed it: a branch leaves the forge's queue once every standing announcement on it has a verdict, so an announcement an intake reads later at the same tip is still asked about. This refines dcn-2610161949032458 (spc-2610150728396006 step 3, on review), which named only a branch the cap cut short and kept a tip an app pushed as asked until it moved.

  • dcn-26101619490324582026-10-16

    2026-10-16 — The status intake keeps every branch it left unread, each with the turn it was left at, and walks them before any other branch, the one left first first; a branch walked and left again goes behind every branch already waiting, so no branch waits behind more than the branches left before it. Once the cap has cut a branch short, it takes half its share from its newest unread commits and the rest from its oldest, and its read mark moves up to the newest commit beneath which every commit is read, so every unread commit is read within a bounded number of intakes. The forge is asked about the branch waiting longest first, and each branch asked goes behind every branch still waiting; a tip whose newest covering push came from an app is kept as asked until the tip moves, so every branch is asked within a bounded number of fetches. This refines dcn-2610161907315656 (spc-2610150728396006 step 3 fix round 5, on review): one place to start from, a newest-first read of each branch and a fixed newest-first order of asking each let a branch that keeps gaining commits keep other announcements unread or unasked for good.

  • dcn-26101619311309112026-10-16

    2026-10-16 — Refines dcn-2610161826443524 on when a pending hand-back ends (facilitator-on-delegation, drain-many-accounts review round 2): it ends only when a release publishes it, or when it is no longer due: a tip already marking a hand-back, a record finished or changed on origin's default branch since the yes was judged, a record origin holds in no one file, or a tombstone the hand-back would take past its cap. A move that ends it unpublished says in its next step and in the route that it was dropped, and why, and never that it was published. A release that could not read origin's default branch at all (this checkout names none, or its tree would not read) keeps it pending, whether the release pushed a plain tombstone or found one already there, since that failure says nothing about the record and passes; the next move's release publishes it once the branch reads (grounds: dcn-2610161826443524, dcn-2610161837009957; spc-2610161044461448 steps 2 and 3; the re-review of the fix round).

  • dcn-26101619311226062026-10-16

    2026-10-16 — Refines dcn-2610161412283450 and dcn-2610161806433529 on a reservation made over a standing hand-back (facilitator-on-delegation, drain-many-accounts review round 2): a drain's reservation that would take over, or renew, the reservation at the issue's tip reads that reservation's first-parent line down to the tombstone it was made over, the same walk a plain release keeps a hand-back by, and backs off when that tombstone marks a hand-back whose record origin's default branch holds unchanged, whether the reservation over it is lapsed or still live, from this copy or another; a walk that cannot be read backs off too, since it cannot show the hand-back no longer stands. A person's own take-over or renewal goes ahead, as a person's own reservation over the hand-back's tombstone does. Reading the tip alone let a drain build an issue that waits on a person once that person's reservation over it lapsed (grounds: dcn-2610161412283450, dcn-2610161806433529; spc-2610161044461448 step 3; the re-review of the fix round).

  • dcn-26101619301916322026-10-16

    2026-10-16 — Refines dcn-2610161821420088: the headless approver runs each approved command from the working tree it judged it for. The host keeps the shell's directory from one call to the next, so an allow hands the command back as cd -- '<dir>' && <command>, the directory quoted as one literal word by internal/shellquote; a change of directory inside the line still holds for the rest of it. A relative removal target after a cd the line spells out and joins with && is read in that directory, and one after a change of directory the line leaves unknown is refused as a name the line does not place, with that reason. A removal (rm, rmdir, unlink, mv's sources, a find that deletes, an rsync --delete) whose fixed target lies outside the launched working tree, the run's own directories (the brief's and the receipt's, which the runner passes as --run-dir) and the temporary directory is refused. A write outside the working tree is judged as before, by the protected set alone: the OS sandbox of spc-2610161751056096 is what bounds those writes, not the approver. Three narrowings keep ordinary work from being refused: a git -c core.pager or core.sshCommand setting whose value is a fixed command is read as that command, as a bang alias already is, and approved when that command is clean, where git runs from the working tree and no earlier part of the line writes or removes a file; a glob removal whose fixed directory is inside the working tree and unprotected is approved unless a protected name could match the glob: one its literal text aims at (a name starting with a dot only by a pattern that spells the dot, as the shell does by default), an entry already standing in that directory that is or holds a protected path, or a protected path below it; and the words after a script's or a module's name belong to it, not to the interpreter, so node app.js -p 3000 and python3 -m pytest -c pytest.ini are approved.

  • dcn-26101619073268382026-10-16

    2026-10-16 — A forge record of pushes whose page is not full but that names no push to the tip this checkout holds is read as a record not read in full: nothing it leaves open is kept, and the next fetch asks again (spc-2610150728396006 step 3 fix round 4, on review). The forge records a push a little after it lands, so such a record is one that has not caught up yet, and keeping no pusher for those commits would have left them claimed for good.

  • dcn-26101619073156562026-10-16

    2026-10-16 — A status branch holding more new commits than one intake takes in is no longer shown as doubtful: it is left unmarked, the branches after it are not walked once nothing is left to take in, the block counts each branch left as not read yet, and the next intake starts at the branch after where this one stopped; continuity not verified stays only for a walk that itself ran out, refining dcn-2610161737571276 (spc-2610150728396006 step 3 fix round 4, on review). A read mark at the tip passed the commits the cap left over for good, and a lasting doubt told the person nothing they could act on.

  • dcn-26101618370099572026-10-16

    2026-10-16 — Refines dcn-2610161412283450 on the blob a hand-back is judged by when origin's default branch could not be refreshed (facilitator-on-delegation, drain-many-accounts review round): a stale branch reads the record at the blob it held when last fetched, so it can err either way: a hand-back made over a newer blob than that reads as changed though no one edited the record since (a drain may then take the issue), and a person's edit this copy has not fetched reads as unchanged until it is (a drain keeps backing off). Neither is bounded by the act; each lasts until this copy's next fetch of that branch succeeds, which every drain move and reservation act tries first. The earlier record's claim that a stale blob only reads as changed sooner was wrong. A release asked to hand back while the branch could not be read at all (this checkout names none, or its tree would not read) says so, rather than that the branch holds no one record of the issue (grounds: dcn-2610161412283450; spc-2610161044461448 step 3; the review of steps 1 to 18).

  • dcn-26101618355297572026-10-16

    2026-10-16 — A drain plan read from a commit reads the intent store from that commit too (facilitator-on-delegation, drain-many-accounts review round): the promoted rule's question for a record the consistency pass filed (which intents name it back in related_issues) is answered from the intent store as origin's default branch holds it at the commit the plan read the ledger from, read through one bounded cat-file batch and parsed as intent.Load parses the checkout's, so a checkout behind origin never hands such a finding to a lane that an intent on origin owns, and a draft half-written in the checkout never refuses a plan read from origin; the checkout's store is read only for a plan that reads the checkout's ledger, and a commit's store that cannot be read, or holds a malformed intent, refuses the plan as the checkout's would (grounds: spc-2610161044461448 steps 1 and 4; ruling H12, dcn-2610161425496537; the review of steps 1 to 18).

  • dcn-26101618270363202026-10-16

    2026-10-16 — A drain's reservation that renews this copy's lapsed reservation asks the fork question, and the lane a no opens on a judgement's hold takes the fork check from the recorded judgement (facilitator-on-delegation, drain-many-accounts review round, refining dcn-2610161040378209): that push makes the reservation the drain's hold afresh, the one a lane then opens on, so it asks the forge as a fresh reservation does, whether the drain takes it to ask a judgement or a lane's start renews a judgement's hold that lapsed before the no; a drain's renewal of a live hold, a person's plain reserve that renews, and every release still ask nothing. Each judgement keeps the hold it was asked on (judgements[].hold), so the lane opened on that hold in any later move names the check its reservation could not make or waived, not only the lane the answering move opens (grounds: spc-2610161044461448 step 10; dcn-2610161141338923; the review of steps 1 to 18).

  • dcn-26101618265579102026-10-16

    2026-10-16 — A drain move that has done anything writes it before it refuses, and says whether the answer given was taken (facilitator-on-delegation, drain-many-accounts review round): every refusal and error after the judgement block, the outage read, the merged-lane cleanup, a lane's routing, the run listing, the origin check, the judgement's reservation and its request, goes through refuseMoved, which writes the state a live drain holds first and then takes the judgement awaited as written as the one whose hold the move's clean-up keeps, so a hold the written state no longer records is released; a refusal after an answer was taken says it is not to be given again, and one met routing a yes before anything was taken says to give it again (grounds: dcn-2610161315385888; spc-2610161044461448 steps 2 and 9; the review of steps 1 to 18).

  • dcn-26101618265513092026-10-16

    2026-10-16 — A release the claim package refuses is never logged as released, and a hand-back never refuses a release (facilitator-on-delegation, drain-many-accounts review round): a tombstone that would pass the 4096-byte message cap, or the outbound policy, with its hand-back on it is pushed plain, and the result says the hand-back was not published and why (HandBackUnpublished), because a refused release leaves the issue held off every account until its lease runs out, which is worse than a hand-back a person can re-publish; a release the claim package still refuses for a reason of the tip's own is logged at reservation_release_failed, which the drain routing the hand-back tries again, never at reservation_released (grounds: review finding R1 on spc-2610031753359849 steps 1-3; spc-2610161044461448 step 3; the review of steps 1 to 18).

  • dcn-26101618264435242026-10-16

    2026-10-16 — A yes whose hand-back a move cannot publish keeps it pending in the drain's state and publishes it over the issue's next release on origin (facilitator-on-delegation, drain-many-accounts review round): when the hold the yes would release has moved on (this person renewed or reserved the issue again by hand, another took it over, a person released it), when the drain took none because this person held the issue live from this copy, or when the release did not reach origin, the route says the hand-back is not yet published and why, the drain keeps it (pending_hand_backs: issue, kind, the blob the yes was judged over, why, when) and carries it into the next drain, and each later move whose view shows the issue's tip as a tombstone marking no hand-back publishes it as that tombstone's child, fenced on the tombstone and on the judged blob; a tip already marking a hand-back, a record finished or changed on origin's default branch, or one origin holds in no one file ends it with nothing published. The drain never releases a person's own reservation to publish it, so it waits for the person's release rather than taking the issue (grounds: dcn-2610161040365515, dcn-2610161806433529, dcn-2610161315385888; spc-2610161044461448 steps 2 and 3; the review of steps 1 to 18).

  • dcn-26101618214200882026-10-16

    2026-10-16 — Refines dcn-2610161624025493: the headless approver's own checks read the guard's parse of the line, not its raw text. Writes and removals are the targets the guard's write model resolves (writesOf), in every shell state the reading placed each segment in, plus the operands of touch, mkdir, chmod, chown, truncate, rm, rmdir, unlink, mv's sources, ln's link targets and a sed script's w commands; a target the line does not fix (a variable, a substitution's output, a glob, or a relative name after an unknown change of directory) is refused, and a fixed one is compared, with its existing directories resolved through symlinks and its case folded where fsutil.CaseFoldingFS says the filesystem folds, against the protected set: the git common directory with its hooks and config, each core.hooksPath directory, each checkout's .git, the home shell start-up files and git configuration, the host's settings directories, .mcp.json and .abcd/guard.json, plus the harness's protected names as path components relative to the working tree or home. A line that only names a protected path is no longer refused. git config is refused with --global, --system or --file on a write, on setting a key that starts a program (the gitutil.ExecPins keys and git's documented program settings) and on opening the editor, and so is any git command setting such a key for itself. The approver takes --base, the lane's base or the worktree's HEAD at an interview's launch, and the working tree's registry is in force only where it is at least as strong as the one at that commit: any weakening, of a warn or a blocker, committed during the run or not, refuses every command, and a shell launch with no base is not started. An allow returns only the command and its description, and a call asking to run outside the host's sandbox is refused. Critical removals widen to home's direct children and the repository's other checkouts, and to a find that deletes from home or above, a move of a critical directory, an rsync --delete into one and a recursive chmod or chown of one. Code reaching an interpreter outside -c/-e is refused: on the standard input of a listed interpreter or ex that names no script file, an awk program that runs a command, a sed script with the e command or flag, tar's options that run a program, and a vim or ex command holding a !. A glob in a removal target is refused as not fixed except where it lists a critical directory, which the critical check refuses first. The checks read the line itself; a script the line runs is read for the registry's hazards, not for its own writes. The guard stays a mistake filter (adr-42) and this adds no sandbox (dcn-2610161619296615).

  • dcn-26101618142792042026-10-16

    2026-10-16 — The product thinker approved a measured trial of two preflights in their test stages at once, with the race stage kept to one at a time; the default stays one, and a person may raise it only for their own machine (load.preflights in ~/.abcd.noindex/config.json, or ABCD_LOAD_PREFLIGHTS), never from a repository file. So the setting takes 1 or 2 and nothing more: 3 and 4 are refused, saying the limit rises once a measured trial supports it. At the default of one the preflight runs exactly as before, its race gate opening at once.

  • dcn-26101618092596232026-10-16

    2026-10-16 — The fence for the agents abcd's runner launches (itd-2610161621364075 part A) is Anthropic's sandbox-runtime (srt, Apache-2.0, npm @anthropic-ai/sandbox-runtime, tested against 0.0.79, which is not an exact pin: an untested version is warned about and a failed trial launch refuses) for both the claude and the opencode runner, on macOS and Linux, run by abcd at its one launch point as srt --settings <per-launch file> -- <harness>, behind a fence seam (internal/core/fence: a fence-neutral Policy and a Fence interface with Check, Wrap and Refusals) whose one adapter, internal/core/fence/srt, runner.sandbox.backend selects with srt as its default. Grounds: ruling 6 names Anthropic's own fence while abcd launches Claude and rules out a fence of abcd's own; srt wraps any process, so one fence and one policy derivation serve both runners (one-canonical-primitive), which settles how opencode launches are fenced; it is the code Claude Code's own sandbox is built on and the vendor's guide names it for a whole-process boundary. Weighed and not picked: nono (Apache-2.0, Seatbelt and Landlock, pre-1.0, not Anthropic's; the first alternative if the srt probes fail), landrun and go-landlock (Linux only, and abcd would write the policy layer), bubblewrap alone (a building block, Linux only), nsjail (Linux only, built for jailing services), firejail (setuid root, CVE-2022-31214), a sandbox-exec profile of abcd's own (a fence of abcd's own, and the command is deprecated), Codex's sandbox (ships inside another vendor's agent; reconsidered when abcd launches Codex). An adversarial fit-challenge kept the pick and changed the design: the main git directory is narrowed to what a lane's commit writes with a ref check after each launch, srt's interpreter and package are admitted as well as its script, srt's placeholders are cleared after a killed launch, opencode's state is seeded rather than shared, and reads of credential stores a launch never needs are denied. srt is a new required program on the runner route and brings a network host list with it, since it refuses '*'; both wait for the product thinker's sign-off before anything is built. An advisor's fit review the same day kept the pick and changed the design again: GOPATH moves into the run's fence folder with the Go caches, since the checksum-database cache lives under it, and the hosts GOPRIVATE and GONOPROXY name join the host list; lane commits are proposed unsigned inside the fence and signed by abcd at land, so no signing key is opened to the agent; automatic gc is sealed off for each launch; the approver is abcd's own executable, admitted as srt is; srt is framed as adr-22's first declared exception, scoped to the runner route, with the per-machine off switch in place of degradation; and the probes now come before the sign-off. Five questions go to the product thinker with the sign-off, listed in spc-2610161751056096.

  • dcn-26101618064335292026-10-16

    2026-10-16 — A plain release keeps a hand-back that still stands (facilitator-on-delegation, drain-many-accounts review round): a release with no hand-back of its own reads the reservation branch's first-parent line below its tip, at most 256 commits, to the first tombstone, and when that tombstone marks a hand-back whose record origin's default branch holds unchanged by the reading handBackStands uses, the new tombstone carries its kind and blob forward and the result says so (Result.HandBackKept); the walk passes renewals and take-overs, and an unreadable commit, a plain tombstone, the root or the bound keep nothing. The carried tombstone names the person releasing as its holder, since the closed trailer form names no earlier holder and a new trailer would read as unreadable to every binary already released. A release asked to hand back over a tip a plain tombstone already released publishes the hand-back as that tombstone's child, fenced by Tip on the tombstone or the reservation it released; with HandBackBlob it publishes none once the record's blob is another. Reserving and releasing an issue is not a person's change to its record, and a failed build start's clean-up is not a person's decision, so neither erases the hand-back (grounds: dcn-2610161040365515, dcn-2610161412283450; spc-2610161044461448 step 3; the review of steps 1 to 18).

  • dcn-26101618033899402026-10-16

    2026-10-16 — The product thinker ruled that the forge's team (organisation) settings change only through its website, never through a command line, and that the machine's forge login holds no organisation-admin scope, so no agent on the machine can change the team's settings by accident; reading the settings is fine (iss-2610161732283346).

  • dcn-26101617375712762026-10-16

    2026-10-16 — A first read of a status branch that runs past the walk limit is always shown as doubtful, continuity not verified, whatever times its commits carry, refining dcn-2610161320457650 and dcn-2610161100416718 (spc-2610150728396006 step 3 fix round 3, on review). Within the bounded walk no signal settles whether a line older than what the read took in can still stand, so the read cannot say that nothing beneath it is live.

  • dcn-26101616553888092026-10-16

    2026-10-16 — abcd's own repository loosens its drain floors (product thinker, 2026-10-16, reversing for abcd alone the part of ruling H11 of 2026-09-29 that kept abcd's own repository at the stricter default): a drain in abcd takes any issue that needs no design decision, at every severity and including security, and takes the most urgent first, security and then critical, major, minor, nitpick. The bundled baseline that other projects get stays strict, and they loosen it in their own record as before.

  • dcn-26101616512861842026-10-16

    2026-10-16 — A drain takes a minor issue the after-merge fidelity check files again (product thinker, 2026-10-16): such an issue names the shipped feature it was filed about, yet the promoted hand-back does not hold it when it is minor, so small after-merge fixes get done unattended; a major or security one still goes through the feature's audit or a person's build. This refines dcn-2610161401449155 and dcn-2610161519047899.

  • dcn-26101616453607192026-10-16

    2026-10-16 — The messaging intent's promise holds as written (product thinker, 2026-10-16): a colleague's session sees an announcement before the session that made it pushes, not only before the work merges, so the build changes to publish the announcement ahead of the push rather than the press release being reworded (iss-2610161645224876).

  • dcn-26101616240254932026-10-16

    2026-10-16 — A headless claude run whose role's contract grants the shell gets its permission prompts answered by abcd's guard through the harness's --permission-prompt-tool, naming the one tool of an 'abcd guard approve' MCP server that the launch passes inline with --mcp-config and --strict-mcp-config, under --permission-mode default; the shell is no longer pre-granted on that launch, so every shell command the harness would ask about reaches the guard, which approves only a clean allow (no entry, signal or diagnostic, a program the line names, no inline code handed to a non-shell interpreter) and refuses every other prompt with the guard's reason. The expected shape, a PreToolUse hook in a per-launch --settings file, cannot work: --bare skips every hook, those --settings declares included (probed on claude 2.1.301: a SessionStart and a UserPromptSubmit hook from --settings ran without --bare and not with it), and dropping --bare would let the repository's hooks, plugins and CLAUDE.md run. A role whose contract grants no shell keeps dontAsk, which already refuses every prompt; opencode has no per-launch approval callback and is unchanged; the person's host settings are never touched. This change adds no sandbox; sandboxing autonomous runs is a separate later step (dcn-2610161619296615). Grounds: claude --help 2.1.301; code.claude.com/docs/en/cli-reference, /headless, /agent-sdk/permissions, /agent-sdk/user-input; live probes of the prompt tool's request and allow/deny answers, and of --bare connecting an --mcp-config server.

  • dcn-26101616210880502026-10-16

    2026-10-16 — The refusal of a bash -c or sh -c script built from variables that deletes (iss-2610161612200864) is read in code beside the payload reading, under the reserved id shell-c-variable-delete, and its SHELL rule is generated beside it, as the script reading's is (guard.ScriptLesson). Not a registry entry: the pattern language matches one command's words, and cannot say a -c string that holds a variable and a deleting command. Not a hand-written rule in defaults/rules.json: SHELL may not be declared there, and a new domain would be a second copy of the refusal's words, free to drift. Where the refusal and rm-unguarded-variable-path fire on the same line, the refusal speaks, because its rewrite includes that entry's; every other blocker keeps its own message.

  • dcn-26101616210286132026-10-16

    2026-10-16 — The product thinker changed the brief for iss-2610161612200864 from teaching alone to teaching and enforcement: the guard refuses a bash -c or sh -c script built from variables that runs rm, rmdir, unlink or shred, and the refusal says how to rewrite it (write the script to a file in one command and run it in the next; delete with literal paths through /bin/rm -f --, or a variable guarded as "${VAR:?}", outside the -c string), rather than warning. The agent gets the reason back and rewrites the command before the host would stop to ask a person. Only that shape is refused: a -c script with no deleting command, or one with no variable in it, still passes.

  • dcn-26101616192966152026-10-16

    2026-10-16 — Correction to dcn-2610161612269647: sandboxing autonomous runs was not declined. The 2026-10-16 question offered only teaching and per-launch approvals, after the sandbox option was dropped to fit the screen, so the product thinker made no ruling on it; it stays open, and the product thinker named it on the same day as an important feature for autonomous runs.

  • dcn-26101616141263052026-10-16

    2026-10-16 — The product thinker chose to ship the rule that has an agent check for an abcd command before writing its own helper script together with the scratch-folder rule, as a second rule in the bundled SCRATCH domain (iss-2610161614039496).

  • dcn-26101616122696472026-10-16

    2026-10-16 — Agents keep running past the host's permission prompts in two ways (product thinker, 2026-10-16): abcd teaches agents the command forms the host can check (iss-2610161612200864), and, for the agents abcd itself starts without a terminal, abcd answers the prompts per launch with its guard rules (iss-2610161612203555). abcd does not approve commands in interactive sessions, does not sandbox, and never edits the person's host settings.

  • dcn-26101615190478992026-10-16

    2026-10-16 — Refines dcn-2610161428244461: a person's own abcd build takes a promoted issue only when no other hand-back would hold it; the rule is asked again with promoted set aside, and an issue that security, category, severity, Waits on, a deferral or a missing remedy still holds is refused with that rule's reason, while the drain still hands every promoted issue back.

  • dcn-26101614282444612026-10-16

    2026-10-16 — An after-merge audit's owed-check issue reaches a lane through a person's own build, and a drain still hands it back as promoted (facilitator-on-delegation, drain-many-accounts step 4; a new record refining dcn-2610161401449155, since records are append-only): ruling DQ1a, that an undecided fidelity audit reopens the work and sends the feature back to a lane, is subsumed by ruling DQ1c, which says what reopening means for a shipped intent (it stays shipped and flagged, and one issue carries the owed check, dcn-2609300000000027), so DQ1a is met when that issue reaches a lane, and a person's abcd build <iss-N> remains the lane route for it: the eligibility check lets a promoted issue through with a note naming its intent, as dcn-2610161040365515 lets a person's own build through a hand-back, while every other hand-back is still refused. This overrides the resolution of iss-2608290820473197 where it says the captured issue is one "which a drain can take": a drain hands it back, and a person's build or abcd intent audit takes it (grounds: rulings DQ1a and DQ1c, dcn-2610161040365515, dcn-2610161401449155; iss-2610161015370582).

  • dcn-26101614254965372026-10-16

    2026-10-16 — A record the consistency pass files is outside the drain's promoted rule (facilitator-on-delegation, drain-many-accounts step 4): the pass writes into related_intents the two intents its contradiction is between, which are the finding's subjects and not intents that took the work on, so under the promoted rule its record would be handed back for good, against the product thinker's ruling H12 as dcn-2609290000000016 records it, that an automatic filer's record is filed and a drain passes it over only until a person writes a real remedy; such a record is skipped while it carries the machine remedy and may be taken by a drain once a person writes one. The record is told by the three fields the filer writes, category inconsistency, source agent-finding and a found_during opening "abcd intent consistency, finding ", which no other filer in the binary writes, and not by finding_ref, which a record the pass filed before keys existed lacks. This narrows the "no exception by source" of dcn-2610161401449155 by this one filer: every other issue whose related_intents names an intent, the after-merge audit's owed-check issue included, is still handed back as promoted (grounds: ruling H12; the filer's own fields in internal/core/capture/consistency.go; iss-2610161015370582).

  • dcn-26101614203143132026-10-16

    2026-10-16 — A drain does not ask a lapsed judgement request's issue again in the move it lapsed in, nor before a cool-down of the take-over margin (five minutes) from the move that dropped it, and then only after its other eligible work; that move releases the lapsed hold at once, every push a drain makes for a judgement is its hold except a renewal of this person's own live reservation, and a lapse is forgotten once its issue is asked again or answered. This refines dcn-2610161315385888: with no other work the tombstone and a new reservation landed in one move, so no other account ever had a window (spc-2610161044461448 step 2).

  • dcn-26101614122874792026-10-16

    2026-10-16 — A hand-back tombstone names one of seven kinds and is read fail-closed (facilitator-on-delegation, drain-many-accounts): the kinds are the drain's four routed kinds (user-visible, trust-rule, design-finding, second-package), unachievable for a lane stopped after its fix rounds, which is the kind its route already names, stuck and closed, while no-found-at is left out because it never holds a reservation; a kind outside them, a record blob that is not one full lowercase object name, either trailer without the other, or either on a reservation that is not released, reads the tip as unreadable as every other malformed known trailer does, the writer refuses it before anything runs, and every reservation is measured against the longest such tombstone with a SHA-256 object name so it can always be handed back (grounds: closed-vocabulary, fail-closed parsing of input on a shared remote as language-theoretic security recommends, the reservation reader's existing rule for malformed trailers, and dcn-2610150000000001; spc-2610161044461448 step 3; iss-2610161015370582).

  • dcn-26101614122840182026-10-16

    2026-10-16 — Every issue lane's hand-back is published, and a drain judges a standing one from its view before it pushes (facilitator-on-delegation, drain-many-accounts): a lane of a run abcd build <iss-N> started publishes its kind as a drain's lane does, since the step's release already serves both and a hand-back names a person's decision whoever started the run; a drain move passes over a standing hand-back in its view, whichever copy made it, before any push or judgement, and the reservation it pushes still backs off one the view missed, which is the compare-and-swap; and a checkout holds a record as origin does when git's object name for its open file, as git hash-object stores it, equals origin's blob at the commit the move planned from, a promotion a killed call already made being found first (grounds: the view-then-compare-and-swap order of dcn-2610161040368890, and content-addressed equality as git defines it; spc-2610161044461448 step 3; iss-2610161015370582).

  • dcn-26101614122834502026-10-16

    2026-10-16 — A hand-back stands while origin's default branch holds the record at the blob its tombstone names (facilitator-on-delegation, drain-many-accounts): the claim package reads that blob from origin's default branch as last fetched, as an entity tag names the version a conditional request was made against; only a blob read there that differs lifts the hand-back, never an unreadable branch or a record held in no file or in several; a blob read from a branch the act's fetch could not refresh can only read as changed sooner than a fresh one; and a release asked to hand back a record the branch does not hold in exactly one file pushes a plain tombstone and says why rather than refusing, so the reservation never outlives the hand-back (grounds: entity tags and If-Match in RFC 9110 sections 8.8.3 and 13.1.1, and git's content-addressed object model; spc-2610161044461448 step 3; iss-2610161015370582).

  • dcn-26101614014491552026-10-16

    2026-10-16 — An issue an after-merge audit files is handed back as promoted (facilitator-on-delegation, drain-many-accounts step 4): the owed-check issue names its audited intent in related_intents, so the promoted rule of invariant 19 hands it back to that intent whatever its severity, and its check is paid through abcd intent audit rather than by a drain lane; this replaces the as-built note of dcn-2609300000000027 that an undecided audit's minor inconsistency is one the drain takes, which was the lane's reading and not part of ruling DQ1c, and keeps the rule field-only with no exception by source (grounds: the spec's wording for the rule, dcn-2610161040365515, and one rule over special cases; iss-2610161015370582)

  • dcn-26101613204576502026-10-16

    2026-10-16 — A first read of a status branch that runs past the walk limit is shown as doubtful only while something beneath what it read could still stand: when the oldest commit it read does not read as an announcement, or was sent, by the time it carries, less than a day and an hour before the read (the longest life plus C9's one-hour slack), refining dcn-2610161100416718 (spc-2610150728396006 step 3 fix round 2, decided by the facilitator on delegation). Status branches only grow, so every new checkout's first read of a long-lived one passed the limit and showed a doubt for history that had all ended. The bound is the oldest commit's send time rather than its own expiry, since a commit beneath it, sent earlier with a longer life, can outlast it.

  • dcn-26101613153858882026-10-16

    2026-10-16 — A drain takes its judgement hold on an issue once per request and never renews it on a poll; a request whose hold lapses unanswered is dropped, the hold released, and the issue asked again only after the drain's other eligible work, since judgement requests had no expiry of their own and a host that kept polling held the issue indefinitely (spc-2610161044461448 step 2).

  • dcn-26101612232122182026-10-16

    2026-10-16 — reservation.fork_origin names the one fork whose reservations it allows, as "<owner>/<name>", instead of a bare "allow" (facilitator-on-delegation, drain-many-accounts): the key takes "refuse", the bundled default, or one owner and one name, each a plain GitHub name, read as before through the layered configuration and only once the forge has named an origin push URL a fork; a fork the forge names that is not the allowed one, compared without regard to case, is refused naming both, and a waived check is never silent: reserve, a run record and a drain lane say "origin is a fork the repository allows (<owner>/<name>)"; the bare "allow" is dropped, since it never shipped (grounds: a committed "allow" in a repository that is itself a fork is inherited by every fork of it, so a fork of the fork would reserve silently where no one working on the repository can see it; naming the fork keeps the waiver to the one repository the setting was written for; refines dcn-2610161141338923).

  • dcn-26101611413389232026-10-16

    2026-10-16 — A repository whose canonical home is itself a GitHub fork allows reservations there with reservation.fork_origin set to "allow" in .abcd/config.json (facilitator-on-delegation, drain-many-accounts): the key takes "allow" or "refuse", the bundled default, and is read through the layered configuration, the repository file winning over the machine file, only once the forge has named an origin push URL a fork, so a malformed key can stop no act on a repository that is not a fork; the fork refusal names the key (grounds: a fork that is the shared home of the work is where every account reserves, so the refusal would only stop it reserving; whether origin is the shared home is a fact about the repository, so its committed file may say so; refines dcn-2610161040378209).

  • dcn-26101611351222942026-10-16

    2026-10-16 — Reserving a record being reopened on a branch backs off until the reopen is merged (facilitator-on-delegation, drain-many-accounts): the finished-record back-off reads only origin's default branch, so while that branch holds an issue resolved or wontfix, or an intent shipped or superseded, a branch that moves it back to open cannot reserve it, and no flag gets past the back-off; the reopen is merged first, and the record is reserved once origin's default branch holds it open again; accepted because the default branch is the one view every account shares, and an exception for one branch would let a checkout reserve work that origin still calls done (spc-2610161044461448 step 1; iss-2610160957404827).

  • dcn-26101611004167182026-10-16

    2026-10-16 — A status branch this checkout has never read that holds more than one read covers is shown as doubtful, continuity not verified: more was added than one read covers, the same as a branch read from a mark (spc-2610150728396006 step 3 fix round, build note 24 extended; decided by the facilitator on delegation). A first read that stopped at the walk limit could otherwise bury a live announcement under a thousand ended ones with no sign.

  • dcn-26101610441876732026-10-16

    2026-10-16 — The drain bundle's pre-pass answers (facilitator-on-delegation, drain-many-accounts): brief invariant 7's sentences naming what drain and implement step fetch and push are amended, in each building step that adds an act, to name the per-move fetch, the reservation before a judgement, the hand-back tombstone, the renewal of the lane in progress, the parked lanes' pull-request listing, the fork question and the sync's fetch of the default branch; brief invariant 19 gains a clause that an issue whose related_intents names an intent is not taken; a hand-back published on origin is the record of a judgement kept on the reservation, not a field classification written onto the issue, so invariant 19's re-derivation stands; and each member keeps both against its siblings itd-82, itd-2609091034175565 and itd-2609151838312703, building on the first two (grounds: the invariants are the record of what may touch the network and what a machine may take, so they move with the surface, as the principle spec-moves-with-the-surface requires).

  • dcn-26101610403991172026-10-16

    2026-10-16 — A drain's pace reaches every lane (facilitator-on-delegation, drain-many-accounts): a drain carries its resolved pace and sub-agent ceiling into every lane it opens, and a running drain takes a new --pace or --sub-agents, recording them in its state and applying them from the next lane it opens and the lane in progress's next stage; a handed-back issue whose record blob on origin's default branch has changed is eligible again, and a finished handed-back run no longer passes its issue over (grounds: a setting the person gives is the drain's for its whole life, and a changed record is a new question; iss-2610161015417715, iss-2610161015457468).

  • dcn-26101610403987912026-10-16

    2026-10-16 — A restarted hosted drain takes over its holds (facilitator-on-delegation, drain-many-accounts): a hosted session that restarts recovers its drain with abcd drain --take-over, which moves the person's own live reservations from a lost copy to this one as the drain reaches them; abcd keeps no drain state outside the checkout, and the draft's press release is narrowed to match (grounds: the principle durable-state-lives-where-the-platform-says-it-survives, since where a hosted session's files survive a restart is the host's and abcd stays host-agnostic; iss-2610161015422306).

  • dcn-26101610403949702026-10-16

    2026-10-16 — A drain lane's stage shows in abcd peers (facilitator-on-delegation, drain-many-accounts): a drain lane's stage is published as a closed-vocabulary trailer on its reservation's renewal commits, and abcd peers lists it beside the reservation with each holder's hand-back tombstones of the last day; the people's status view inherits the same rows when it takes the reservation listing over (itd-2609151838312703, iss-2610150726331622); and the holder a process resolves through the forge is cached for that process (grounds: the reservation is the record every account already fetches, so the stage costs no new act; iss-2610161015434746, iss-2610161015433495).

  • dcn-26101610403900012026-10-16

    2026-10-16 — The drain's judge is a routed role (facilitator-on-delegation, drain-many-accounts): the drain's judgement is a new drain-judge role on the runner routing the build roles use; with no route the request goes to the host as today; abcd computes the remedy digest itself in either case (grounds: one routing for every model-run role, which the build roles already use; iss-2610161015422306).

  • dcn-26101610403851522026-10-16

    2026-10-16 — Generated files never block a reservation (facilitator-on-delegation, drain-many-accounts): generated files are declared with the forge's own linguist-generated attribute in .gitattributes, read from origin's default branch, and never count as an overlap; a person's own abcd reserve that overlaps another of their copies warns instead of refusing, while reservations a drain makes keep the back-off between one person's copies; and a lane's reservation narrows to the files its branch changed at its first renewal after the implement stage, since narrowing never widens a hold (grounds: the forge's linguist convention, and lock de-escalation; iss-2610152125101468).

  • dcn-26101610403840682026-10-16

    2026-10-16 — A drain lane merges the default branch first (facilitator-on-delegation, drain-many-accounts): the lane's sync step, which already merges landed sibling lanes and has the merge head validated, also merges origin's default branch whenever it has moved, before the records and the push, and is entered again from arming and from the merge wait when the open pull request starts to conflict; a conflict confined to declared generated files goes back to the implementer as a fix round under the host's permissions, with the validators judging the result, so abcd itself runs no command the repository declares; any other conflict hands the lane back naming the files (grounds: the forge ignores the merge drivers a local merge uses, iss-2609240646538011; iss-2610161015410527).

  • dcn-26101610403820672026-10-16

    2026-10-16 — A stuck drain lane hands itself back (facilitator-on-delegation, drain-many-accounts): a drain lane whose step has refused identically three times, or has refused at one stage for sixty minutes, is handed back as stuck and its reservation released; refusals that are waits by design, the preflight-receipt wait and an outage wait, never count; both bounds are configurable in the pace's layers; a refusal that cannot change (the issue finished at the base or on the default branch, or the hold now another's) hands back at once; and implement step --discard accepts a lane handed back as stuck (grounds: dead-letter redrive after a maximum receive count, as SQS maxReceiveCount; iss-2610161015368630).

  • dcn-26101610403809482026-10-16

    2026-10-16 — Parked lanes are read from their pull requests (facilitator-on-delegation, drain-many-accounts): each drain move reads every parked lane's pull request in one forge listing; a closed pull request releases its lane's reservation and hands the lane back, a conflicting one stops being renewed and is named in next, and a parked lane whose head is not yet on the default branch is named as waiting rather than skipped (grounds: the pull request's state is the evidence of the lane's progress, and one listing costs one request a move; iss-2610161015381750).

  • dcn-26101610403787132026-10-16

    2026-10-16 — An unreadable worktree refuses the move once (facilitator-on-delegation, drain-many-accounts): a sibling worktree abcd cannot read refuses the drain move once, before any reservation or judgement, naming the worktree and its repair, rather than reading as contention on every issue (grounds: a named refusal is repaired in a minute, while a queue silently emptied by one bad worktree costs a whole run; iss-2610161015397586).

  • dcn-26101610403782092026-10-16

    2026-10-16 — A fork origin refuses reservations (facilitator-on-delegation, drain-many-accounts): a fresh reservation and a drain's start ask the forge once per process whether a github.com origin is a fork, and refuse a fork, naming the repository it was made from and the command that sets origin to it; renewals and releases never ask, an origin that is not on github.com is not asked, and a forge that does not answer gives a warning and lets the act through, so a forge outage never stops leases being kept (grounds: a fork's reservation branches are invisible to every other account, so a hold there protects no one; iss-2610161015400509).

  • dcn-26101610403743432026-10-16

    2026-10-16 — A drain renews its lane's lease every move (facilitator-on-delegation, drain-many-accounts): every drain move, waiting or not, renews its in-progress lane's reservation at half its lease before its window gate, independent of the lane's progress; and the land stage checks the reservation before its push as well as at arming, handing the lane back at once when the hold is now another's, so a lapsed lease never becomes a duplicate pull request (grounds: lease keep-alives as Chubby and etcd keep them, and fencing before a write; iss-2610161015393523).

  • dcn-26101610403688902026-10-16

    2026-10-16 — A drain reserves an issue before it judges it (facilitator-on-delegation, drain-many-accounts): the drain reserves an issue before it asks any judgement over it, so the reservation push is the compare-and-swap that keeps two accounts from judging or promoting one issue; an issue or footprint another copy holds in the move's view is passed over with no push and no judgement; and within each group of one category and severity the drain takes file-scoped issues first and orders each part by a rendezvous hash of the holder, the copy key and the issue id, so accounts and copies spread across the group with no coordinator (grounds: competing consumers with skip-locked selection, and rendezvous hashing; iss-2610161015387318).

  • dcn-26101610403655152026-10-16

    2026-10-16 — A drain's hand-backs are published on origin (facilitator-on-delegation, drain-many-accounts): a drain's hand-back, from a lane or from a judgement, is the release of the reservation the drain took before judging, carrying a closed-vocabulary hand-back kind and the blob id of the issue record on origin's default branch, never free text; a reservation a drain makes backs off such a tip while the blob is unchanged, while a person's own abcd reserve or abcd build is let through with a note; a promotion the checkout cannot make because it does not hold the record as origin does publishes the tombstone alone and says so; an issue whose related_intents names an intent is ineligible, a clause added to brief invariant 19; and every account draining at once runs one build, since an older build reads the tombstone as a plain release (grounds: reasoned tombstones as Cassandra and Kafka keep them, and the fixed-form rule for the shared remote, dcn-2610150000000001; iss-2610161015370582).

  • dcn-26101610403643122026-10-16

    2026-10-16 — A drain waits when only held work is left (facilitator-on-delegation, drain-many-accounts): when the drain's holder is at the reservation cap, counted from the move's view before any reservation or judgement, or when every remaining eligible issue is held by others, the drain keeps its judgements, writes a waiting_until fifteen minutes on that is kept apart from the pace window, and names what it waits for (the holds, or the pull requests waiting to merge); it stops as empty only when no eligible issue is left, held or not (grounds: the drain already treats its pace window as a wait, and a bounded poll is the standard consumer wait; iss-2610161015371794, iss-2610161015422836).

  • dcn-26101610403524402026-10-16

    2026-10-16 — The three drain drafts are one bundle (facilitator-on-delegation, the product thinker having delegated the planning of the drain-many-accounts bundle on 2026-10-16): itd-2610161016394967, itd-2610161016391855 and itd-2610161016401115 are planned as one bundle, drain-many-accounts, with severity critical, major and minor; itd-2610161016401115 builds on the other two, which are independent of each other; the decomposition files each draft whole as an intent and routes two parts to clauses in brief invariants 7 and 19, and none to a new ADR, principle or brief page (grounds: the three are user moments of one run on several accounts, which the product thinker asked to have delivered together, and every part is drain behaviour inside records that already exist).

  • dcn-26101610403502562026-10-16

    2026-10-16 — A drain plans from origin's default branch (facilitator-on-delegation, drain-many-accounts): each drain move fetches origin inside the drain's lock before it reads anything, and takes one snapshot of the ledger from origin's default branch, which the plan, the lane's start check, the judgement's remedy digest and the reservation footprint all read; a fetch that fails, a default branch the fetch could not read, or a missing origin/HEAD means the move cannot plan and enters the drain's outage wait, never planning from what the checkout last saw; the dry run plans from the last fetched view and says how old it is, so it still writes nothing; a checkout behind origin is warned about, not refused, because the lane is cut from origin anyway; and any reservation of a record finished on origin's default branch backs off, with or without a tip (grounds: a queue consumer reads the row it locks, as SELECT ... FOR UPDATE SKIP LOCKED; iss-2610160957404827, iss-2610161015448977).

  • dcn-26101500000000012026-10-15

    2026-10-15 — Sessions under different accounts, on different machines and in cloud sessions tell each other what they are doing through short fixed-form notes on the shared remote, with no free text, and what is really a hold stays a reservation (the product thinker's ruling, "ok, agreed, option 1", choosing between the three options of research note 2026-10-14-session-messages-across-accounts; recorded on itd-2609151838312703 decisions 1 and 2). A forge coordination issue and a private side repository were the options not chosen.

  • dcn-26101400000000062026-10-14

    2026-10-14 — Planning interview of bundle ideate-librarian, after two adversarial reviews (design, record discipline; each an Opus and Sonnet pair) returned FIX_FIRST: the verdict fix (itd-2610141646454347) and private ingest (itd-2610141646467500) leave the bundle and ship as soon as each is ready; a verdict whose idea came from a private reading pack is always private; the shared research note is a person-run command, research (itd-2610142116477426), on the librarian's engine, whose agent step is library pack; leg-3 reviewers receive a pack's quoted items only; ideate record takes --private or --public and refuses to guess (adr-2610142116480836). The product thinker's rulings of the day.

  • dcn-26101400000000052026-10-14

    2026-10-14 — Bundle ideate-librarian (itd-2610141646126492, itd-2610141646452213, itd-2610141646454347, itd-2610141646456128, itd-2610141646467500) is kept out of the v0.16.0 release and built meanwhile, to ship in its own release cut right after v0.16.0 lands (the product thinker's ruling of the day, reversing that afternoon's 'join Friday's release'). Its major issue iss-2610141647304982 therefore must not be open on the default branch when v0.16.0 is cut: the records land after that tag, or with the fix.

  • dcn-26101400000000042026-10-14

    2026-10-14 — abcd never reads a file another account can write (the product thinker's ruling during the machine-load work of 2026-10-14, recorded here on 2026-10-15 from the design brief that relayed it; the original words were not logged at the time). It rules out a directory shared between accounts as a channel between sessions, the shape draft itd-2609151838312703 first proposed.

  • dcn-26101400000000032026-10-14

    2026-10-14 — Before 1.0 only the newest release is offered: the product thinker ruled, after the v0.14.1 cut, "We don't want to offer them prior to 1.0", choosing "Only v0.14.1" over the recorded newest-per-line rule (brief, launch chapter; draft itd-70), which would also have kept v0.13.4, v0.12.0 and v0.11.1. The eight earlier GitHub Releases (v0.14.0, v0.13.4, v0.13.3, v0.13.2, v0.13.1, v0.13.0, v0.12.0, v0.11.1) and their assets were deleted by hand that evening; their tags and the git history stay, so each is still buildable from its tag. Automating the removal at every cut, and changing the recorded rule to match, is iss-2610141938299842 ("auto remove previous ones"); iss-282 holds the older newest-per-line executor gap. Not chosen: newest per line, which keeps older builds on offer.

  • dcn-26101400000000022026-10-14

    2026-10-14 — The product thinker signed off on github.com/sigstore/sigstore-go and its transitive modules, added to verify release build provenance, and on moving google.golang.org/grpc from 1.83.1 to 1.83.2 to clear GHSA-2v4p-qf9q-27wj (an xDS server denial of service; abcd runs no gRPC server), which CI's dependency review raised on PR #990 (Product Q3, "Sign off, patch flaw").

  • dcn-26101400000000012026-10-14

    2026-10-14 — ideate: abcd-read-or-write-intent-md — verdict reframed. The idea, the three legs, and the rejected alternatives: .abcd/development/research/ideas/488a0aa96ac5de805348635b27036addf15cddc2/2026-10-14-ideate-abcd-read-or-write-intent-md.md

  • dcn-26101200000000052026-10-12

    2026-10-12 — A build next series counts a pick whose lane waits for a person to merge its pull request as done and moves on, as the drain does, so both verbs read that lane state through one predicate (the product thinker's ruling on itd-2609211116005482 decision 4 and criterion 5; iss-2610111014218303).

  • dcn-26101200000000042026-10-12

    2026-10-12 — R8's dated receipt for itd-2610031348087517 carries pictures as well as the text copies of the 80-column harness view: images of Q1, of each tab call and of the run that asks nothing after a no, taken in a fresh live session once the option-order change lands (the product thinker's ruling; iss-2610121442326914).

  • dcn-26101200000000032026-10-12

    2026-10-12 — In the README question pair asked through the host's question tool, the two parts that are off unless chosen (the managed-with-abcd badge and the table of contents) list off first, so a quick Enter leaves them out; every other part keeps on first, so the order differs between tabs (the product thinker's ruling, overriding the facilitator's fixed on/off/later order from lane-4 of run-2610110908176735; iss-2610121442314872).

  • dcn-26101200000000022026-10-12

    2026-10-12 — An existing abcd home is narrowed to the account's alone, reversing the 2026-10-04 decision that it keeps the mode it has (iss-2610120949163534), on the security standard ruling of 2026-10-11 (abcd fixes the risks it adds): a home made 0755 by an earlier abcd or by hand leaves every folder abcd keeps in it (worktrees, runs, history, lab, sources) readable by the other accounts in the home directory's group. At the CLI front door, before any verb runs, a ~/.abcd.noindex this account owns that is a real directory has its group and other bits removed (fsutil.NarrowToOwner, on the opened descriptor, never following a symlink); a symlinked home, one another account owns and an absent one are left alone, and nothing below the home is walked or re-moded, because closing the home closes everything in it. A lane worktree git adds into the store is narrowed the same way after the add. Writers keep their contract that a folder they find keeps its mode; only the home itself is narrowed. Not chosen: re-moding every folder below the home, which would change folders a person may have opened deliberately and gains nothing once the home is closed.

  • dcn-26101200000000012026-10-12

    2026-10-12 — Repository and tool text the implement loop keeps in a run's state.json (step titles, pick text, record notes, kept, sync paths, the landing URL, the runner's model, transcripts) is masked with termsafe both where the loop stores it and at every render that shows it, never refused at read time, so a run abcd wrote stays readable (the person's ruling as technical facilitator, "both: mask when stored and when shown"; iss-2610121542240257).

  • dcn-26101100000000032026-10-11

    2026-10-11 — Security work is scoped by one rule, the product thinker's ruling of the day: abcd fixes the security risks it adds, never changes how a repository works on its own (its hooks, content filters, large-file storage, merge tools and remote transport), and helps prevent a risk that exists without abcd only where it can do so without such a change; otherwise the finding is closed with that reason. Recorded as the principle abcd-fixes-what-it-adds, injected into security sessions by the SECURITY domain in .abcd/rules.json, and stated to reporters in .github/SECURITY.md. Fixes already shipped that switch a repository's own settings off for abcd are to be reviewed against it separately.

  • dcn-26101100000000022026-10-11

    2026-10-11 — The merge queue builds four entries at once again (main protection ruleset 19969675; the technical facilitator's ruling, amending the same day's ruling of two). #933 took macOS off pull-request runs (one race pass of about 25 minutes) and queue-sweep cancels superseded queue runs, so only queue entries and the nightly run use the five macOS runners; four parallel builds leave one runner for the nightly run. The 90-minute check timeout stands.

  • dcn-26101100000000012026-10-11

    2026-10-11 — The merge queue builds at most two entries at once and waits 90 minutes for a group's checks (main protection ruleset 19969675, was five and 45; the technical facilitator's ruling). Every queue entry and every pull-request push runs a macOS job, and the account runs five macOS jobs at a time at about 25 minutes each, so with five parallel builds the waiting entries passed the 45-minute timeout and were dropped. Each drop rebuilt the queue, and the superseded group's runs, whose gh-readonly-queue refs are gone, kept holding macOS runners, so nothing merged from 03:36 to past 08:40 on 2026-10-11 while ten stale runs were cancelled by hand. Fewer parallel builds make each entry wait its turn longer; the cancellation of superseded queue runs in CI is a separate fix.

  • dcn-26101000000000062026-10-10

    2026-10-10 — A finding of the ruthless reviewer of lane-1 of run-2610101926030564 (iss-2610090642392144) is deferred, not fixed in the change that puts a verifier's copy outside every working tree: the bundled OPINIONS rule in internal/core/rules/defaults/rules.json ("The user's directory is theirs") still allows a verifier's copy in the checkout's .abcd/.work.local/ tier, against the repository's own CONCURRENCY rule, AGENTS.md, itd-193 and the users-directory principle, which now forbid it. Reason: the bundled rule is injected into every managed repository, so changing it is a user-visible change the issue's remedy did not name, and it waits on a person's ruling, recorded as iss-2610102021042657.

  • dcn-26101000000000052026-10-10

    2026-10-10 — Three defects the reviewers of PR #886 (itd-2609201925079472, run-2610100550297632) noted below their bar are deferred, not fixed in the change that set the bundled pause to zero: iss-2610100913086397 (a rate-limited validator whose partial return cannot be saved aside leaves its lane stuck, its named --restart refused), iss-2610100913088696 (the rate-limit checkpoint matches an await by receipt path alone, against its comment) and iss-2610100913096412 (the run-start quota query has no deadline and its error is not home-redacted). Reason: each needs a tested change to the rate-limit and budget code in internal/core/implement/loop/, which steps 3 to 5 of spc-2609212015054359 (itd-82, the drain) rework next, and none is reachable in a run today without a second fault: a refused save-aside on a rate limit, an operator restart racing the dispatch, or a quota-reporting runner, of which none ships. They are taken up with the rate limit's own wait (iss-2610100602595553), or by the drain's steps where those touch the same code.

  • dcn-26101000000000042026-10-10

    2026-10-10 — A target's refusal is an error in bare abcd lint, whatever its rule's findings weigh (iss-2610100649479892). The 2026-07-13 warn mapping stays for findings: re-raising a docs blocker or a site gate failure would double-gate one check. A refusal is not a finding: a docs-lint config that will not load or that the engine refuses (a roots entry that does not exist), a site that will not render, a positioning registry or identity block that cannot be read each checked nothing, and the target alone exits 2 on it, so its rule raises one error finding naming the target and quoting the refusal, and the aggregate exits 2. docs-currency also runs wherever .abcd/docs-lint.json exists, not only where docs/ does, since roots need not include docs/; skipping it there hid the refusal entirely. A repo with docs/ and no config stays a warn: that is a repo that never adopted the docs target, not one whose target refused.

  • dcn-26101000000000032026-10-10

    2026-10-10 — Five points spc-2609212015054359 step 1 (scope 3, the host judgement before a drain's lane opens; itd-82 criterion 2) left open, settled by lane-1 of run-2610101724174688 in building it. (1) The host-pass shape is the loop's own: the drain writes one request, .abcd/.work.local/run/drain-judgement.request.md, records the issue and the sha256 of the remedy it shows in its state as judging, and opens nothing; the host writes strict JSON to .abcd/.work.local/run/drain-judgement.json and hands it back with a new flag on the bare verb, abcd drain --judgement <file>, which accepts only that path. The answer echoes issue and remedy_sha256, so an answer written for an earlier request, or over a remedy rewritten since, cannot be taken for this one; a remedy rewritten while the answer is out refuses the answer and the next move asks again. (2) The spec's yes/no carries a kind with a yes, user-visible or trust-rule (trust-rule when both, since it names the decision a person owes first), and a yes is routed exactly as a lane's hand-back of the same kind (promoted with capture promote, or flagged as needing a decision record with the reason as its question), with from: "judgement"; the intent's press release routes "an issue that needs a decision" by kind whatever found it, and a second routing for the judgement alone would be a design the record does not ask for. (3) The request tells the host to answer yes when the remedy does not let it tell, since the judgement guards a failure that runs one way and can only hand back. (4) An answer over an issue that left the eligible set since the request is recorded with applied: false and a note and decides nothing, which is criterion 2's "never makes an ineligible issue eligible" at the moment the answer arrives; a no is bound to the remedy's digest, so a rewritten remedy is asked about again before its lane opens. (5) --max keeps counting lanes, as it did: an issue the judgement hands back opened no lane, and the intent's "issues attempted" is read as lanes attempted. abcd build <iss-N>, a person's own start of one issue's lane, asks no judgement: the judgement is the drain's unattended pass, and the person typing the id is the judgement.

  • dcn-26101000000000022026-10-10

    2026-10-10 — Four points spc-2609301921521360 left open, settled by lane-1 of run-2610100550297632 in building it (itd-2609201925079472 criteria 7 and 8). (1) A runner's quota is counted in agent runs (runner.Quota.Remaining, reported through the optional runner.QuotaReporter), and the estimate from the spec's size is the least the run starts: per step to build, one implementer and one round of the two reviewers, and the fidelity audit once for an intent; fix rounds and syncs are not foreseen. Neither shipped runner reports a quota (the claude CLI and opencode expose none a launch can read before it starts), so today every run names its runners and skips the check out loud; the comparison is reached by a runner that reports one. (2) The rate-limit response is read from the claude CLI's own events, a rate_limit_event whose rate_limit_info.status is rejected or an assistant message whose error is rate_limit, on a run that did not finish; opencode's error events carry no rate-limit shape this build has verified, so an opencode limit stays a refusal and falls back as before. A rate limit is never fallen back on: every route spends the budget the window paces. (3) "Checkpointed to its branch" reads as the restart of 2026-10-09 reads a gone agent (iss-2610080620372731): the limited agent's uncommitted work and partial receipt are saved aside for review, never built on, its worktree reset to the branch's last commit, and its await dropped so the first step after the pause hands the same work to a fresh agent; a limited validator has only its partial return saved aside, since it edits nothing and may share the worktree with its round. Every other lane with work in flight is checkpointed at its branch's head in the record and left running, its agents' receipts still taken inside the pause, because their agents are not this process's to stop. (4) The pause after a rate limit is the run's own pause minutes, not the reset time a harness reports (decision 2 of the intent), and a pause already running is kept.

  • dcn-26101000000000012026-10-10

    2026-10-10 — Ruling of the product thinker on the bundled pace (given in a build session, on the report that its run had entered a 300-minute pause): "Remove that forever, we don't need a pause", then "it must be set to zero by default". The bundled pause of decision 5 of itd-2609201925079472 (120 minutes of work, 300 of pause) becomes 0: BundledPauseMinutes is 0, so a run that sets no pace runs window after window with no pause, and a repository or machine that wants one sets pace.pause_minutes. The working window, the sub-agent ceiling and the fix rounds are unchanged. The intent's record keeps decision 5 and its first criterion as written (120/300), which this entry supersedes for the pause; iss-2610100546338578 carries the change.

  • dcn-26100900000000012026-10-09

    2026-10-09 — Rulings of the product thinker on the three hand-backs of the 2026-10-07/08 autonomous drain (asked by abcd-0b, one question at a time, answers verbatim): (1) iss-2609251618079479, whether the build-sequence chapter's build-milestone sense retires with the phase: "Rewrite in today's terms" — 06-delivery/01-build-sequence.md stays a current chapter, its build order restated as dependencies with no milestones (neither retired as history nor kept as a second sense of the word). (2) iss-2610040758569116, whether an agent may run 'abcd decide accept', which stamps the person's git name as accepted_by: "Agents too, disclosed" — no guard block as for 'source ledger --flip'; the commit's Assisted-by trailer is the disclosure. (3) iss-2610030956156354's open design point, whether a step still falls back to the agent harness when the size count already sent the brief to the person's own model server and the chat call then fails: "Move to the harness" — no answer received is the trigger, not nothing sent; recorded as iss-2610090701491123, since the resolved fix stops instead.

  • dcn-26100700000000012026-10-07

    2026-10-07 — Ruling DR3 of the person (2026-09-29, in the human-step interview run for autonomous run A and relayed by its interviewer abcd-23 [b1e81b]), restated for iss-2610020728128805 (recorded by lane-1 of run-2610071733272557, records only). The answers of that interview are kept in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md, line 31, and are restated here because that file is not committed. DR3, verbatim: "itd-60 docs-fidelity verdict: FOUND AUTOMATICALLY by spec close and launch ship (a saved verdict labelled with the reviewed code's fingerprint; match -> proceed; none/stale -> refuse 'run the docs review first'), like the preflight receipt." It is the ruling the doc-fidelity gate's shape rests on (itd-60, ac-2: the semantic layer is a saved review for HEAD that spec close and launch ship find automatically, rather than a review run at the close), cited by internal/core/docfidelity/store.go, internal/core/docfidelity/docfidelity.go and internal/core/lint/gatereceipt.go. The issue was captured on 2026-10-02 against the 2026-09-30 entry above, which restates DR1, DR2, DR4, DR5 and DR6 and skips DR3; that entry is left as written (DA002). The 2026-10-02 entry of lane rd2 above already restated DR3 later the same day, after the capture, together with CB1, CC1, CD1 and CD2, and DQ2b and CJ1b have their own 2026-09-30 entries, so none of the rulings the issue names as owed is still missing; this entry adds the issue's own pointer to the ruling and changes no earlier line.

  • dcn-26100500000000022026-10-05

    2026-10-05 — Decided without asking (facilitator default, recorded by abcd-e8 at abcd-d7's direction while the person is away): the dashboard refuses a node shared into the tailnet from another account, and a request relayed by another node's Serve or Funnel, until the person decides; decision 4's 'anyone on your Tailscale' did not settle either, a shared-in node belongs to someone else and a Funnel relay is the open internet, so refusing is the safe default. A raw TCP relay cannot be told apart and stays a residual.

  • dcn-26100500000000012026-10-05

    2026-10-05 — Release v0.13.0 is cut by the coordinating session abcd-d7 while the product thinker is away, and the run's agenda line is: approve the publish step. Under the product thinker's rulings of 2026-10-04 (~10:05Z, verbatim: "Yes, that order", to cut v0.13.0 now with the home rename #815 inside it and rename the folder on their return; "Yes, approve it", for the coordinating session to approve the GitHub publish deployment itself once every check has passed, then verify the downloads and the site; ~13:35, leaving overnight: "keep going autonomously so we can have a new release tomorrow morning"), the session approves the release environment's deployment of v0.13.0 only after the merge queue, the verify job and every other gate on the tagged commit report green, and stops with a handover instead if any does not. The cut: v0.13.0, impact breaking (decided by itd-2610030720038073, the home folder renamed to ~/.abcd.noindex with every abcd entry point stopping until the person renames it; itd-2610030814013772, AGENTS.md the one conventions file; and iss-2610020723185314, only a personal route hands a role to a command-line runner), 55 records since v0.12.0: five shipped intents (two breaking, three additive: itd-201, itd-2610030810350727, itd-2610030821294016) and 50 resolved issues (41 fixes, one additive, one breaking, seven internal and outside the changelog); the release guard and the findings guard passed. The noindex intent's scan receipt (D6) was taken on a .noindex probe folder before the rename, with consent, and adr-2610030720195401 accepted with brief invariant 21 (6538ab4a). Brief fidelity: three tier-full reviews and their holds brought 25 brief sentences current before the close (9d57917c, 9e6e0aa0), and the guide's own review found one false sentence, corrected to say the rename is done in a plain Terminal (cde071b9, 405cf34d). Content commit c6441dc0, on top of 3a092b89, which the cross-check's one fix-before-tag finding required; both semantic gates ran at tier full over the first roll 317cd0cc, which differs from the content commit only by that commit and the re-cut CHANGELOG. The docs-currency-reviewer (Fable 5.1) found 2: dc-1 accepted as written (while only ~/.abcd stands the plugin root holds no binary, so the hook refuses the rename too and the pages describe what the person meets), dc-2 a nitpick deferred to the next release notes. The brief-surface cross-check (45 pinned checkers, Opus 5.5, at most eight alive) found 144 (31 major, 94 minor, 19 nitpick), 143 valid and one invalid (x-036) on an independent classification (Fable 5.1); of the three user-facing findings x-065 (abcd build --help said the sub-agent ceiling is not counted, where it binds through implement step since ruling DR6) is fixed in 3a092b89, and x-010 and x-042 are minor and deferred; the 140 design-record findings go to the systematic brief pass iss-2609091956001547. Deferred out loud, to be captured after the tag as two records: launch ship reads the records at HEAD, so a spec close left uncommitted was silently missing from the cut rather than refused (the close was committed as 44a73e6f before the ingest), and docs fidelity --apply flags the drafted replacement while the landed sentence was hand-tidied, so .abcd/work/brief-review-flags.json carries the drafted wording for 10-docs, 15-prepare-this-repo, 22-site, 23-reading and 27-implement. Reason for deferring: neither changes what v0.13.0 ships, and the person's ruling was a release by morning.

  • dcn-26100400000000102026-10-04

    2026-10-04 — Ruling of the product thinker, correcting the entry above (asked by abcd-e8; the first question wrongly said only the title named the harness; answer verbatim: "Reword both sentences too"): the two press-release sentences of itd-2610030821294016 that read "from inside Claude Code" read "from inside your coding session", like the title, so the site's featured announcement stays host-agnostic. Nothing else in them changes. Alternatives not taken: let a featured announcement name the tool; feature an older intent.

  • dcn-26100400000000092026-10-04

    2026-10-04 — Ruling of the product thinker (asked by abcd-e8, one question, answer verbatim: "Reword the title"): the shipped guided-connect intent itd-2610030821294016's title becomes "Connecting a model service from inside your coding session looks up the details and offers the choices". The site features the newest shipped intent whose audit is met, and its banned-token gate keeps the published surface host-agnostic, so a title naming the harness made the site unpublishable once the intent's audit was recorded. The record's body keeps naming the harness. Alternatives not taken: let feature titles name a tool; feature an older intent.

  • dcn-26100400000000082026-10-04

    2026-10-04 — Rulings of the product thinker on closing itd-2610030810370060's spec spc-2610030911534855 (asked by abcd-e8, one question at a time, answers verbatim): (1) "Ship it as partly done": the spec closes with --remainder and the intent stays planned, because iss-2610040025088395 (an answers file that stops at a question decided during the run leaves the earlier steps' writes) keeps criterion B3 from holding in that case; (2) "Add it to the remaining work": the AI-written interviews in a Terminal take a typed answer (the typed part on the question type) as well as the role's drafts; (3) "Add a real run to the remaining work": one real AI-written interview on the person's own runner route, with the person, before the intent is marked done, to confirm the change guard does not stop on what the runner itself writes. Alternatives not taken: ship as finished with the issue tracked; leave the drafts-only answers; skip the real run.

  • dcn-26100400000000072026-10-04

    2026-10-04 — Decided without a question by abcd-50 (one defensible answer), on the security review of the home-mode fix (iss-2610032205304585): an existing abcd home keeps the mode it has, because every home-scope writer's contract is that a level which already exists keeps its mode (fsutil.EnsureHomeScope, fsutil.EnsureRealDir) and re-moding a folder on the person's machine is a change the issue did not ask for; the two records an earlier version wrote 0o644 (the path-entry record and the registry's index) are narrowed to 0o600 at their next write instead (the bootstrap re-stamps path-entry at every provision, the registry rewrites its index at every registration), so on an existing 0o755 home the residual is that other accounts can list the folder's names, never read a record abcd keeps there. Not chosen: chmod an existing home to 0o700 when the account owns it.

  • dcn-26100400000000062026-10-04

    2026-10-04 (the product thinker, working hypothesis, not a ruling): a brief is the product thinker's target design, written in present tense as the vision of the finished product; abcd makes it real step by step through the technical facilitator, deterministically: each brief section lists the intents and implementations that realise it, and a brief change is assessed for a new intent or issue, or for a contradiction with a filed, planned or built intent, which owes the product thinker a design decision. Under test on another repository; a state-of-the-art pass follows. Recorded on itd-61, itd-142 and itd-143.

  • dcn-26100400000000052026-10-04

    2026-10-04 — Decided without a question under the person's ruling that an obvious answer is decided (lane e8term3fix of autonomous run A, on sec-e8term3 finding 5; iss-2610040025088395): the gap with B3's "writes nothing" is split. This branch settles before the install's first write what is fixed before the run: every answers-file entry whose question has a fixed set of answers is checked against that set, and every config value the run would ask is walked by ahoy.WalkConfigValueQuestions, which follows the install's own collection (collectMissingValues), so those refusals write nothing and say so. The questions whose asking the run itself decides (the status line's elements, the routing and status-line offers, the lineage question, the house-style question, the artefact kind) are still checked when they are put, and their stop now says that what the steps before it changed stays; iss-2610040025088395 stays open for them, waiting on a question plan in core ahoy, the setup questions' owner's area. Why: the config values depend only on detection, the flags and two answers given before any write, so they can be settled without the plan, while the rest depend on state the steps before them write. Alternative not taken: holding the whole fix for the plan, which would leave the common case (a missing visibility leaving .abcd/config.json behind) open.

  • dcn-26100400000000042026-10-04

    2026-10-04 — Decided without a question (lane e8term3 of autonomous run A, spc-2610030911534855 step 3, on sec-e8term2 finding 5): the plain-Terminal answer loop's relay of an outside SIGINT, SIGTERM or SIGHUP (term.RawSession restores the terminal, resets the signal and raises it again, so no deferred function runs) stays as it is, and no Hooks.Ending is added. Nothing that draws a question runs under signal.NotifyContext or holds a lock or a temporary file across a question: the one NotifyContext in the tree is abcd build's runner loop, which asks nothing, ahoy install asks every question outside its config, rewrite and history locks, and ahoy remote apply and site setup hold none. For these front doors the relay is parity with an unhandled signal; ask.Terminal's documentation says a caller under a NotifyContext must not draw. Alternative not taken: a Hooks.Ending callback, which would have no caller.

  • dcn-26100400000000032026-10-04

    2026-10-04 — Decided without a question (the person's ruling that an obvious answer is decided; recorded by abcd-e8): the guided connect carries at most 32 KiB of listed ids between turns, with the count not carried, because a 5,000-id list exceeds Linux's per-argument limit under sh -c and costs the session ~80K output tokens a turn; real services list a few hundred. Alternative not taken: one more keyless listing on a miss, which breaks the one-request rule of G2.

  • dcn-26100400000000022026-10-04

    2026-10-04 — itd-2610030814013772's press release names no specific agent tool: "for Claude Code or for any other tool" reads "for any tool" and "an older Claude Code" reads "an older version of your agent tool" (ruling of the product thinker, 2026-10-04, answer "Use the reworded text"). Asked because the intent's fidelity audit made its press release the website's front-page hero and the site gate refuses user-facing text naming a specific agent harness; the alternatives offered were keeping the name as a one-off exception and deciding later. The filing-time wording, superseded at the planning interview, moved out of the press release to its own section unchanged (the orchestrator, without a question: it is history, not the confirmed text).

  • dcn-26100400000000012026-10-04

    2026-10-04 — Ruling of the technical facilitator, asked by abcd-50, on who reconnects the git worktrees that renaming abcd's home moves (iss-2610040147016103: git records a worktree's location in absolute form, so after mv ~/.abcd ~/.abcd.noindex each repository lists every store worktree as prunable until git -C <worktree> worktree repair runs, and a prune deletes its link), verbatim: "Person, one printed command". Not chosen: abcd repairing them itself on its first run after the rename (a write into each repository's .git/worktrees, outside abcd's home, against itd-2610030720038073 decision 6); decide later. Applied: both stop lines of spc-2610031309233367 print for w in ~/.abcd.noindex/worktrees/*/*; do git -C "$w" worktree repair; done after the rename command, recorded as that spec's open question 6, with TestPrintedRepairReconnectsMovedWorktrees proving the loop.

  • dcn-26100300000000052026-10-03

    2026-10-03 — The visibility question's public answer carries its caveat about records git already tracks only where .abcd/ holds tracked files, and the flag hint every flagged question shares is reworded so its change-later line fits one row (the orchestrator of autonomous run A, 2026-10-03, choosing option (b) of iss-2610031236155833's "Fit 2026-10-03" choices because it drops no fact; applied by lane setupFit2). Core decides the per-repository help (ahoy.HelpIn, on the same evidence the install narrows the public ignore block on); the front door only renders it. Private's advice, that it suits a repository whose code is not published, stays.

  • dcn-26100300000000042026-10-03

    2026-10-03 — The machine's model-tier routing offer in ahoy install says abcd's proposal in counts, never one row per agent (ruling of the product thinker, 2026-10-03, relayed by the orchestrator of autonomous run A; applied by lane setupFit2; iss-2610031236155833). Asked: setup offers a plan giving each of abcd's 16 helpers a model level, and with all listed it cannot fit (options: counts only, split into parts, let it scroll, decide later). The answer, verbatim: "Show counts only". The question stays one yes-or-no answer; the counts are computed from the bundled proposal and the written table is unchanged; acceptance criterion 2 of itd-2609170822093401 is amended to match.

  • dcn-26100300000000032026-10-03

    2026-10-03 — Decided without a question (the person's ruling that an obvious answer is decided; recorded by abcd-e8): iss-2610032115023656, a SIGTSTP sent from outside stopping the plain-Terminal answer loop with the terminal raw, is won't-fix under its remedy A. An interactive job-control shell restores its own terminal state when a foreground job stops, and the session re-enters raw mode and redraws once on SIGCONT (pinned by the fix round's pty case). Remedy B, process-wide stop handling in internal/term with the kernel's orphaned-process-group rule reimplemented, risks a stopped abcd that nobody continues. The security review's own fix does not work in Go, because the runtime keeps its handler and drops the signal. Alternative not taken: remedy B.

  • dcn-26100300000000022026-10-03

    2026-10-03 — Ruling of the product thinker, asked by abcd-50 one question at a time, on where the status board lists the intent that starts next (iss-2610031207397996; it was listed under Now marked next up and again under Next), verbatim: "Under Now only". Not chosen: under Next only, at the top (Now would mean building alone, at the cost of reversing criterion 3 of itd-2609212103568351, that Now holds the head without a state file); decide later. Applied: statusblock.Read drops the head from Next, so the bare board, --json and the site's Status page list it once, and the shipped intent's Audit Notes record the amendment to its criterion 1. Decided without a question in the same change (technical facilitator): the board's width is the terminal's when stdout is one and 80 columns otherwise, whatever COLUMNS says, so piped output is the same on every machine; a wrapped line continues four columns past its own indent; a review row begins at column four with its stale mark at its end, so the levels are indented two, four and six.

  • dcn-26100300000000012026-10-03

    2026-10-03 — Reserving work across people (product thinker, at an interactive interview, with a second person now working on this public repository). Rulings: anything kept on one computer (the local tier, a desktop note, same-account messaging) is never the record of who works on what, because the other person never sees it; an item is reserved by a reservation branch on the shared remote, abcd-reserved/<record-id>, which abcd lists and nobody merges, chosen over a hidden ref because a hosted cloud session can push branches only (probe of 2026-10-03 and the host's documentation); a hosted cloud session takes part exactly as a second person's machine does; itd-2609091034175565 is planned and built today with every acceptance criterion, and the session register itd-2609150819440345 stays a draft for later; outside contributors, who cannot push a claim branch, are the follow-up itd-2610031259176838, not urgent. The ruling of 2026-09-22 ("Cross-account and cross-machine agent communication stays out of the run") covered the run of 2026-09-23 only, confirmed by the product thinker today, so nothing is overturned. The 2026-09-09 ruling's two-release migration for a claimed_by stamp does not arise, because no stamp is written on any record (decided without a question: one defensible answer). The research and both reviews are filed as research/notes/2026-10-03-multi-agent-coordination-sota-and-run-lessons.md.

  • dcn-26100200000000252026-10-02

    2026-10-02 — Ruling DR5b-4 of the product thinker (2026-09-30, a security-review addendum relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), on coverage, verbatim: "TREAT ANY REMOTE LIKE PAID — every provider off this computer, keyed or keyless, needs the owner's personal list and gets the fixed file list, the owner's size cap and secret blanking; only on-machine helpers skip." It widens the scope of DR5's default, which itd-2609081951381895 decision 10 limits to a provider that holds a key, to every provider off the machine. Not built at this entry's base (see DR5b-1 above).

  • dcn-26100200000000242026-10-02

    2026-10-02 — Ruling DR5b-3 of the product thinker (2026-09-30, relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), on secrets in an outbound bundle, verbatim: "CHECK AND BLANK OUT — scan, redact to a placeholder, send, and note what was blanked." Not built at this entry's base (see DR5b-1 above).

  • dcn-26100200000000232026-10-02

    2026-10-02 — Ruling DR5b-2 of the product thinker (2026-09-30, relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), on the size of an outbound bundle. The person first gave no option, with the note "again, configurable per repo", then corrected the interviewer's framing of a per-project cap, verbatim: "that's only for abcd, not for other projects; each project owner will have their own external services." Re-asked with the distinction between repository settings shared with contributors and the owner's personal machine settings, the answer: "OWNER'S PERSONAL SETTINGS, PER PROJECT — a default cap plus per-project caps in the machine layer; repository settings ignored for this." Not built at this entry's base (see DR5b-1 above).

  • dcn-26100200000000222026-10-02

    2026-10-02 — Ruling DR5b-1 of the product thinker (2026-09-30, relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), on the files sent with a file-reading agent to a listed paid provider, verbatim: "A FIXED LIST PER HELPER (e.g. reviewer: changed files + the spec)", with the note "will this be configurable per repo?", answered as DR5b-1b, verbatim: "ONLY YOUR PERSONAL SETTINGS may change a helper's list (machine layer widens or narrows); a repository's setting is ignored with a warning." The DR5b-2 answer below was applied to DR5b-1b without asking again: the per-helper lists change only in the owner's personal settings, per project. Not built at this entry's base, where every file-reading agent stays refused on a provider that holds a key (itd-2609081951381895 decision 11); the bundle these rulings shape is planned only through a planning interview still owed.

  • dcn-26100200000000212026-10-02

    2026-10-02 — Ruling DR6d-2b of the product thinker (2026-10-02, relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), on who starts a lane's full check, in the person's words, verbatim: "yes, by default. but we need a new setting to make it the operatoor (TF); this should also be set in abcd;ahoy install interviews -- as some maintainers may prefer the operator by default." Reading, recorded as the interviewer's reading and not as the person's words: the build loop runs the project's full check itself in the lane's worktree by default; a new project setting hands that to the operator (the technical facilitator); the ahoy install and setup interview asks which default the project wants. Nothing is filed or built: its routing awaits the person's decomposition confirm (proposed as a split into a new intent, an amendment to the setup interview, and a trust question answered before any spec).

  • dcn-26100200000000202026-10-02

    2026-10-02 — Ruling DR6d-2 of the product thinker (2026-10-02, relayed by abcd-a2 [75597f] after the person asked for its benefits and drawbacks; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "missing preflight receipt for one lane: CARRY ON, WAIT SHOWN — other lanes continue; the lane waits for its receipt like the merge wait (contend, not refuse), and the status shows 'waiting for its full check (since HH:MM)'." The person's note, "what is the check? Manual? by the PT or by the TF?", was put as DR6d-2b below. Not built at this entry's base, where the loop's push refuses a lane whose head carries no preflight receipt (internal/core/implement/loop/land.go); lane dr6d builds the wait.

  • dcn-26100200000000192026-10-02

    2026-10-02 — Ruling DR6d-1 of the product thinker (2026-10-02, relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "preparing parallel steps' worktrees: ONLY WHEN A HELPER IS FREE — a step's worktree is made just before an agent takes it; at most the agent ceiling's worth on disk." Not built at this entry's base; lane dr6d of autonomous run A builds it in the build loop of spc-2609202134341288.

  • dcn-26100200000000182026-10-02

    2026-10-02 — Ruling OC2 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "SAME RULE, PERSONAL ONLY — only machine-layer routes may hand a role to any runner (claude or opencode); repo routes skipped with a warning." Not built at this entry's base; lane runnerSeal builds it with RN2.

  • dcn-26100200000000172026-10-02

    2026-10-02 — Ruling OC1 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f] after a research pass on the opencode harness; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "SEAL IT, AND TEST IT — runner adds OPENCODE_DISABLE_PROJECT_CONFIG=1, OPENCODE_DISABLE_CLAUDE_CODE=1, OPENCODE_DISABLE_EXTERNAL_SKILLS=1 beside --pure; plus a hostile-fixture test (planted instruction, setting, skill) that fails if any is read." Sources: opencode's published documentation (config, cli, rules, plugins, skills) and its source, read 2026-10-02; the project-config switch is documented only in the source. Not built at this entry's base, where internal/core/runner/opencode.go passes --pure alone; lane runnerSeal builds it.

  • dcn-26100200000000162026-10-02

    2026-10-02 — Ruling RN2 of the technical facilitator, FINAL (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "YES, SEALED, PAID KEY ONLY — runner keeps --bare with an API key; only machine-layer (personal) routes may hand a role to a runner; repo routes skipped with a warning; subscription-only owners run the role in their own session." It supersedes the provisional answer, "TREAT IT LIKE A PAID SERVICE", given with the note "are you sure it cannot run via a subscription? Investigate first.", which stood only until a research pass returned: no flag set short of the bare flag seals project instructions, plugins, skills and agents (code.claude.com/docs/en/cli-reference, read 2026-10-02), and the vendor's terms do not permit third-party developers to route requests through Free, Pro or Max plan credentials on behalf of their users (code.claude.com/docs/en/legal-and-compliance, read 2026-10-02). Not built at this entry's base; lane runnerSeal of autonomous run A builds it with OC1 and OC2.

  • dcn-26100200000000152026-10-02

    2026-10-02 — Ruling CD4 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "repo route to a provider the machine has not configured, displacing the machine route of the same name: OWNER'S SETTING APPLIES — skip the repo route (with a warning) when a machine-layer route for that name exists; adr-25's 'stays on host' sentence amended." Not built at this entry's base, where such a route runs on the host with a diagnostic and displaces the machine's route (internal/core/oracle/config.go); lane routeSkip builds it. It narrows the closing clause of itd-2609081951381895 decision 8, whose settled text stands, with a dated amendment note in that intent's Audit Notes.

  • dcn-26100200000000142026-10-02

    2026-10-02 — Ruling CD3 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "repo route naming a model a configured keyless provider does not offer: SKIP THAT ROUTE, WARN — skip with a diagnostic; the machine's route for the role applies; adr-25 amended." Not built at this entry's base, where such a route refuses the whole configuration (internal/core/oracle/config.go); lane routeSkip of autonomous run A builds the skip and amends adr-25. itd-2609081951381895 carries a dated amendment note citing it.

  • dcn-26100200000000132026-10-02

    2026-10-02 — Ruling PC1 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "pick-commit attribution: A THIRD LABEL NAMING ABCD — e.g. 'Assisted-by: abcd:<version>' for commits abcd composes from record facts; AGENTS.md and the attribution gate amended to accept it." Not built at this entry's base: scripts/check-attribution.sh and AGENTS.md accept no such label yet; lane pickLabel of autonomous run A builds it.

  • dcn-26100200000000122026-10-02

    2026-10-02 — Ruling CY2 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "itd-14<->itd-15 and itd-2609081951381895<->itd-2609170822093401: SAME, DECLARED PAIRS — each direction names the piece it needs." Applied as CY1 above: both edges of each pair stand, and each of the four intents carries a dated Audit Notes line naming its pair and the piece each direction needs; edge_cycle still warns on both pairs until the linter can read a declared pair (iss-2610020836255174). This answers the ruling iss-2609300903551032's remedy waited on.

  • dcn-26100200000000112026-10-02

    2026-10-02 — Ruling CY1 of the technical facilitator (2026-10-02, asked in plain words by the interviewer abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "runner <-> loop mutual builds_on: KEEP BOTH, DECLARED (a declared mutual pair)." The person's note, verbatim: "in future, I think we need an intent to ensure this is checked first, so that the loop -- while acceptable -- is precise about what is needed each way." Applied: itd-2609201916056194 (the command-line runner) and itd-2609201916151817 (the build loop) keep both builds_on edges, and each carries a dated Audit Notes line naming the pair and each direction's piece. The record has no field record-lint's edge_cycle rule reads as a declared pair, so none is invented, edge_cycle still warns on the pair, and the gap is captured as iss-2610020836255174. This answers the ruling iss-2609300848016421's remedy waited on. Not filed: the intent the note asks for, whose routing waits on the person's decomposition confirm.

  • dcn-26100200000000102026-10-02

    2026-10-02 — H4-0 (2026-10-02; recorded by lane rd2) is no new ruling: no question was put, because ruling H3-0 above settles it. The draft itd-2609291923559186 had no record of two adversarial reviews either, so the interviewer abcd-a2 [75597f] ran both reviews before its planning interview, on branch plan/consistency-followups, which is not on the default branch at this entry's base (same local-tier file as the H3-0 entry above).

  • dcn-26100200000000092026-10-02

    2026-10-02 — Ruling H3-0 of the product thinker (2026-09-30, in the planning interview for the draft itd-2609091014076309 run by the run's interviewer abcd-a2 [75597f]; the answers are kept in the local-tier file .abcd/.work.local/scratch/reports/planning-answers-2609-30.md and restated here because that file is not committed; recorded by lane rd2). Put because the draft had no record of the two adversarial reviews the planning-interview prerequisite requires; the answer, verbatim: "REVIEWS FIRST, THEN INTERVIEW (two reviewers one after the other — design/feasibility, then record-discipline — findings applied or rejected in the draft, then the interview on the corrected text)." Applied: both reviews ran and their dispositions were applied before the interview, on branch plan/worktree-store-review, which is not on the default branch at this entry's base (the intent is still in drafts/ here).

  • dcn-26100200000000082026-10-02

    2026-10-02 — Ruling H2 of the person (2026-09-29, same interview and local-tier file as the DR3 entry above; recorded by lane rd2), verbatim: "dependency-update key: a GITHUB APP created and installed on the repo; the landed update's AUTHOR is the person (App pushes; human authorship kept so the attribution gate passes). Creating/installing the App and storing its secret is the person's act (owed)." Built: .github/workflows/dependency-reauthor.yml re-authors an in-bound bump with the owner named in .abcd/config/dependency-reauthor.conf as author and committer and pushes it with the App's token, minted in the shell under ruling CG1 (adr-2609292116133348). Not done: creating and installing the App and storing its two secrets is the person's act and stays owed (iss-2609292030070275).

  • dcn-26100200000000072026-10-02

    2026-10-02 — Ruling CD2 of the person as technical facilitator (2026-09-29, same interview and local-tier file as the DR3 entry above; recorded by lane rd2), verbatim: "repository route to a keyed provider: WARN AND SKIP that route (other commands keep working), not a hard LoadAPI refusal." Built: a repository's route to a provider that holds a key is skipped with a diagnostic and the machine's own route to that name applies in its place (skipKeyedRoute in internal/core/oracle/config.go; a repository's malformed route and malformed route name are skipped under the same ruling); decision 8 of itd-2609081951381895 and adr-2609221009491186 carry it.

  • dcn-26100200000000062026-10-02

    2026-10-02 — Ruling CD1 of the person as technical facilitator (2026-09-29, same interview and local-tier file as the DR3 entry above; recorded by lane rd2), verbatim: "repo-row settings on a person-typed keyed route: LEAVE AS IS (they merge, within the provider's accepted set)." Nothing is built for it: a --route the person types to a provider that holds a key merges the repository row's settings within the provider's accepted set, as internal/core/oracle/resolve.go already did, and that code cites the ruling.

  • dcn-26100200000000052026-10-02

    2026-10-02 — Ruling CC1 of the person as technical facilitator (2026-09-29, same interview and local-tier file as the DR3 entry above; recorded by lane rd2), verbatim: "board 'next up' vs peers: DO THE CHECK (the board pays the peers read so 'next up' always equals the pick)." Built: the status block's head takes the peers check build next runs (loop.StatusPeers in internal/core/implement/loop/loop.go, internal/core/statusblock), read once and only when a head is in reach, so the head is always the intent the pick would choose; the brief's surface chapter 04-surfaces/08-abcd.md states it. The record-only half of the same finding is iss-2609291803334904.

  • dcn-26100200000000042026-10-02

    2026-10-02 — Ruling CB1 of the person as technical facilitator (2026-09-29, same interview and local-tier file as the DR3 entry above; recorded by lane rd2), verbatim: "transcript store owned by another uid: REFUSE EVERYTHING (reads included), as now; NOTE: the refusal wording should name the foreign owner, not use write wording." Built: every history verb, reads included, still refuses a records leaf another account owns, and the refusal names the owning uid (and the account name where it resolves) with no write wording on a read verb (internal/core/history/location.go; iss-2609291731336469, resolved by commit 3674db3a4).

  • dcn-26100200000000032026-10-02

    2026-10-02 — Ruling DR3 of the person (2026-09-29, in the human-step interview run for autonomous run A by its interviewer abcd-23 [b1e81b]; recorded by lane rd2, records only). The answers of that interview are kept in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md and are restated here because that file is not committed. DR3, verbatim: "itd-60 docs-fidelity verdict: FOUND AUTOMATICALLY by spec close and launch ship (a saved verdict labelled with the reviewed code's fingerprint; match -> proceed; none/stale -> refuse 'run the docs review first'), like the preflight receipt." Built: itd-60 shipped with it; a spec close that ships an intent, and launch ship for every intent shipped since the last tag, find the docs review saved for HEAD through internal/core/docfidelity and refuse until abcd docs fidelity record has saved one (internal/core/lint/gatereceipt.go).

  • dcn-26100200000000022026-10-02

    2026-10-02 — The consistency pass follow-ups are planned as one intent (itd-2609291923559186, spc-2610021456200324, impact additive) after two adversarial reviews and a planning interview with the product thinker and technical facilitator, asked one at a time. Rulings: A3 stays in this intent, though iss-2609260926323349's body had routed it to the shipped itd-34; A4 stays and builds its own overflow signal; the pre-commit gate runs the rule checks on every commit and the model pass only where the owner's personal settings provide a route, marking it owed otherwise, and never refuses a commit on a judgement it could not obtain; what the gate does on a finding (warn, stop, or automatic: fix the obvious and file the rest) is asked at setup; the rule checks cover the whole corpus and the model pass covers the staged records and their links; the gate waits for the core-owned managed pre-commit gates (iss-84 with itd-62, ruling J23); G1 lands first; the new A1 codes are warnings, and the 136 one-way builds_on edges that exist when the rule lands are baselined, so only new ones are flagged. The 10 acceptance criteria are the product thinker's. Grounds: "pursued: contradictions get into the records unnoticed and are answered twice, and unattended runs write records with no one checking them for contradictions; wrong if, after it ships, the same contradiction is still filed twice, a rule-catchable one still gets in, or an unattended run still lands a contradiction the check covers."

  • dcn-26100200000000012026-10-02

    2026-10-02 — itd-2609301918174237 (a provider off this machine takes a file-reading agent only as a fixed, blanked, capped bundle) is filed as a draft pending its interview, under the product thinker's ruling DR5c-0 of 2026-10-02, as relayed by the orchestrator of autonomous run A: "BACK TO DRAFT, INTERVIEW LATER — moved back to drafts/, queued for two reviews + a full planning interview; nothing built from it meanwhile". Lane dr5bSpec of autonomous run A had written it as planned with a spec, without a planning interview; that spec was not filed (a parked copy stays in the local tier for the interview), the intent carries no kind, spec link, impact or scope-condition identities until the interview sets them, and nothing is built from it. Its Decisions section keeps the rulings DR5b-1 to DR5b-4 of 2026-09-30 verbatim and the lane's facilitator choices (its Decisions 5 to 9) as written, the latter open to the interview; DR5c-1 to DR5c-3 were not asked and fold into that interview (filed by lane dr5cRecords).

2026-09177

  • dcn-26093000000000282026-09-30

    2026-09-30 — Release v0.12.0 is cut by autonomous run A, and the run's agenda line is: approve the publish step. Under ruling A2 of the product thinker's run A interview (2026-09-23 07:52Z: the run approves the release environment itself once every gate is green) and the product thinker's releases ruling of 2026-09-25T08:04:52Z ("cut additional releases if that makes sense, but bundle multiple intents for it"), the run approves the release environment's deployment of v0.12.0 only after the merge queue, the verify job and every other gate on the tagged commit report green, and stops with a handover instead if any does not. The cut: v0.12.0, impact breaking (three breaking records, iss-2609251324599468, iss-2609291313276243 and iss-2609292359485570, and five removed command spellings the release guard found and the records declare), 281 records since v0.11.1: eleven shipped intents, all additive, and 270 resolved or declined issues (171 fixes, nineteen additive, three breaking, 77 internal and outside the changelog); the release guard passed, and the findings guard passed with the one major carried past v0.11.1 on its recorded deferral (iss-2609281134544802). Content commit fecdbed5, on top of 4b8ff2afa, e8d5d006, 4d634c4f and c8ddb042, which the gates' findings required. Both semantic gates ran at tier full over the first roll b89784c4, which differs from the content commit only by those four commits and the re-cut CHANGELOG. The docs-currency-reviewer (Fable 5.1) found 24, four major (a schema version the CHANGELOG and the upgrade guide gave as 4 where the binary writes 8, a build page's key shape, and a timeout the CHANGELOG gave to three hook entries where only UserPromptSubmit declares it), all four fixed; eleven in all are fixed in 4b8ff2afa and the re-cut CHANGELOG, and the thirteen remaining minors and nitpicks are captured as one documentation record (iss-2609302306281487). The brief-surface cross-check (45 pinned checkers, Opus 5.5, at most eight alive) found 129, all valid at b89784c4 on an independent classification (Fable 5.1): 39 cycle, 87 standing, three user-facing and four behaviour. The three user-facing findings are fixed in 4b8ff2afa, and every finding on the guard chapter 17-guard.md in e8d5d006, 4d634c4f and c8ddb042, after three docs-review holds; the docs review of c8ddb042 is PROMOTE. One brief sentence (17-guard.md:426) was applied from the reviewer's draft and is flagged for the product thinker's review in .abcd/work/brief-review-flags.json. Captured as four records, all minor and all to be fixed in the first lane after the tag: a capture refusal that leaves .iss-alloc.lock behind (iss-2609302305500526, x-025), the appendix generator labelling /abcd:version host-delegated (iss-2609302306003610, x-039 and x-118), the guard's trailing-dot fold that its comment promises and rm -rf ../. does not make (iss-2609302306019245), and docs fidelity record and --apply disagreeing on a verdict's chapter shape (iss-2609302306153318). The behaviour finding x-001 is not a defect: bare ahoy remote listing its sub-verbs and exiting 0 is the stated behaviour of v0.12.0's breaking change, so the stale side is the shipped intent's criterion; it and the rest of the design-record drift go to the systematic brief pass iss-2609091956001547. Integration branch 24d, reviewed and ready, holds until the tag and falls into the next release.

  • dcn-26093000000000272026-09-30

    2026-09-30 — An after-merge fidelity audit that fails or comes back undecided leaves the intent shipped and flagged, and the ingest captures one issue carrying the owed check (ruling DQ1c of the product thinker, 2026-09-30, relayed by the orchestrator of autonomous run A; applied by lane dq1cFlag). DQ1c, verbatim: "(a) STAYS SHIPPED, FLAGGED: the intent stays in shipped/, its changelog entry stands, and a 'check still owed' flag names the unmet/undecided criteria until it is fixed and re-checked." The product thinker's note, verbatim: "can it auto-capture an issue with the remaining check? Either fix it or check again etc.?" It defines what "reopen" means for a shipped intent under DQ1a ("an UNDECIDED audit REOPENS the work") and DQ1b ("until the loop is ready it stays after the merge (reopen on undecided/fail)"): nothing un-ships. As built: a verdict judging any criterion NOT_MET or INCONCLUSIVE writes an audit-owed flag in its Audit Notes block naming each such criterion, the receipt, the remedy ("fix, then re-run the audit" when a criterion failed, "re-run the audit" when every owed one is undecided) and the issue carrying it; that issue is captured through capture.Capture, the one filer, as a major bug for a failure and a minor inconsistency for an undecided verdict (both in the drain's fixable set, so the drain's field rules decide as for any issue; the remedy is real, so H12's automatic-filer value does not apply), related to the intent, with the filing-time match, and a later failed or undecided audit of the same receipt links to it while it is open. A re-emit of a flagged receipt rewrites its request (check_owed); a re-run judging no criterion NOT_MET or INCONCLUSIVE replaces the block without the flag, leaves a dated clearance line below it, and resolves the issue with impact fix. This supersedes itd-165's draft reading that an inconclusive verdict creates no record: DQ1c is the later ruling and names the undecided case.

  • dcn-26093000000000262026-09-30

    2026-09-30 — The implement loop's state file is schema version 9 where a run works in parallel (ruling DR6, spc-2609202134341288), not the version 8 that spec's amendment names: the runner's record (itd-2609201916056194) reached the default branch first, on the v0.12.0 cut, and took version 8, so the two are numbered in the order they landed (integration integ24d of autonomous run A, internal/core/implement/loop/state.go). A version 7 or 8 file migrates its lane's one awaiting into awaits and is written back at version 9; a version 7 or 8 file carrying what only version 9 writes, and a version-9 file carrying awaiting, are refused naming the version and the key. The closed spec keeps its text; brief 34-build.md names the three versions.

  • dcn-26093000000000252026-09-30

    2026-09-30 — The implement loop arms auto-merge only where the repository's ruleset requires a person's approval, and otherwise leaves the pull request open for a person to merge (the product thinker's ruling AM1 of 2026-09-30, applied by lane amApproval of autonomous run A). AM1, verbatim: "(a) ONLY WHERE APPROVAL IS REQUIRED: abcd arms auto-merge (land.go:703) only when the project's hosting service requires a person's approval; in a project without that rule it leaves the change open for a person to merge. This project unchanged." As built: the arm step reads the same ruleset mirror at the lane's base that names the merge queue, and counts approval as required when an active ruleset on the default branch carries a pull_request rule whose required_approving_review_count is one or more, or whose require_code_owner_review is set while a CODEOWNERS file at the base (.github/, the root or docs/) names at least one owner; this repository's own mirror (a code-owner review with an approving count of 0 beside .github/CODEOWNERS) is that second shape, so it still arms. A code-owner rule with no CODEOWNERS owner asks no person for anything and does not count. A missing mirror requires nothing, so the pull request is left open; a mirror file that cannot be read or parsed stays a refusal, which arms nothing either. Where a queue exists but nothing requires approval, the landing records "left open for a person to merge: the ruleset requires no approval" in its state, the run record and implement status, and no later step arms it.

  • dcn-26093000000000242026-09-30

    2026-09-30 — Narrowing the administrator-group exception in the entry above (lane fix-runnerAdmin of autonomous run A, internal/core/runner/proc.go adminGroupWritableOnly): a command-line runner admits a harness binary, or a directory it is reached through, that is group-writable (never other-writable) only on darwin and only when the group is gid 80 admin; gid 0 is refused on every OS, and gid 80 is refused off darwin. Reason: the entry above granted gid 0 on the premise that members of the administrator group can already act as root, which holds for darwin's admin group (its members may sudo by default) but not for Linux's gid 0 root group nor darwin's gid 0 wheel, whose membership does not by itself let someone act as root (the runner2Land review note). The Homebrew /opt/homebrew/bin case the exception exists for is group admin, so it stays admitted.

  • dcn-26093000000000232026-09-30

    2026-09-30 — A command-line runner admits a harness reached through a directory, or a binary, that is group-writable only when the group is the system administrator group (gid 0 anywhere, gid 80 admin on darwin) and other cannot write it; other-writable stays refused whatever the group, and every other group stays refused (lane runner2Land of autonomous run A, internal/core/runner/proc.go adminGroupWritableOnly). Reason: the runner2 re-verification (reverify-runner2) found that on a Homebrew Mac /opt/homebrew/bin is drwxrwsr-x group admin, so a harness installed there was refused with the chmod go-w message; members of the administrator group can already act as root, so that write grants them nothing new, and asking a person to strip Homebrew's own directory mode would break Homebrew.

  • dcn-26093000000000222026-09-30

    2026-09-30 — The worktree store is planned (itd-2609091014076309, spc-2609301811532881), after two adversarial reviews and a planning interview with the product thinker and technical facilitator, asked one at a time. Decomposition: file as is, with no new ADR or principle; the build loop's lane primitive moves into the store's package, so the intent refines itd-2609201916151817. Rulings: the verb is abcd ahoy worktree add|list|prune; "merged" is the forge's recorded pull-request state or patch-equivalence, and it works with no forge; an unmerged worktree quiet for 14 days (repo-configurable) is surfaced with a dossier and removed only when named (--yes <name>), never forced; a reclaimed worktree's local tier is moved, never deleted, into a new sibling store ~/.abcd/notes/<root-sha>/<timestamp>-<name>/, redacted on write with a manifest; the plugin page carries add as a host-run step; the worktree directory is 0o700; prune exits 0 when it reclaimed something, 1 when it reclaimed nothing, 2 on a refusal; a directory keyed on an abbreviated root commit is listed as "not a lane" and names the full-key lane; the board line keeps "can be cleared" as an estimate. The 21 acceptance criteria are the product thinker's. Grounds: "pursued: working copies keep piling up with nothing to list or clear them; wrong if, after it ships, copies still accumulate outside the store." Carried from itd-148's 2026-08-26 interview and confirmed here: the merge proof and the quiet sweep. Also ruled: itd-148 keeps its mint-visibility criterion as peer awareness (its Decision 5).

  • dcn-26093000000000212026-09-30

    2026-09-30 — An older site interface-string file keeps building: abcd site setup and abcd site build add to site-src/ui.json each label the allowlist declares and the file does not carry, with abcd's default words, name each on stderr, and change nothing else in it (the product thinker's ruling TG1 of 2026-09-30, relayed verbatim: "(b) ABCD ADDS THE MISSING LABELS: on the next site setup or site build, abcd adds only the missing required labels (with the default words); the project's own wording elsewhere in ui.json is never changed. No failure, no manual step; both intents stay impact: additive."). It is the one exception to "a file the repository owns once it exists is kept", recorded as adr-2609301720596683, which refines adr-47 and leaves decision 2's closed allowlist untouched: a blank declared label and an unknown key are still refused, and the site gate's own render never completes the file. itd-2609212103568351 and itd-2609212103572513 keep impact: additive (lane tgLabels of autonomous run A).

  • dcn-26093000000000202026-09-30

    2026-09-30 — Rulings DR6b and DR6c (the product thinker, 2026-09-30, relayed by the orchestrator of autonomous run A) close the two questions the DR6 spec review left open in spc-2609202134341288 and are recorded as decision 8 of itd-2609201925079472 (lane dr6Spec, amend round 3; records only, nothing built). DR6b, verbatim: "(a) ONE AFTER ANOTHER BY DEFAULT: a step runs alongside earlier ones only if its plan says so; nothing already planned changes; reviews run side by side; the 2026-09-21 wording stands." A step without a - needs: line needs every earlier step, so itd-2609212103565953's wording of 2026-09-21 stands. DR6c, verbatim: "(c) FINISH, BUT HOLD THEM: when one piece is handed back, pieces in flight finish but nothing merges until the person re-plans; the person then decides whether the held pieces land as they are." After a hand-back the sibling lanes run to completion and each passing one takes the lane stage held (before its push, or before arming once pushed; an armed one is disarmed), recorded in lanes[].hold and shown by implement status; the person releases or discards each with implement step --release <lane> or --discard <lane> (the claim verb implement release is a different noun and is not reused). Tested by the spec's criterion C13.

  • dcn-26093000000000192026-09-30

    2026-09-30 — Six entries above appear twice, verbatim: the five dated 2026-09-29 from "Two itd-111 follow-ups from its fidelity audit" to "Ruling J13", and the 2026-09-30 entry beginning "The 2026-09-29 itd111Follow entry above". Two histories carried them in opposite order relative to the 2026-09-30 BU1/BT1 entry (main below them, the implement-loop lanes above them), so joining them in integration 24b-3 kept main's order and repeated the six after BU1 in the lanes' order, the one merge result the append-only gate admits (every parent's lines kept in their order, DA002; no line beyond what the merge base held plus what each side added, DA003). Each pair is one decision recorded once: the first copy is the record, and the second repeats it (recorded by the integration lane of autonomous run A).

  • dcn-26093000000000182026-09-30

    2026-09-30 — Correcting three points of the entry above after its review (lane fix-drainOwnRule of autonomous run A). The drain-rule offer of ahoy install is asked only of a person at a terminal, the itd-131 precedent the git identity question set, rather than behind a named opt-in flag: off a terminal neither its category question nor the offer is asked, so a piped answer stream keeps the order it had before the offer existed and a scripted yes never writes the record, and the run reports drain_rule.offered under optional_skipped naming the terminal as the way to be asked. The terminal gate was chosen over a --drain-rule flag because the record decides what an unattended agent may do, which a scripted answer is not a person's yes to, and a flag would hide the offer from the person at a terminal it is for. A checkout holding no release tag (a shallow clone fetches none) marks the anchor unknown rather than reading every deferral as lapsed: every record carrying a deferral is handed back as deferred, naming the missing tags and git fetch --tags, which keeps the rest of the dry run readable where refusing the whole plan would not. The rule's reader refuses, as malformed, a record that states any frontmatter key twice (not only a drain_ key) and one whose frontmatter id disagrees with its file name, and reads each record through the capped trust-boundary reader, so a record that is a symlink or past the size cap refuses; every refusal of the rule exits 2 on the dry run as on the bare verb.

  • dcn-26093000000000172026-09-30

    2026-09-30 — The drain reads the drained repository's own eligibility record, which may loosen abcd's floors loudly, and it hands back every record still waiting on a person (the product thinker's rulings BX2 and H11 of 2026-09-29, applied by lane drainOwnRule of autonomous run A; partial of itd-82, whose spec stays open for the host judgement, the lane, the hand-back writes and the pace). BX2, verbatim: "the PROJECT MUST HOLD the eligibility decision in its own record (e.g. added at setup); drain refuses there until it does." H11, verbatim: "MAY LOOSEN abcd's floors (a project may let drain take major/critical and security issues). NOTE for the lane: make a loosened floor loud (drain --dry-run and the drain start name every floor the project loosened), and keep abcd's own repository at the stricter default." As built: the record is the one accepted decision record in the repository's .abcd/development/decisions/adrs/ whose frontmatter carries drain_categories (an inline list, a subset of the fixable set), drain_severities (an inline list of severities), drain_security (handback or take) and drain_remedy (required, its only value, since the remedy is the brief a lane works from); abcd's own adr-2609291342092738 carries the strict baseline, which the binary also bundles as the measure a loosening is named against, and a test fails if abcd's record loosens anything. A repository without such a record, with one that is only proposed or superseded, with two accepted, or with one that misses, misspells, repeats or mis-values a field, is refused by drain --dry-run and bare drain alike, exit 2 and nothing written, never falling back to the baseline or a looser rule; widening the categories past the fixable set is refused as a decision by kind, which H11 does not name. Every loosened floor (severity major, severity critical, security) is named in the dry run's text, on stderr in both output modes, in --json as loosened, and in the start's refusal. ahoy install offers the baseline as an accepted record, written through the decision store's mint only on an answered yes; --yes skips it and reports drain_rule.offered under optional_skipped, as the routing offers are. The gap the remedy lanes found (50 of 54 dry-run-eligible records waiting on a ruling) is closed by BOTH hand-backs, each its own rule: a remedy opening "Waits on" (compared case-folded) is handed back as waits-on-ruling, because taking it would make the ruling the remedy waits on; and a record whose deferred_after names the current anchor tag is handed back as deferred, because a person carried it past this release and the waiver is that person's decision for the cycle. Both hold whatever the repository's record says. capture defer writes a deferral only onto a major or critical record, which H11 now lets a record take, but this ledger also carries hand-written deferrals on minor records (62 of the 231 open records on this branch are handed back as deferred), and the rule holds them back the same way. They are asked after the category and severity hand-backs, whose fix a ruling or a lapse would not change, and the ruling before the deferral, because it names which decision is owed; a record carrying both waits on both. The release tags are read only when an open record carries a deferral, and a failure to read them refuses the plan rather than letting a live deferral through. The threat is stated in the drain brief chapter: the record is a repository-authored file deciding what an unattended agent may do, so a contributor's pull request can loosen it; what guards it is that the record is committed history reviewed like code, a loosening is loud on every run, abcd's own repository keeps the baseline under a test, and the store is read inside the checkout so a symlink leaving it is refused.

  • dcn-26093000000000162026-09-30

    2026-09-30 — Pending the person's ruling CL1, a promoted inbox report files the machine value: outside text never becomes a drain-eligible remedy without a person naming it (fix round of lane remedyRequired, autonomous run A, closing the review's trust finding on the entry of 2026-09-29 above). As built: inbox promote always writes remedy: none (filed automatically) (issueschema.MachineRemedy), whatever the report proposes, so abcd drain --dry-run lists the issue as ineligible; the sender's proposal stays in the issue's text under "Remedy the reporter proposes:", scrubbed like every other value the report carries, for a person to adopt with capture remedy. This narrows the entry above, which filed a report's own remedy as the issue's; the ruling CL1 may widen it again.

  • dcn-26093000000000152026-09-30

    2026-09-30 — Building the 2026-09-25 ruling on iss-2608291814575788 (lane gitleaksAug of autonomous run A) took four calls the ruling left open. (1) Only the not-installed binary is the recorded gap: the scanner declares scanner.ErrAugmenterNotFound, which gitleaks.ErrConfiguredNotFound matches, and every other state the augmenter reports — a refused configured path, a broken gitleaks.json, a run that fails, a report the scanner cannot place at its line and column, or more than 10,000 findings from one scan — degrades the scanner, so every consumer treats it as it treats a broken pii.json. The ruled Scan(text, file) []Finding has no error, so a failed run is reported through the next Available(), which the scanner asks after every scan; a write path therefore consults Unavailable() after scanning as well as before. (2) The two outward-bound consumers the ruling does not name fail closed on the gap as launch does: disembark pack refuses (a lifeboat leaves the repository as a release does), and the privacy lint reports it as an error finding citing .abcd/config/gitleaks.json. (3) The augmenter's output is untrusted: the scanner keeps only a finding whose bytes sit where it says, forces hard_fail, namespaces a kind that would choose a native redaction (an identity, network or PEM kind, or any un-namespaced one) under augmented:, drops its snippet and suggestion for its own, and sanitises and caps an error it prints; the gitleaks runner runs in gitutil.IsolatedEnv and discards the binary's own output. (4) A write path verifies what the augmenter found by its bytes (scanner.UnsealedAugmented) beside a native-only re-scan (ScanTextNative), never by re-running gitleaks over redacted text; history migrate builds its scanner without the augmenter, as its redaction of lineage scalars never ran gitleaks.

  • dcn-26093000000000142026-09-30

    2026-09-30 — Correcting one name in the entry above that applies rulings CJ1 and CJ1b (lane installerMeta2, autonomous run A; Refs: iss-2609291942520919): the session start's single write is not cache/update-shown but cache/update-shown-<new>, one claim per release, named for the new tag and written beside the cache's binary-meta; in the degraded per-root mode it is .update-shown-<new> beside the plugin root's own .binary-meta (updateShownPrefix in internal/core/ahoy/unseen_update.go, as the fix round of that lane built it). The ruling and the rest of the entry stand.

  • dcn-26093000000000132026-09-30

    2026-09-30 — Correcting three points of the entry above after its review (lane fix-drainOwnRule of autonomous run A). The drain-rule offer of ahoy install is asked only of a person at a terminal, the itd-131 precedent the git identity question set, rather than behind a named opt-in flag: off a terminal neither its category question nor the offer is asked, so a piped answer stream keeps the order it had before the offer existed and a scripted yes never writes the record, and the run reports drain_rule.offered under optional_skipped naming the terminal as the way to be asked. The terminal gate was chosen over a --drain-rule flag because the record decides what an unattended agent may do, which a scripted answer is not a person's yes to, and a flag would hide the offer from the person at a terminal it is for. A checkout holding no release tag (a shallow clone fetches none) marks the anchor unknown rather than reading every deferral as lapsed: every record carrying a deferral is handed back as deferred, naming the missing tags and git fetch --tags, which keeps the rest of the dry run readable where refusing the whole plan would not. The rule's reader refuses, as malformed, a record that states any frontmatter key twice (not only a drain_ key) and one whose frontmatter id disagrees with its file name, and reads each record through the capped trust-boundary reader, so a record that is a symlink or past the size cap refuses; every refusal of the rule exits 2 on the dry run as on the bare verb.

  • dcn-26093000000000122026-09-30

    2026-09-30 — The drain reads the drained repository's own eligibility record, which may loosen abcd's floors loudly, and it hands back every record still waiting on a person (the product thinker's rulings BX2 and H11 of 2026-09-29, applied by lane drainOwnRule of autonomous run A; partial of itd-82, whose spec stays open for the host judgement, the lane, the hand-back writes and the pace). BX2, verbatim: "the PROJECT MUST HOLD the eligibility decision in its own record (e.g. added at setup); drain refuses there until it does." H11, verbatim: "MAY LOOSEN abcd's floors (a project may let drain take major/critical and security issues). NOTE for the lane: make a loosened floor loud (drain --dry-run and the drain start name every floor the project loosened), and keep abcd's own repository at the stricter default." As built: the record is the one accepted decision record in the repository's .abcd/development/decisions/adrs/ whose frontmatter carries drain_categories (an inline list, a subset of the fixable set), drain_severities (an inline list of severities), drain_security (handback or take) and drain_remedy (required, its only value, since the remedy is the brief a lane works from); abcd's own adr-2609291342092738 carries the strict baseline, which the binary also bundles as the measure a loosening is named against, and a test fails if abcd's record loosens anything. A repository without such a record, with one that is only proposed or superseded, with two accepted, or with one that misses, misspells, repeats or mis-values a field, is refused by drain --dry-run and bare drain alike, exit 2 and nothing written, never falling back to the baseline or a looser rule; widening the categories past the fixable set is refused as a decision by kind, which H11 does not name. Every loosened floor (severity major, severity critical, security) is named in the dry run's text, on stderr in both output modes, in --json as loosened, and in the start's refusal. ahoy install offers the baseline as an accepted record, written through the decision store's mint only on an answered yes; --yes skips it and reports drain_rule.offered under optional_skipped, as the routing offers are. The gap the remedy lanes found (50 of 54 dry-run-eligible records waiting on a ruling) is closed by BOTH hand-backs, each its own rule: a remedy opening "Waits on" (compared case-folded) is handed back as waits-on-ruling, because taking it would make the ruling the remedy waits on; and a record whose deferred_after names the current anchor tag is handed back as deferred, because a person carried it past this release and the waiver is that person's decision for the cycle. Both hold whatever the repository's record says. capture defer writes a deferral only onto a major or critical record, which H11 now lets a record take, but this ledger also carries hand-written deferrals on minor records (62 of the 231 open records on this branch are handed back as deferred), and the rule holds them back the same way. They are asked after the category and severity hand-backs, whose fix a ruling or a lapse would not change, and the ruling before the deferral, because it names which decision is owed; a record carrying both waits on both. The release tags are read only when an open record carries a deferral, and a failure to read them refuses the plan rather than letting a live deferral through. The threat is stated in the drain brief chapter: the record is a repository-authored file deciding what an unattended agent may do, so a contributor's pull request can loosen it; what guards it is that the record is committed history reviewed like code, a loosening is loud on every run, abcd's own repository keeps the baseline under a test, and the store is read inside the checkout so a symlink leaving it is refused.

  • dcn-26093000000000112026-09-30

    2026-09-30 — Rulings CJ1 and CJ1b of the product thinker (2026-09-29), applied (lane installerMeta2, autonomous run A; Refs: iss-2609291942520919): an update of the abcd binary is announced once, by whatever swapped it, when the swap completes. CJ1, verbatim: "the INSTALLER (bootstrap.sh) writes the previous release tag into binary-meta when it swaps a binary; the session hook stays read-only. Follow-up: it REPLACES the setup_version comparison." CJ1b, verbatim: "ONCE ONLY. Preferred mechanism (the person's note): couple the notice to the install/update process itself — the installer shows 'updated from X to Y' when it concludes, so it is naturally linked to the installation and the session check need neither show it nor write anything. Only IF that is not possible (e.g. the swap happens where no one sees its output), the session check may write one small 'shown' marker as a single exception to its read-only rule." As built: hooks/bootstrap.sh records previous_tag in the binary-meta it writes at a cache or per-root swap and opens its success notice with abcd updated from X to Y (update.UpdatedFormat, the one wording, which abcd update also opens its receipt with); the session-start setup_version comparison (ahoy.VersionTransition) is removed, and ahoy's own version.upgrade gap stays. The exception applies: the bootstrap salvage in the UserPromptSubmit, PreToolUse and PreCompact hooks discards its output (hooks/hooks.json), so those runs pass --unseen, record transition_unseen=yes, and the next session start shows the line once and writes cache/update-shown in the plugin data directory, its single write. itd-111 criterion 6 is amended to match.

  • dcn-26093000000000102026-09-30

    2026-09-30 — A reading finding is matched against the record when it is stored, and itd-180's ruling that recurrence matching is warm work is reversed (the person's ruling DQ2b of 2026-09-30, recorded as adr-2609300821558671, which carries the typed reverses link to itd-180; applied by lane filingReading of autonomous run A; Refs: iss-2609281911024185). DQ2b, verbatim: "reading findings and repeats: ALL THREE — (a) store a 'same as / builds on' link on the stored reading finding (this REVERSES itd-180's ruling that spotting a recurrence is the researcher's warm work, never a mechanical join; record it as a typed 'reverses' decision against itd-180), (b) at storing time also SHOW the likely repeats, and (c) check again at the promote step." As built: a reading record may carry duplicates: and refines: naming an iss-N, itd-N or rdi-N; reading ingest runs capture's one filing-time match on each finding's pattern and body (never the envelope), against the open and resolved issues, the intents and every earlier reading item, never against another item of the same ingest, writes the links and prints the match (and carries it as matches in --json); capture promote <rdi-N> matches the draft it mints on the item's finding and links it as a capture is linked. Earlier reading items are candidates on this route only, because a recurrence is a finding a later reading returns again; a capture's candidate set is unchanged.

  • dcn-26093000000000092026-09-30

    2026-09-30 — The person answered eighteen rulings of autonomous run A on 2026-09-30 (CF1, CF2, CG1, CI1, CI2, CJ1, CK1, CL1, CM1, DR1, DR2, DR4, DR5, DR6, DQ1a, DQ1b, DQ2, DQ3), relayed by the run's interviewer abcd-23 [b1e81b] and recorded by lane recRulingsDR for orchestrator abcd-8d [5bfdfb]. The answers are kept in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md, lines 13 to 30, and are restated here because that file is not committed. SETTLED BLOCKERS: a blocker replaced by an accepted ADR counts as settled, so the waiting intent may start (CF1); a blocker reclassified as a discipline counts as settled too (CF2). Neither is built at this entry's base: the blocked pre-start check still refuses both shapes, and iss-2609300751191426 carries the change. AS BUILT: the App token for the dependency re-authoring workflow is minted in the shell, an openssl-signed JWT exchanged with curl and revoked on exit, with no new action (CG1); when the prompt router cannot evaluate a prompt, its envelope carries the error and leaves the active-domain list out, so the client keeps what it had (CI1); a domain that returns to the active set is re-injected on every host, one that appends to a transcript included, not only on a client that snapshots (CI2); abcd update shows progress only when stderr is a terminal, and saved output stays clean (DR4). BUILD: the installer (hooks/bootstrap.sh) writes the previous release tag into binary-meta when it swaps a binary, the session hook stays read-only, and that tag replaces the setup_version comparison of the itd-111 update notice (CJ1); the SHELL domain also teaches a repository's own guard entries, generated the same way as the bundled registry's (CK1); step in abcd implement check is renamed stage too, in the same breaking v0.12.0 (CM1); the fix rounds a run spends before it hands a lane back are a per-run setting beside --pace, for example --fix-rounds, default 3 (DR1); the dependency-bump intent itd-2609221842494980 ships now, with the first live bump recorded as owed until the person has created the App and its secrets (DR2); only a self-contained agent is sent to a paid provider by default, so the cold-reading positions may go while a file-reading agent such as the intent auditor is refused with the reason, and a central override, a machine-level settings list the person keeps that no agent or repository can change, may name providers that take bundled-context requests for file-reading agents (DR5); a run works in parallel, building several pieces and running reviewers at once up to its agent limit, which is new build-loop work that makes the pacing intent's criterion 6 testable (DR6); an undecided fidelity audit reopens the work, sending the feature back to a lane, and never closes like a pass (DQ1a, iss-2608290820473197); the audit moves before the merge, as part of the build loop's last lane (per ruling AI), and until that loop is ready it stays after the merge and reopens on an undecided or failed verdict (DQ1b, iss-2608290822140563); the filing-time duplicate check covers every route, the promoted inbox report, the consistency pass and the reading ingest, in a lane after remedyRequired (DQ2, iss-2609281911024185); abcd ahoy offers to install gh on an explicit yes (DQ3, iss-2609281911024838). KEEP: a promoted inbox report's own remedy is kept but not usable: the sender's suggestion stays in the issue's text for reference, the remedy field is none (filed automatically), and a drain skips the record until a person writes the fix, so the conservative default recorded above on 2026-09-30 stands and is not widened (CL1). The person added to CL1 that when a person comes to write the real fix for such an issue, the agent offers a state-of-the-art research pass first (principle prefer-sota), which commands/capture.md says under the capture remedy verb. The three rulings of 2026-09-29 owed to this ledger by earlier sessions of the run, the ceilings of five and of eight sub-agents and the remedies ruling, already have their entries above, so this entry adds none.

  • dcn-26093000000000082026-09-30

    2026-09-30 — Ruling CK1 of the product thinker (2026-09-29), applied (lane teachRepoGuard, autonomous run A; Refs: iss-2609300756163382): the SHELL domain teaches a repository's own guard entries, generated the same way as the bundled registry (the ruling, verbatim: "YES, generated the same way as the bundled registry"). This replaces the consequence the entry for ruling J10 above recorded, that the domain is built from the bundled registry only. Every rules load rebuilds SHELL, before any rules.json layer lands on it, from the registry abcd guard enforces in the repository (guard.LoadRepo: the bundled entries merged with .abcd/guard.json), through the same generator. Taken by the lane rather than the ruling: a lesson whose words are the repository's (an entry the file adds, or a bundled entry whose tier, pattern, why or successor it changes) carries (repo) after its entry id, so provenance stays visible while the domain itself stays bundled to every other contract; a guard file the guard refuses is refused here too, SHELL teaching the registry the guard falls back to and a load note naming the file and the reason on stderr from abcd rules and the hook, rather than failing the whole rule set (which would silence PII and COMMITTING over one broken guard file); the guard file's disabled switch does not silence the teaching, which keeps its own switches in rules.json (spc-16, "Config home").

  • dcn-26093000000000072026-09-30

    2026-09-30 — The person's ruling CM1 of 2026-09-29 ("'step' in implement check: RENAME it to 'stage' too, in the same breaking v0.12.0"; kept verbatim in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md and restated here because that file is not committed) is applied by autonomous run A's integration lane integ24b1, answering iss-2609292359485570: implement check calls what a session asks about a stage, so its verdict's JSON field and its refusal line's field are stage (were step), its text says may take the <stage> stage, an operand outside lane, release, review, audit and land is refused as an unknown stage, and its help, sentence, command page and brief chapter say stage. The operands keep their spellings. The upgrade guide docs/how-to/upgrade-to-v0.12.0.md lists both renamed fields. The 'point' spelling the capture's remedy offered was not chosen: CM1 names 'stage'.

  • dcn-26093000000000062026-09-30

    2026-09-30 — The technical facilitator's ruling H9 of 2026-09-29 is applied (recorded by lane denyRetire of autonomous run A; the answer is kept verbatim in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md, dated 2026-09-29, and restated here because that file is not committed): the bundled anthropic/* vendor denylist is retired and a provider's allowlist alone decides which models it serves. adr-2609300107513982 supersedes adr-2609221009491186, revising its decision 2 and carrying decisions 1, 3, 4 and 5 forward word for word; itd-2609081951381895's criterion 3 and spc-2609221011153746 are amended to the allowlist-alone reading, with the old wording in the intent's Audit Notes (iss-2609300110451242). This answers the follow-up the 2026-09-29 entry above left to the technical facilitator under AA(a), whether the bundled entry stays as a backstop: it does not. Ruling Y (added 2026-09-26, from lane apiadapter: may a person remove a bundled entry on their own machine) closes as moot, since no bundled entry remains to remove. The detail H9 left to the lane, whether oracle.denylist survives as an optional repository or machine extension, is decided as keep: the setting already existed in both layers, and removing the bundled list leaves it working with no added code, which is the ruling's condition.

  • dcn-26093000000000052026-09-30

    2026-09-30 — Ruling DR6 (the product thinker, 2026-09-29, verbatim: "per-run agent limit: WORK IN PARALLEL — a run may build several pieces and run reviewers concurrently up to its limit (new build-loop work; then AC6 is testable).") is designed into spc-2609202134341288 as its piece 6 and recorded as decision 7 of itd-2609201925079472 (lane dr6Spec of autonomous run A; records only, nothing built). A slot is one outstanding await in the run's state file, implementers and validators alike; the validators of a round run side by side; a spec step runs beside earlier ones only when it declares - needs: (absent, it needs every earlier step, so itd-2609212103565953's in-order landing holds for every spec written so far); a lane lands one at a time and, when a sibling landed after its base, is merged with the default branch (never rebased) and judged by a fresh round, a sync that does not count against --fix-rounds. Criterion 6 is tested through the spec's criteria C1 to C12.

  • dcn-26093000000000042026-09-30

    2026-09-30 — The 2026-09-29 itd111Follow entry above records the ordering of the stale-binary refusal but not what it changes for a repository that is already set up, which only commit ea70f3c9b and its pull request named (recorded by lane integ23 of autonomous run A, from the review of itd111Follow). Because the refusal runs before the adoption question and before the idempotency check that answers a set-up repository with already_up_to_date, ahoy install run through a stale or unknown-vintage binary on an already set-up repository refuses and names both revisions, instead of reporting it already up to date; an explicit --adopt=false through such a binary yields refused, with its note, rather than aborted. Both are the louder answer itd-111 asks for: a stale binary that reports "up to date" is the silent answer its design decision 1 forbids (iss-2609291942529461).

  • dcn-26093000000000032026-09-30

    2026-09-30 — BU1 and BT1 are applied under H6, the person's approval of v0.12.0 as a breaking release in the human-step interview ("next release: APPROVED as BREAKING v0.12.0 (lane-stage rename per BU1 + old command spellings removed per BT1), with a migration note in the release notes", 2026-09-29), by autonomous run A's lane breakingStages. The implement loop's lane stages are stage: the run state file's lanes and record lines, the implement step and implement receipt results (performed became performed_stage, step became stage), every loop refusal (refusal.stage) and the status board's lane; the spec's spec_step, step_title and pending keep "step", and the verb keeps its name, implement step performing one stage. The state file is schema version 4, and a file of versions 1 to 3 is migrated on read, never rewritten by the read: each step is carried over to stage in memory and the run's next mutation writes version 4, as the loop already did for versions 1 and 2, while such a file that already says stage is refused. Migration was chosen over refusing the old file so a run in progress survives the upgrade (the lane's technical ruling). The one-release stubs itd-2609212130136102 left are removed in the same cut: ahoy dry-run, ahoy identity-check, version (with --check), docs lint and site check are unknown commands, and bare identity and bare ahoy remote list their sub-verbs; the CLI's moved-spelling machinery goes with them while the release snapshot keeps its moved_to field, which the snapshots the guardrail diffs against still carry. The upgrade guide docs/how-to/upgrade-to-v0.12.0.md names every renamed field and removed spelling with its replacement. BU1 ruled on the build loop only, so the shared run's implement check vocabulary, which also says "step", is left as it is and captured as iss-2609292359485570 for a ruling. Resolves iss-2609291313276243 and iss-2609251324599468; criterion 5 of itd-2609212103565953 is met, and its spec stays open for criterion 2.

  • dcn-26093000000000022026-09-30

    2026-09-30 — Pending the person's ruling CL1, a promoted inbox report files the machine value: outside text never becomes a drain-eligible remedy without a person naming it (fix round of lane remedyRequired, autonomous run A, closing the review's trust finding on the entry of 2026-09-29 above). As built: inbox promote always writes remedy: none (filed automatically) (issueschema.MachineRemedy), whatever the report proposes, so abcd drain --dry-run lists the issue as ineligible; the sender's proposal stays in the issue's text under "Remedy the reporter proposes:", scrubbed like every other value the report carries, for a person to adopt with capture remedy. This narrows the entry above, which filed a report's own remedy as the issue's; the ruling CL1 may widen it again.

  • dcn-26093000000000012026-09-30

    2026-09-30 — The 2026-09-29 itd111Follow entry above records the ordering of the stale-binary refusal but not what it changes for a repository that is already set up, which only commit ea70f3c9b and its pull request named (recorded by lane integ23 of autonomous run A, from the review of itd111Follow). Because the refusal runs before the adoption question and before the idempotency check that answers a set-up repository with already_up_to_date, ahoy install run through a stale or unknown-vintage binary on an already set-up repository refuses and names both revisions, instead of reporting it already up to date; an explicit --adopt=false through such a binary yields refused, with its note, rather than aborted. Both are the louder answer itd-111 asks for: a stale binary that reports "up to date" is the silent answer its design decision 1 forbids (iss-2609291942529461).

  • dcn-26092900000000222026-09-29

    2026-09-29 — Every new issue carries a remedy, and abcd's own automatic filers write one machine value when they have no fix (the product thinker's rulings BX3 and H12 of 2026-09-29, applied by lane remedyRequired of autonomous run A; partial of itd-82, whose decision 6 already required the field). BX3, verbatim: "REFUSE the filing; every new issue must carry remedy:". H12, verbatim: "'NO FIX YET' ALLOWED: automatic filers may write remedy 'none (filed automatically)'; the record is filed, drain skips it until a person writes a real remedy." As built: capture refuses a new issue with no remedy or a blank one, exit 2 and nothing written, naming --remedy and the machine value; the value is spelt once, issueschema.MachineRemedy, and written by every in-binary filer (the consistency pass, and an inbox report promoted without a remedy of its own, whose own remedy otherwise becomes the issue's); abcd drain --dry-run lists a record carrying it as ineligible, naming the automatic filer and the verb that answers it; and capture remedy <iss-N> "<fix>" writes or replaces the remedy on an open issue. A record filed before the rule carries none, stays readable and valid, and is listed as ineligible. The one-line capture friction that commands/capture.md and the principle adversarial-review-scales-with-blast-radius promised is tightened by the ruling, and both now say so. A person typing the machine value is REFUSED, by capture --remedy and by capture remedy, compared trimmed and case-folded: the value is useful only while it means that a machine filed the record, and a person has either a fix to name or the choice not to file; allowing it would let a hand-filed record pass as machine-filed and be skipped silently. A remedy chosen in an autonomous run cites its grounds, a prior-art or state-of-the-art check where the fix depends on outside practice (principle prefer-sota), in the capture's text; nothing checks that mechanically yet.

  • dcn-26092900000000212026-09-29

    2026-09-29 — Ruling J13 (the product thinker, 2026-09-29, verbatim: "iss-2608230752354928 source_kind: BOTH, two separate labels (tool + route).") is applied to the transcript store (lane sourceLabels, autonomous run A). source_kind carries the ROUTE, a closed set of native (abcd's own capture of the host's transcript) and import (another tool's export); a new source_tool carries the TOOL, an open lowercase slug with host reserved for the harness abcd is installed in. The tool vocabulary is open rather than closed, so a second harness needs no code change, and because it is caller-named it passes the redaction scan with the body and a label the scan would change refuses the capture. Neither label can stand in for the other: the route refuses a tool name, the tool refuses a route word and any -import composite, and an import never names host. A record stored before the split carries source_kind alone and reads under both labels, derived on read without rewriting it: native as native from host, specstory-import as import from specstory; the same derivation accepts the fused spelling on write. Nothing migrates on write, and only history migrate, rewriting a record for its own reasons, stamps the new form. The record schema version does not move: parsing is by field presence (adr-2609021016275803).

  • dcn-26092900000000202026-09-29

    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).

  • dcn-26092900000000192026-09-29

    2026-09-29 — The product thinker's rulings CH1 and CH2 of 2026-09-29 correct the salvage-hook timeout entry above (iss-323; recorded by lane salvageTimeout of autonomous run A, fix round 1). CH1: only the every-message hook, UserPromptSubmit, declares "timeout": 120; PreToolUse and PreCompact declare no timeout and keep the host's ten-minute default, so a slow first download always finishes there. CH2: SessionStart (240 seconds) shows the same statusMessage as the salvage entries, and the text states no duration ("abcd: checking the plugin binary; a first run downloads it, so this can take a while"), because the entries that show it now have two-, four- and ten-minute limits. The command strings stay byte-identical, and internal/surface/cli/hooks_timeout_test.go pins both the timeouts and the message's lack of a duration. The entry above stands as written, since the ledger is append-only.

  • dcn-26092900000000182026-09-29

    2026-09-29 — The product thinker's ruling of 2026-09-29 on the salvage-hook timeout is applied (iss-323; recorded by lane salvageTimeout of autonomous run A): every hook entry that runs hooks/bootstrap.sh as a salvage (UserPromptSubmit, PreToolUse, PreCompact; SessionEnd no longer does) declares "timeout": 120, and the wait is shown rather than silent through the host's statusMessage field, its spinner text while a hook runs. A notice from the script itself cannot show, because each salvage command sends the script's output to /dev/null and those command strings, which carry the PATH trust checks, stay byte-identical. SessionStart keeps 240, and internal/surface/cli/hooks_timeout_test.go pins every event's timeout, absent ones included. The host's hooks reference, read the same day, gives a command hook a 600-second default lowered to 30 on UserPromptSubmit, not the 60-second default the 2026-08-01 bootstrap entry records; so 120 raises the prompt hook's budget and bounds the other two below their default, which is the ruling's two-minute ceiling on any stall.

  • dcn-26092900000000172026-09-29

    2026-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-26092900000000162026-09-29

    2026-09-29 — Every new issue carries a remedy, and abcd's own automatic filers write one machine value when they have no fix (the product thinker's rulings BX3 and H12 of 2026-09-29, applied by lane remedyRequired of autonomous run A; partial of itd-82, whose decision 6 already required the field). BX3, verbatim: "REFUSE the filing; every new issue must carry remedy:". H12, verbatim: "'NO FIX YET' ALLOWED: automatic filers may write remedy 'none (filed automatically)'; the record is filed, drain skips it until a person writes a real remedy." As built: capture refuses a new issue with no remedy or a blank one, exit 2 and nothing written, naming --remedy and the machine value; the value is spelt once, issueschema.MachineRemedy, and written by every in-binary filer (the consistency pass, and an inbox report promoted without a remedy of its own, whose own remedy otherwise becomes the issue's); abcd drain --dry-run lists a record carrying it as ineligible, naming the automatic filer and the verb that answers it; and capture remedy <iss-N> "<fix>" writes or replaces the remedy on an open issue. A record filed before the rule carries none, stays readable and valid, and is listed as ineligible. The one-line capture friction that commands/capture.md and the principle adversarial-review-scales-with-blast-radius promised is tightened by the ruling, and both now say so. A person typing the machine value is REFUSED, by capture --remedy and by capture remedy, compared trimmed and case-folded: the value is useful only while it means that a machine filed the record, and a person has either a fix to name or the choice not to file; allowing it would let a hand-filed record pass as machine-filed and be skipped silently. A remedy chosen in an autonomous run cites its grounds, a prior-art or state-of-the-art check where the fix depends on outside practice (principle prefer-sota), in the capture's text; nothing checks that mechanically yet.

  • dcn-26092900000000152026-09-29

    2026-09-29 — The 2026-09-29 entry applying ruling J15 names one plain-path consequence of the ledger forgetting a stopped domain, a domain edited out of rules.json and back; there is a second, which needs no edit at all: a dormant domain activated with *NAME is in force for that prompt alone, so a prompt without the prefix drops it from the active set and the next *NAME renders it again (review-routerRemoval finding 2; recorded by fix round fix-routerRemoval of autonomous run A; Refs: iss-2608261550580260). Both follow from J15, since the domain left the set in between, and both are documented in brief 05-internals/03-configuration.md "The prompt router's output"; the rule-loader text in AGENTS.md and the managed-repository marker block qualify "never re-injects unchanged rules" to a domain that stays in force. The earlier entry stands as written.

  • dcn-26092900000000142026-09-29

    2026-09-29 — Ruling J10 of the product thinker, applied (lane teachPlane, autonomous run A; Refs: iss-151): itd-103's teaching plane is built rather than dropped from the intent (the ruling, verbatim: "BUILD IT (a lane; the registry is the single source)"). The rules loader bundles a SHELL domain generated from the bundled hazard registry the guard reads: one rule per entry and one recall term per command head, plus a fixed five-word list for shell work in general (bash, command line, force push, shell, zsh); no second copy is written in the bundled rules.json, and a test fails the build if the domain and the registry part. Two consequences taken by the lane rather than the ruling: the domain is built from the bundled registry only, never from a repo's .abcd/guard.json, because the two features keep independent switches (spc-16, "Config home"); and SHELL joins COMMITTING, LOAD and PII as a guardrail domain, so an override that withholds a bundled lesson is named on every load.

  • dcn-26092900000000132026-09-29

    2026-09-29 — Ruling J15 of the product thinker, applied (lane routerRemoval, autonomous run A; Refs: iss-2608261550580260): the prompt router's removal signal for a client that snapshots injected rules is the FULL active-domain list on every prompt, and a name absent from it has stopped (the ruling, verbatim: "FULL ACTIVE-DOMAIN LIST each time (absence = stopped)"), not tombstones. The list rides the --json envelope of abcd hook prompt-router, the flag every verb takes for a machine reader, as active beside text and injected; the hook manifest keeps invoking the plain form, so the model's context is unchanged and a prompt that matches nothing still adds zero tokens. Two consequences taken by the lane rather than the ruling: an envelope whose prompt could not be evaluated (an unreadable payload, a rules.json that will not load) carries error and no active field, meaning "unknown, change nothing", so a typo never reads as every domain stopping; and the per-session ledger forgets a domain the turn it leaves the list, so its return re-injects its text once for a client that pruned it.

  • dcn-26092900000000122026-09-29

    2026-09-29 — Ruling J13 (the product thinker, 2026-09-29, verbatim: "iss-2608230752354928 source_kind: BOTH, two separate labels (tool + route).") is applied to the transcript store (lane sourceLabels, autonomous run A). source_kind carries the ROUTE, a closed set of native (abcd's own capture of the host's transcript) and import (another tool's export); a new source_tool carries the TOOL, an open lowercase slug with host reserved for the harness abcd is installed in. The tool vocabulary is open rather than closed, so a second harness needs no code change, and because it is caller-named it passes the redaction scan with the body and a label the scan would change refuses the capture. Neither label can stand in for the other: the route refuses a tool name, the tool refuses a route word and any -import composite, and an import never names host. A record stored before the split carries source_kind alone and reads under both labels, derived on read without rewriting it: native as native from host, specstory-import as import from specstory; the same derivation accepts the fused spelling on write. Nothing migrates on write, and only history migrate, rewriting a record for its own reasons, stamps the new form. The record schema version does not move: parsing is by field presence (adr-2609021016275803).

  • dcn-26092900000000112026-09-29

    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).

  • dcn-26092900000000102026-09-29

    2026-09-29 — The product thinker's rulings CH1 and CH2 of 2026-09-29 correct the salvage-hook timeout entry above (iss-323; recorded by lane salvageTimeout of autonomous run A, fix round 1). CH1: only the every-message hook, UserPromptSubmit, declares "timeout": 120; PreToolUse and PreCompact declare no timeout and keep the host's ten-minute default, so a slow first download always finishes there. CH2: SessionStart (240 seconds) shows the same statusMessage as the salvage entries, and the text states no duration ("abcd: checking the plugin binary; a first run downloads it, so this can take a while"), because the entries that show it now have two-, four- and ten-minute limits. The command strings stay byte-identical, and internal/surface/cli/hooks_timeout_test.go pins both the timeouts and the message's lack of a duration. The entry above stands as written, since the ledger is append-only.

  • dcn-26092900000000092026-09-29

    2026-09-29 — The product thinker's ruling of 2026-09-29 on the salvage-hook timeout is applied (iss-323; recorded by lane salvageTimeout of autonomous run A): every hook entry that runs hooks/bootstrap.sh as a salvage (UserPromptSubmit, PreToolUse, PreCompact; SessionEnd no longer does) declares "timeout": 120, and the wait is shown rather than silent through the host's statusMessage field, its spinner text while a hook runs. A notice from the script itself cannot show, because each salvage command sends the script's output to /dev/null and those command strings, which carry the PATH trust checks, stay byte-identical. SessionStart keeps 240, and internal/surface/cli/hooks_timeout_test.go pins every event's timeout, absent ones included. The host's hooks reference, read the same day, gives a command hook a 600-second default lowered to 30 on UserPromptSubmit, not the 60-second default the 2026-08-01 bootstrap entry records; so 120 raises the prompt hook's budget and bounds the other two below their default, which is the ruling's two-minute ceiling on any stall.

  • dcn-26092900000000082026-09-29

    2026-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-26092900000000072026-09-29

    2026-09-29 — The product thinker answered twenty-six owed rulings and the published-history question in one interview, asked one at a time by orchestrator abcd-23 of autonomous run A (recorded by lane recRulings for orchestrator abcd-cb). The answers are kept verbatim in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29.md, dated 2026-09-29, and are restated here because that file is not committed. Published history is left as it is, with no rewrite. The build loop's fidelity audit runs once, on the lane that closes the spec, over the whole delivery (AI). On the vendor denylist the product thinker answered, verbatim: "I think we need an allow list rather than trying to catch a deny list." The interviewer's reading of that answer, recorded as a reading and not as the product thinker's words, is that the per-provider allowlist is the control and the vendor denylist is not extended to chase spellings, with whether the bundled anthropic/* entry stays as a backstop left to the technical facilitator (AA(a)). Only a route the person set up on their own machine may use their paid key, and a repository's own route to it is refused, which replaces the route half of itd-2609081951381895 decision 8 (AA(b)). The live site setup, the API adapter and the decision adapter may each close on tests against a simulated service, with the live paid check recorded as owed to a person (iss-2609291925387011, iss-2609291925393913, iss-2609291925398978). itd-111's last criterion is met by an agent's timing check on macOS plus the Linux CI run, so the intent may be finished. Automated dependency updates are switched on, pushed with a personal or app token the person creates and stores as a repository secret (itd-2609221842494980; creating the token is the person's act, and the lane builds everything else and names the secret it expects). itd-6 adds a Go MCP module, proposed for the person's explicit sign-off before it is fetched; closing itd-6 on a fake server was not ruled in this interview. (A later answer the same day, H1b in the local-tier file .abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md, dated 2026-09-29, rules that it is not: itd-6 is finished only after running once against the real RepoPrompt app, a check owed to a person.) For itd-148: the store under the home folder wins (adr-2609091248200336); the store draft itd-2609091014076309 owns add, list and clean-up and itd-148 uses them; a session that declares itself the coordinator is exempt from the write block in the primary checkout and every other session is blocked; and the store draft is planned first, with nothing from the store draft, the merged-worktree clean-up included, built before its planning interview (Q4). itd-148's own wait is not part of that ruling: it follows from Q2, because itd-148 uses the store's verbs, and is carried by the blocked_by below. itd-148 and spc-42 are rewritten to match in this change, and itd-148 is now blocked_by the store draft. A release retrospective is seeded from a release, the intents a tag shipped (AD); itd-24 and its spec are rewritten to the release in this change. An unpointed route is refused naming the one setting to add, as built in 35100512e, so AC11 of itd-2609170822093401 is complete (BR1). A missed target becomes next, whatever the following release is numbered (BS1). Spec pieces keep "step" and the lane stages are renamed, a breaking change to the JSON fields step, performed and refusal.step that resolves iss-2609291313276243 and corrects the glossary entry core/step.md (BU1), and the old command spellings are removed in that same breaking release (BT1). The text board shows Later as a count only while the site and --json keep the full list (BV1), and an intent in progress appears only under Now (BV2). A pause of zero is allowed (BW1); drain stays in the agents' help list until it runs end to end (BX1); a managed repository must hold the drain eligibility decision in its own record, and drain refuses there until it does (BX2); a capture without a remedy is refused (BX3), which tightens the one-line capture friction commands/capture.md promises, so the lane that builds it reconciles that page, the principle wording and every caller that files a capture; a run's pick reason keeps the shared pursued: kind with its marker (BZ1); and an intent whose blocker was superseded waits on the successor, transitively (BZ2). The five itd-48 follow-ups are planned as one intent, drafted as itd-2609291923559186 (BT2), and all warn rules share one shrink-only baseline file in which a new warning fails, drafted as itd-2609291924469783 (BT3); both drafts wait on their planning interviews. Each ruling that contradicts a shipped behaviour or another record is amended in the change that builds it, not here. itd-7's planning interview stays owed.

  • dcn-26092900000000062026-09-29

    2026-09-29 — A records-only lane skips the lane preflight, and the integration branch that lands it runs the one preflight that judges it (ruling by the run A orchestrator abcd-fc [aaba3e]; recorded by lane integRemedies of autonomous run A). A records-only lane changes no code, only record files, and it still runs record-lint, lint-issues, lint-decisions, docs-lint and abcd lint outbound before it reports. Running make preflight once per such lane would queue nine full runs behind the machine's one-preflight lock to judge a tree whose code no lane touched. The receipt the push gate needs is minted by the integration's preflight, on the merged tree that is actually pushed.

  • dcn-26092900000000052026-09-29

    2026-09-29 — Every open issue that carries no remedy gets one (the user as product thinker, directly to the run A orchestrator abcd-fc [aaba3e] on 2026-09-29, verbatim: "add a sensible remedy for each -- conduct SOTA first when necessary"; recorded by lane integRemedies of autonomous run A). The run reads the ruling this way. Each such record gets a one-line remedy:. Where the fix depends on outside practice, a primary-source check grounds the remedy first. A remedy that waits on an unanswered ruling or planning interview opens "Waits on <ruling/interview>:" and names one fix per possible answer, choosing none: the drain's field rule ignores deferral_reason, so the remedy's own opening is what hands such a record back. Nine records-only lanes, remedyA to remedyI, applied it to 187 records. They skipped one, iss-2609020721396212, because it is resolved on a peer branch and an edit to its open copy would collide with that move. They found one duplicate, iss-2609230949466602 of iss-2608282026177429, which is closed as wontfix with a typed duplicates link.

  • dcn-26092900000000042026-09-29

    2026-09-29 — An autonomous run keeps at most eight sub-agents alive at once, in any mix of roles (the user as product thinker, directly to the run A orchestrator abcd-cb [e13a96] on 2026-09-29, verbatim: "use up to eight sub-agents to drain the ledger"; recorded by lane integRemedies of autonomous run A). The ceiling of eight supersedes the ceiling of five recorded above on 2026-09-29 (06:53Z, "use up to five sub-agents from now on"), which already has its own entry. Reviews and audits run on Fable stay one at a time; that rule is unchanged. The run still counts a fork toward the ceiling, as its own lane rule, because a fork is an agent alive.

  • dcn-26092900000000032026-09-29

    2026-09-29 — An autonomous run keeps at most five sub-agents alive at once, in any mix of roles (the user, directly to the run A orchestrator at 06:53Z, verbatim: "use up to five sub-agents from now on"; recorded by lane remerge-integ17 of autonomous run A). The ceiling of five supersedes the ceiling of four recorded above on 2026-09-24 (02:02Z). Reviews and audits run on Fable stay one at a time; that rule is unchanged. The run still counts a fork toward the ceiling, as its own lane rule, because a fork is an agent alive.

  • dcn-26092900000000022026-09-29

    2026-09-29 — The home the 2026-09-23 entry on third-party interface guidance left "still to be written" is a principle, .abcd/development/principles/guidance-carries-its-evidence-and-its-purpose.md, rather than the managed-repository agent conventions (lane triageMajorB, autonomous run A, on iss-2609100506256173; the product thinker's ruling M26 allowed either). A principle states both halves once, in this repository's record, with no change to what abcd writes into a managed repository; carrying the rule into the bundled rules domains that reach every managed repository is a shipped-behaviour change and is left for a planned intent, as is the purpose field on redaction rules that would make the second half checkable.

  • dcn-26092900000000012026-09-29

    2026-09-29 — Correction to the 2026-09-25 entry on the pre-commit guard's sources refresh (itd-76, iss-2609250834251447): that entry says the scaffolded copy's opt-in shape "answers none of the three questions the ruling holds", and half of that is not so. The template abcd ahoy scaffolds (internal/core/ahoy/defaults/pre-commit) takes a PROVISIONAL stance on two of the three questions: default or opt-in — opt-in, since nothing runs until the clone sets abcd.sourcesBinary; fail open or closed — open, since an unusable opt-in (not an absolute path to an executable regular file) prints one line and the commit proceeds. Only the first question, how a scaffolded hook finds abcd, stays unanswered in the template's own terms, which say it "deliberately does not take" that decision. Both provisional answers stand until the product thinker rules on iss-2609250834251447, and the ruling may replace either. The earlier entry stands as written, since the ledger is append-only (review2-sources finding 5; recorded by lane drainDrift2 of autonomous run A, iss-2609252055533837).

  • dcn-26092800000000082026-09-28

    2026-09-28 — Correction to the 2026-09-25 entry on the build's open-question check (lane implementer, autonomous run A, lane drainInt, on iss-2609260932374727). A settled LABEL (resolved:, RESOLVED:, Deferred:) is no longer read anywhere in the item: it counts opening a line of the item (its first line or a continuation line), after a closing bold (**Which surface scaffolds it?** RESOLVED:), or after a dash (**Refusal breadth** — resolved:, **Relationship to itd-73** (derived versioning) — RESOLVED:). The same word and colon mid-sentence are prose, so "Which id wins once the split is resolved: the old or the new?" is a question, where the entry's "anywhere in the item" read it as settled and let build start past it. The bold-span marker keeps its reach anywhere in the item. Every intent in the tree reads the same open-question count under the tightened rule as under the old one, so no record changes verdict.

  • dcn-26092800000000072026-09-28

    2026-09-28 — v0.11.1 is published: autonomous run A approved the release environment at 22:44:40Z under ruling A2 and the releases ruling of 2026-09-25T08:04:52Z, after the merge queue, the verify job, the tag job and main's own CI on the tagged commit 2bc519f7 reported green (every check run succeeded apart from those skipped by design; the macOS leg of the push CI was the last to report). The release published at 22:47:00Z with four binaries, the plugin archive, checksums.txt and the site archive; the run verified the darwin-arm64 binary and the plugin archive against checksums.txt, abcd --version reports v0.11.1, the plugin archive's SHA-256 equals the digest the catalog pins and its address answers, and the build-provenance attestation verifies as signed by release.yml on main. Unlike v0.11.0, the site rendered and deployed inside the release run, so no redeploy was needed; abcdev.app shows v0.11.1. The version is v0.11.1 rather than the v0.12.0 the run had expected, because the cut derives the version from the records and nothing since v0.11.0 is breaking.

  • dcn-26092800000000062026-09-28

    2026-09-28 — A parameter expansion is an unknown word, read for what its value can spell and not for what an earlier command carried into it, and the reading keeps its over-reads, recorded so they are not mistaken for defects (lane drainG3, autonomous run A, on iss-2609251824244354; this supersedes allow (4) of the first 2026-09-25 entry and ruling (c) of the third, which parked the plain-variable half). $X, $1, $@, $*, $- and a ${…} read whole to its own } leave the unknown word's mark where the value goes, so --$X is every flag it could become and $GIT in command position is every program its known text allows; $$, $!, $? and $# print numbers and stay text, as an arithmetic expansion's output is a number. Allow (1) of the first 2026-09-25 entry extends to a word that is wholly a variable: it is one operand, so git push origin "$branch" stays allowed and git push $X origin main is not seen. A string handed to a shell is read with each variable-only word written back out (sh -c "… $X …" reads $X as that shell does), so a bare variable in a string raises no new warn, which keeps the gap shellRawUninspectable names: a value holding shell syntax is not read. The 4,315-input false-positive sweep (Makefile recipes, script lines and whole scripts, the repo-mined and adversarial corpora, and 81 everyday variable lines) moved from 4,000 allow / 47 block / 19 warn to 3,991 / 49 / 26 with 249 unparsable lines unchanged, after three readings of a carried value were left out because together they added 37 blocks on ordinary work: a variable handed to a shell or source as its script is not a stream (bash "$script"), and a variable standing as the program fires no entry that names only its program and an operand (pkill-by-pattern, killall-by-name) and is not a bare interpreter inside a string ("$GO" build, $EDITOR notes.md). Those, a pid list carried through a variable, and eval "$X" (which allows, as it did) are iss-2609281134544802, deferred past v0.11.0 for a ruling. Over-reads kept, each the variable twin of a ruled substitution over-read: a variable program name with a variable first operand can be git clean and warns (exec "$BIN" "$@", "$BASH" "$GATE"; five lines of the sweep), git -c core.quotePath=false "$@" warns under git-clean, git grep whose pattern holds a variable and a ( warns under the fail-safe as its substitution twin does, two printf continuation lines of a script read on their own ("$n" "$n" "$spec" "$n") block as gh-repo-delete, git -c "$KV" commit blocks as a commit that may move core.hooksPath, and a stream piped into a shell whose script is a variable (curl … | bash "$f") blocks, because a word wholly an expansion may be no word. The kill-by-search reading gains three feeds in the same lane (iss-2609270036253187): an unquoted here-document's substitutions are the standard input of the command that opened it, a substitution runs with the pipe into its own command as its input, and a shell string is handed the output of the substitutions in its command's words as its positional parameters or text, so every command of such a string is read as handed it (sh -c 'kill 4242' _ "$(pgrep make)" blocks), the over-block the 2026-09-27 entry accepts for a string xargs runs.

  • dcn-26092800000000052026-09-28

    2026-09-28 — iss-2609280932480608 is fixed rather than deferred (ruling by orchestrator abcd-9f, autonomous run A; lane fix2-drainH): iss-2609100506256636's rule, danglingness not provenance, applies past the one entry install acts on, so a gap-driven install removes every abcd-owned dangling PATH entry other than its target, with its record, and names each in a note. The removal waits for the target to be a working entry of abcd's own after the step, not merely for the run to have something to write: a cold-cache run that adopts the one-liner's copy writes nothing and still leaves abcd answering, while a run that leaves nothing working at the target keeps the dangling entry and names the command to run first. An unowned dangling link is never removed by this step. A dangling link runs nothing — the shell skips it — so the shadow note and the dangling gap no longer say it is what runs or that it shadows later entries. Correction to the 2026-09-27 entry above on iss-2609100506263330: an unrecorded dangling link is not cleared only when install writes the verified copy there, as that entry says, but whenever install writes an entry of its own there — the verified copy, or the --dev shim when the plugin binary it rebuilds beside exists; clearDanglingEntry clears it ahead of either write, and a run with nothing to write in its place still leaves it untouched.

  • dcn-26092800000000042026-09-28

    2026-09-28 — abcd banlist list unfiltered is byte-identical to bare abcd banlist (iss-2609282105240081, the v0.11.1 gate's x-115), the plain unfiltered <verb> list the naming chapter forbids; DEFERRED out loud past v0.11.1 rather than fixed by lane gateFix of autonomous run A. The chapter forbids the shape and prescribes no remedy, and every remedy changes a shipped verb: an unfiltered list that refuses and points at bare banlist (the capture list precedent, which refuses without a status flag) breaks a script calling it; retiring list moves its layer filter onto bare banlist; naming it in the bare-invocation exception paragraph keeps the shape the rule forbids. Which one is the product thinker's call, so the record carries deferred_after: "v0.11.1" and the reason, and waits for that ruling.

  • dcn-26092800000000032026-09-28

    2026-09-28 — guard registry, the rm targets (iss-2609282105242542, autonomous run A lane gateFix): the chapter's headline promised the catch of "an rm -rf with an unlucky glob" while the one rm entry fired only behind a cd chain, so rm -rf / and rm -rf ~ were an allow. Two bundled entries close it through one new additive Pattern field, arg_values (some operand is exactly one of the listed words, by its known text; empty and dash-led values are load-time rejections like an empty prefix). rm-rf-root-or-home is a BLOCKER on /, /*, ~, $HOME, ${HOME} and their / and /* forms; rm-rf-working-directory is a WARN on *, ., .., ./, ../, ./*, ../* and .*, graded like git clean because emptying a build directory the same way is ordinary work and a blocker there would teach sessions to route around the guard. Both require the recursive flag alone, not -f: for an agent, whose stdin is not a terminal, rm does not prompt, so -f changes nothing about what is destroyed (the cd-chain entry keeps its -f requirement; changing a blocker's pattern is a separate act). This reverses the incidental stance that a bare rm -rf * is not a hazard (the lab finding iss-2609012040019014 and two tests that used it as their ordinary-work probe): those tests keep their point with rm -rf ./build as the probe, and a host workdir is still never read as a cd. A third operand residual is recorded beside the two unknown.go names: a target a substitution prints WHOLE (rm -rf $(echo /)) is read by its known text, as the + refspec prefix is, because rm -rf $(find . -name '*.pyc') is how an everyday delete names its targets and reading the word as every target would block it as a delete of /; glued text still counts ("$(true)"/ is /). Parameter expansions stay unread except as the literal words the entry names (rm -rf "$DIR"/* with DIR unset is not seen). The per-byte work bar of the guard's cost tests moves from 20 to 24: the operand walk reads every token once per entry, and sixteen entries put the costliest asserted shape at about 20.

  • dcn-26092800000000022026-09-28

    2026-09-28 — Release v0.11.1 is cut by autonomous run A, and the run's agenda line is: approve the publish step. Under ruling A2 of the product thinker's run A interview (2026-09-23 07:52Z: the run approves the release environment itself once every gate is green) and the product thinker's releases ruling of 2026-09-25T08:04:52Z ("cut additional releases if that makes sense, but bundle multiple intents for it"), the run approves the release environment's deployment of v0.11.1 only after the merge queue, the verify job and every other gate on the tagged commit report green, and stops with a handover instead if any does not. The cut: v0.11.1, impact additive (no breaking record since v0.11.0; the run had been calling it v0.12.0 until launch ship derived the version), 354 records since v0.11.0: eighteen shipped intents, all additive, and 336 resolved or declined issues (228 fixes, eighteen additive, 90 internal and outside the changelog); the release guard and the findings guard passed with no waiver. Content commit 8a6c83d5, on top of 9ead1d1bf, which the docs-currency gate's findings required. Both semantic gates ran at tier full. The docs-currency-reviewer (Fable 5.1) read the first roll 7c7f5525 and found four minor findings (two stale terminology rows, a README sample status line no state renders, and the root command sentence missing three dispatched record families), all fixed in 9ead1d1bf. The brief-surface cross-check (44 pinned checkers, Opus 5.5, at most four alive) found 127; an independent classification (Fable 5.1) found 126 real at the content commit: the two user-facing and three behaviour findings are captured as four records (iss-2609282105240689, iss-2609282105242542, iss-2609282105241960, iss-2609282105240081), the one major among them, the guard registry passing a bare rm -rf / (iss-2609282105242542), deferred out loud past v0.11.0 because it already shipped in v0.11.0 and a registry change needs its own tests and review, all four to be fixed in the first lane after the tag; the design-record drift goes to the systematic brief pass iss-2609091956001547. Landed before the cut on the cutting session's ruling: #736 (integration branch 11); integration branches 12, 13 and 14, reviewed and ready, hold until the tag and fall into the next release.

  • dcn-26092800000000012026-09-28

    2026-09-28 — Rulings Z, AR and the cancel policy, given by the user as technical facilitator at 15:10:37Z (autonomous run A, recorded by lane cap45 for orchestrator abcd-a8). (Z) The macOS leg of ci.yml's check job and the main ruleset's merge-queue check_response_timeout_minutes both rise from 30 to 45 minutes, because a 30-minute cap cancelled passing macOS runs (#728, #730 twice, #733; iss-2609281514435020). This amends the standing rule that never raises the check job's timeout or edits the ruleset, for exactly this one change: 45 minutes, those two settings; every other timeout, every required-check name or split and every other ruleset field stays as it is, and the ubuntu leg keeps 30. The workflow and the .abcd/work/rulesets/main-protection.json mirror change through a reviewed pull request; the live ruleset is changed with gh api by the run's orchestrator after that pull request merges, and until then the live queue still fails a group at 30 minutes. (AR) All three speed-ups of iss-2609261924541555 are built: a test-only switch that skips the disk flush in the atomic write code and the slowest -race package first in the race step (lane ciSpeed), and the scanner's per-identity git calls folded into one (lane scanFold), a trust path that is security-reviewed before it lands. (Cancel policy) The rerun-once rule stands: a check cancelled at the cap is rerun once, and a second cancellation for the same reason stops that pull request and opens a speed lane, never another raise of the timeout; and a step on the macOS leg warns, in the log and the step summary, once the check has run past 35 minutes, without ever failing the job, so a speed lane opens before any cancellation.

  • dcn-26092700000000052026-09-27

    2026-09-27 — A pipe into a group and a redirect into a shell string reach every command there, and the reading keeps two over-blocks, recorded so they are not mistaken for defects (lane fix3-drainG, autonomous run A, on iss-2609270028388291 from review-drainG2). A pipe into a { … } or ( … ) group is the standard input of every command in it, so each command emitted inside the group reads it, not only those before the group's first separator; a shell in the group reads it as a stream too. A command in a group is read as handed its group's input even when a pipe inside the group hands it another, because the command before that pipe may pass the group's input on (cat), and which commands do is not modelled; so pgrep make | { true; echo 4242 | { xargs kill; }; } blocks. The runs of the open groups are held as one covering run, which keeps each command's reading constant however deep groups nest, at the cost of also counting a search that sits inside an outer piped group before an inner one opens. A shell passes its standard input to the commands of its string, and a here-string or a process substitution redirected into the shell is that input, as a pipe is; the < that redirects a process substitution is not kept by the tokenizer, so a process substitution handed to the shell as an operand is read as its input as well, which is what sh -c 'xargs kill < "$1"' _ <(pgrep make) does with it.

  • dcn-26092700000000042026-09-27

    2026-09-27 — The kill-by-search reading follows a search into and out of shell strings, and keeps one over-block, recorded so it is not mistaken for a defect (lane drainG2, autonomous run A, on iss-2609262259360005 and the review of the first reading). Every command of a string that xargs runs is read as handed xargs's input, so pgrep make | xargs sh -c 'kill 4242' blocks as kill-by-search though its kill names a pid: xargs -I{} replaces the input into any part of the string, and telling a command that reads "$@" or $1 from one that does not would be a text match on the string, which the feed mechanism does not make. The same holds for the standard input a shell passes to the commands of its string (pgrep make | sh -c 'xargs kill'). The accepted over-block of the first reading, that a lower-case signal name (pkill -term -g <pgid>) blocked as pkill-by-owner because its letters read as the -t and -u selectors, is removed rather than recorded: pkill's first -NAME word naming a signal is read as its signal, in any case and with or without SIG, as procps-ng and BSD pkill read it, which is also what lets -U and -G be read attached (pkill -Ubob) without taking -HUP, -USR1 or -SIGTERM for them. Only the first such word is the signal, so pkill -9 -term -g <pgid> still blocks: both implementations hand the second word to their option parser as -t erm. killall is not read this way, because psmisc killall reads a signal name only when it begins with a capital letter and parses killall -term as killall -t erm.

  • dcn-26092700000000032026-09-27

    2026-09-27 — iss-2609100506263330 takes the record's option (b): with no verified release artefact in the persistent plugin data directory, ahoy install writes no PATH entry and names the install one-liner as the command to run first, rather than writing a symlink into the plugin root that the next plugin update strands (lane implementer drainH, autonomous run A, orchestrator abcd-51). Option (a), fetching the artefact inside install, is not taken: install's documented meaning is local configuration, and adr-38 lets the network answer only a verb whose documented meaning is the fetch; the one fetch-and-verify primitive (abcd update's) also imports ahoy, so reaching it from install would need a second downloader or an import inversion. A symlink into the plugin root that an earlier release wrote is left where it stands on a cold cache, raised as a required symlink.legacy gap whatever the cache holds, and recorded so the hooks accept it meanwhile. A dangling link ~/.abcd/path-entry names (read through the same owned, not-group-or-other-writable guard the hook shims apply) is classified abcd's own and repaired by install or removed by uninstall with its record; an unrecorded dangling link keeps iss-2609100506256636's ruling — no provenance claimed, left untouched by detection and by any run with nothing to write in its place, cleared only when install writes the verified copy there.

  • dcn-26092700000000022026-09-27

    2026-09-27 — A pipe into a group and a redirect into a shell string reach every command there, and the reading keeps two over-blocks, recorded so they are not mistaken for defects (lane fix3-drainG, autonomous run A, on iss-2609270028388291 from review-drainG2). A pipe into a { … } or ( … ) group is the standard input of every command in it, so each command emitted inside the group reads it, not only those before the group's first separator; a shell in the group reads it as a stream too. A command in a group is read as handed its group's input even when a pipe inside the group hands it another, because the command before that pipe may pass the group's input on (cat), and which commands do is not modelled; so pgrep make | { true; echo 4242 | { xargs kill; }; } blocks. The runs of the open groups are held as one covering run, which keeps each command's reading constant however deep groups nest, at the cost of also counting a search that sits inside an outer piped group before an inner one opens. A shell passes its standard input to the commands of its string, and a here-string or a process substitution redirected into the shell is that input, as a pipe is; the < that redirects a process substitution is not kept by the tokenizer, so a process substitution handed to the shell as an operand is read as its input as well, which is what sh -c 'xargs kill < "$1"' _ <(pgrep make) does with it.

  • dcn-26092700000000012026-09-27

    2026-09-27 — The kill-by-search reading follows a search into and out of shell strings, and keeps one over-block, recorded so it is not mistaken for a defect (lane drainG2, autonomous run A, on iss-2609262259360005 and the review of the first reading). Every command of a string that xargs runs is read as handed xargs's input, so pgrep make | xargs sh -c 'kill 4242' blocks as kill-by-search though its kill names a pid: xargs -I{} replaces the input into any part of the string, and telling a command that reads "$@" or $1 from one that does not would be a text match on the string, which the feed mechanism does not make. The same holds for the standard input a shell passes to the commands of its string (pgrep make | sh -c 'xargs kill'). The accepted over-block of the first reading, that a lower-case signal name (pkill -term -g <pgid>) blocked as pkill-by-owner because its letters read as the -t and -u selectors, is removed rather than recorded: pkill's first -NAME word naming a signal is read as its signal, in any case and with or without SIG, as procps-ng and BSD pkill read it, which is also what lets -U and -G be read attached (pkill -Ubob) without taking -HUP, -USR1 or -SIGTERM for them. Only the first such word is the signal, so pkill -9 -term -g <pgid> still blocks: both implementations hand the second word to their option parser as -t erm. killall is not read this way, because psmisc killall reads a signal name only when it begins with a capital letter and parses killall -term as killall -t erm.

  • dcn-26092600000000072026-09-26

    2026-09-26 — The build loop's worktree store is keyed on the FULL root sha: a lane lives at ~/.abcd/worktrees/<root-sha>/<run-id>-<lane-id> with the 40-hex root commit, the form the history, transcript and voyage stores use and the one the store's draft (itd-2609091014076309) specifies. The lanes of autonomous run A made by hand under the abbreviated key (~/.abcd/worktrees/488a0aa9/<name>/) are the pre-verb convention, not a second form of the store: the loop never reads or adopts a lane under that key, and those worktrees are retired with git worktree remove like any other (implementer of fix round fix2-loop2, autonomous run A, on item 4 of the loop2 review; spc-2609202134338445 piece 6).

  • dcn-26092600000000062026-09-26

    2026-09-26 — Three of the rules loader's security records close, and one stays owed to the product thinker (autonomous run A orchestrator's lane brief, taken by the implementer of lane drainS2). (1) The home directory is never a session's repo root (iss-2609020219198779, answering the owed question "is a home-directory git toplevel a legitimate config scope, or excluded outright?" as the brief rules it): its .abcd/ is the user layer, so the root walk passes over the home and a toplevel that is the home resolves like a non-repo directory. The lane narrowed the brief's "or an ancestor of HOME": a toplevel that contains the home, the shape of a hermetic harness that points HOME inside its checkout, stays the root because git vouched for it and its own .abcd/ is its own; only the stop at the home is removed. A session whose working directory is the home still reads a .abcd/ there as the working directory's, the posture question recorded on 2026-09-25. (2) A bundled guardrail that an override withholds is named on every load (iss-174): for COMMITTING, LOAD and PII, each bundled recall keyword, alias or rule missing from a list an override set goes to stderr with the file whose list is in force, and the merge stays per field. The other bundled domains are left out because a repository restates them in its own words, and a note on every restatement would bury the one that matters. Still owed to the product thinker: whether security-bearing lists should union with the bundled entries or take a replace-versus-extend marker instead (itd-117's finer-grained-merging follow-up). (3) The foreign-uid refusal says what it still reads (iss-2609251522588539): the note, the configuration chapter and the install how-to now say that a .abcd/ at the working directory is read, as AGENTS.md has since 0434d475. (4) iss-2609020219265817 is deferred past v0.11.0, not closed. Every CommonMark heading construct in a rule body (ATX on any line, the first line included, setext, and HTML h1-h6) can be closed only by a code-safe rendering that flattens legitimate structure, or by a fence-aware escaper that is complete only by enumeration and changes the raw text the model reads. So "escaped, fenced, or left to the line-start contract" is the product thinker's ruling.

  • dcn-26092600000000052026-09-26

    2026-09-26 — The reading ingest's prose-citation refusal departs from "every refusal past the identity point is recorded" (the rule refuse() in internal/core/reading/ingest.go enforces, from iss-2608311518250688): it is returned unrecorded, because a recorded refusal gives the run an outcome and refuseARerun would then refuse the same run re-worded, where the run left parked is ingested again once its prose describes the record rather than citing a missing id — the stance the verdict ingest takes. It keeps the rest of the refusal contract: it rolls back this run id's own half-landed records and stage as refuse() does, and runs no sweep of other runs' orphans. 04-surfaces/23-reading.md states it (implementer of lane fix2-drainL, autonomous run A, on review-drainL's design point for iss-2609261835118276).

  • dcn-26092600000000042026-09-26

    2026-09-26 — The lab store is keyed ~/.abcd/lab/<root-sha>/<lab-id>/, with one index.jsonl registry per root-sha lane beside the lab homes (lane implementer, autonomous run A, on review-lab's third finding against spc-2609212141418943 for itd-2609212137128014). This supersedes two recorded texts: the spec's literal ~/.abcd/lab/<lab-id>/ (scope item 1), and the 2026-08-31 lab-convention entry's hand-run keying ~/.abcd/lab/<timestamp>-<source-sha7>/ with a single top-level ~/.abcd/lab/index.jsonl, whose stated divergence from root-sha keying is withdrawn. Why: the intent's scope condition keys the store "as the other machine-scoped stores are", and the worktree and transcript stores key on the repository's root commit, because a checkout moves, is renamed and is cloned twice on one machine while its root commit does none of that; a lab's identity is still its intention, carried by its id lab-<yymmddHHMMSS>-<pin7> (the UTC mint time and the pin), so several labs share one baseline inside one lane. The hand-run labs that predate the verb stay where they are, beside the root-sha lanes, and the verb neither reads nor writes them or the top-level registry, so no real lab is moved or migrated by the change. A later text naming ~/.abcd/lab/<lab-id>/ (the open spc-2609221011151661's pairs.jsonl among them) means the lab home inside its root-sha lane.

  • dcn-26092600000000032026-09-26

    2026-09-26 — Three departures the scribe lane (itd-2609020625402599, spc-2609020626045177) made from its closed spec, which its review found recorded only in code, the chapter or the lane report, recorded here (implementer of lane fix2-scribe, autonomous run A). First, the surface chapter is 04-surfaces/31-scribe.md, not the 24-scribe.md the spec names: row 24 is decide's, taken before the lane landed, so the chapter took the next free row. The spec is closed and keeps its text; four open lanes claim row 31 (build, lab, source ledger and this one), so the integration step renumbers three of them. Second, the transcript store's check is SessionSeparation(repoRoot, rootSHA), not the SessionSeparation(rootSHA) the spec names, because it reads through history.List, which takes the repository root to find a checkout's opt-in per-repo transcript store; the report is unchanged. Third, the scribe's context is assembled from the ledger as it stands in the working tree, uncommitted records included, while the intent's scope condition (cond-2609020626046719) says committed ledger content. The working-tree read is what the code does today and the chapter says so. Whether the condition or the code should move is not decided here: it is captured as iss-2609261056373310, a ruling owed.

  • dcn-26092600000000022026-09-26

    2026-09-26 — v0.11.0 is published: autonomous run A approved the release environment at 07:14:41Z under ruling A2 and the releases ruling of 2026-09-25T08:04:52Z, after the merge queue, the verify job and main's own CI on the tagged commit 22997314 reported green (25 check runs succeeded, 5 skipped by design). The one red run on that commit was the site preview, which the run judged a deploy step and not a gate: site.yml's own header declares it non-gating, since release.yml calls it only after release and a failure there cannot change what was published. Its cause predates the release (iss-2609260709386741, major): since the root help was grouped, site is listed only under abcd --help --agent, and the workflow's probe read the plain listing, so every site run on main had refused since then, and v0.11.0's production render after publishing refused the same way. The release, its four binaries, the plugin archive (its digest equal to the catalog pin) and the attestations were published at 07:16:44Z and verified locally. The probe was fixed in #720, and the v0.11.0 site was redeployed through the workflow's documented emergency path, a dispatch from main naming the tag (run 36229830492), which rendered abcdev.app from the released binary and attached site.tar.gz to the release.

  • dcn-26092600000000012026-09-26

    2026-09-26 — Release v0.11.0 is cut by autonomous run A, and the run's agenda line is: approve the publish step. Under ruling A2 of the product thinker's run A interview (2026-09-23 07:52Z: the run approves the release environment itself once every gate is green) and the product thinker's releases ruling of 2026-09-25T08:04:52Z ("cut additional releases if that makes sense, but bundle multiple intents for it"), the run approves the release environment's deployment of v0.11.0 only after the merge queue, the verify job and every other gate on the tagged commit report green, and stops with a handover instead if any does not. The cut: v0.11.0, impact breaking (decided by itd-2609212130136102, the verb consolidation, whose five surface removals the guard names), 193 records since v0.10.0: eleven shipped intents (ten additive, one breaking) and 182 resolved or declined issues (108 fixes, three additive, 71 internal and outside the changelog); two major findings pass on their recorded deferrals (iss-2609250834251447, iss-2609251824244354). Content commit 9ef24744, on top of ae116575, which the docs-currency gate's findings required. Both semantic gates ran at tier full. docs-currency-reviewer (Fable 5.1) read the first roll and found four: the install one-liners ended on the retired abcd version, which v0.11.0 refuses with exit 2 (major; fixed in ae116575), a CONTRIBUTING wording (fixed there too), and two changelog lines recomposed by the composer; the guard gap behind one of them is captured as iss-2609260543090196. The brief-surface cross-check (40 pinned checkers, Opus 5.5, at most four alive) found 130, all real at the content commit by an independent classification (Fable 5.1): the eight user-facing and four behaviour findings are captured as nine minor records (iss-2609260552249742, iss-2609260552247395, iss-2609260552246303, iss-2609260552247252, iss-2609260552256523, iss-2609260552256401, iss-2609260552250826, iss-2609260552254288, iss-2609260552251398), and the design-record drift goes to the systematic brief pass iss-2609091956001547. Landed before the cut on the cutting session's ruling: #717 (the shell guard cluster) and #718 (the race lane's declared timeout, after #717 was ejected from the merge queue by the default ten-minute package timeout).

  • dcn-26092500000000312026-09-25

    2026-09-25 — itd-2609211913453478's acceptance criterion 4 ships under two readings the intent's scope line does not state. A glossary entry's not_to_be_confused_with passes when at least one member names a family row on the record-families page or the page itself, where the scope line says the field "may name only a family on the page"; the stricter reading would force nonsense pairs such as warm against intent, and the entries keep their real confusion pairs. The family-key rule (record_family_key, warn) reports a record frontmatter key only when the glossary already marks that word superseded or forbidden, so a brand-new grouping word with no row (the intent's own Mechanism case, e.g. an initiative: key) is not detected by construction, and the stores the page does not row (adr, rdi, dsp, rdg, adm, srp) are not reported. The six grandfathered_at_phase warnings on itd-20, 27, 28, 63, 69 and 72 are history and stay. Recorded for the product thinker to confirm or widen (autonomous run A, glossary lane review, orchestrator abcd-39).

  • dcn-26092500000000302026-09-25

    2026-09-25 — Correction to the entry above on the parked Phase 9 branch: phase-9/build holds 213 commits that main does not and lacks 905 that main has (the "213 commits behind" figure counted the wrong direction). Of the six intents it ships that main lacks, four (itd-2609041232354002, itd-2609041232363172, itd-2609041232387746, itd-2609041232398582) also exist, as planned, on the parked readings/opening-run branch; itd-2609051548103731 and itd-2609051743587375 exist only on the Phase 9 branches. The ruling itself stands unchanged (orchestrator abcd-39, autonomous run A, on the admission review's finding 4).

  • dcn-26092500000000292026-09-25

    2026-09-25 — itd-2609020625400194 (admission and surprise verbs) is delivered on main by autonomous run A's lane, built against the current main, and not by the parked phase-9/admit branch that delivered the same spec on 2026-09-04. Phase 9 stays parked on the product thinker's word of 2026-09-22 ("leave both parked workstreams"). Its build branch sits 213 commits behind main and ships six other intents that exist nowhere else, so the run neither merges nor edits it. The overlap is this one intent: when Phase 9 is unparked, its admission commits (the spec close in 30f42daa, with b0334b03, 5ca30f92 and 074dea98) are dropped or reconciled against this delivery. That reconciliation is owed to the product thinker and listed in the run's rulings-owed list. The ruling is reversible: nothing on the parked branches is touched (orchestrator abcd-39, autonomous run A).

  • dcn-26092500000000282026-09-25

    2026-09-25 — The build's open-question check reads the record's own settled convention and stays fail-closed (lane implementer, autonomous run A, fix round 1 of the loop lane, on iss-2609252053576085; the lane's first ruling, that every list item under ## Open Questions is a question whatever it says, lived only in its report and refused intents the record had settled). intent.OpenQuestions recognises exactly two markers, learned from the 12 planned intents that carry list items there. A section whose first non-blank line is an italic _All resolved …_, with at most one count word (_All four resolved …_), is settled whole (itd-111, itd-93); _All but one resolved_ is not. An item explicitly marked resolved or deferred is not a question: a bold span opening with the word (**Resolved — …**, **Deferred**, **Deferred to a follow-up intent**, **explicitly deferred**, **explicit deferral**) or the word as a label (resolved:, RESOLVED:, Deferred:), anywhere in the item including its continuation lines. Everything else stays a question: an item led **Open whatever it goes on to say (itd-60's "Open, and not gating scope"), an item that only points to another record (itd-76's "travel with itd-126"), **Out of scope …**, and a question that merely mentions deferral. With the rule, itd-111 and itd-93 pass the check; itd-7, itd-60, itd-65, itd-66, itd-76, itd-82, itd-117, itd-131, itd-2609170822093401 and itd-2609211116005482 still refuse, each on an item the record does not mark settled. Relabelling those items is the product thinker's call through the planning interview, not the loop's.

  • dcn-26092500000000272026-09-25

    2026-09-25 — The pre-commit guard's sources refresh (itd-76) finds its binary two ways until the product thinker rules on iss-2609250834251447, and the ruling may widen the second (finding 1 of the sources-lane review, adopted by the orchestrator as the safe shape). This repository's copy builds ./cmd/abcd from the checkout, as .githooks/commit-msg does, and never runs an installed abcd; a tree that does not build is one warning line and the commit proceeds. The copy abcd ahoy scaffolds refreshes only when the clone opts in with git config --local abcd.sourcesBinary <absolute path>, a path to an executable regular file with no PATH search and never an environment variable, and otherwise prints one line and proceeds. That answers none of the three questions the ruling holds (how a scaffolded hook finds abcd, fail open or closed, default or opt-in): it is the shape that leaves them open, so AC3 holds in this repository and in a managed repository that opted in. In both copies the refresh updates an existing keyed private store only, relays the binary's own line, and names a legacy store's migration once per working tree (implementer of the sources fix round).

  • dcn-26092500000000262026-09-25

    2026-09-25 — On the auto-release path the tag is still made before the release environment's approval, and that residual is recorded for the next cycle rather than built now (finding F2 of the workflows-lane review, LOW). release.yml's tag job needs verify, so a refused gate leaves no tag (iss-2608231226347380), but the job runs before the publish job waits on its human approval and before the four steps between the tag and gh release create (the vcs stamp, the archive re-verify, the two attestations). A rejected approval or a red step there leaves a tag with no Release, which the heal path then rebuilds on the next push. The closure shape: delete the tag job and create the tag as a step inside the release job, immediately before gh release create, through gh api -X POST repos/<owner>/<repo>/git/refs -f ref=refs/tags/<tag> -f sha=<commit> with the job's own GH_TOKEN, so it needs neither persist-credentials nor an extra job; a rejection or a red publish step then leaves no tag either. It also removes the auto-path half of iss-2609251125599536: once no auto-path failure can leave a tag without a Release, the only such tag is a hand-pushed one, which detect already refuses to rebuild when its own verify failed. Not built in this lane because the chain is unverifiable without a live release, and the order the lane shipped is the one the review walked (implementer of the workflows fix round).

  • dcn-26092500000000252026-09-25

    2026-09-25 — iss-2608291814575788 (the opt-in gitleaks augmentation reaches history.Capture alone) is answered by inverting the import edge, not by folding the adapter into internal/adapter/scanner as the record proposes: internal/adapter/gitleaks imports the scanner for its Finding type, so the fold is an import cycle. The scanner declares type Augmenter interface { Available() error; Scan(text, file string) []Finding } and an option WithAugmenter(Augmenter); the gitleaks adapter keeps importing the scanner and is wired at the composition root (cmd/abcd, or the core constructor that already reads the opt-in), so the scanner never imports gitleaks. ScanText and ScanBundle append the augmenter's findings and deduplicate on file, line and span. ErrConfiguredNotFound becomes one state with one consequence per consumer: launch fails closed (an Unscanned reason, and HardFails incremented), while capture, history and memory write and record the gap in their receipt. It is built in its own lane of about 150 lines, not in the scanner-cluster fix round, so the record carries a v0.10.0 deferral naming this ruling. Technical ruling by the orchestrator of autonomous run A, on the design the scanner-cluster review set out (its item 4); recorded by the implementer of lane scanner, fix round 1.

  • dcn-26092500000000242026-09-25

    2026-09-25 — The sentences of itd-2609212113220149 after its review's fix round (the implementing lane's technical rulings in autonomous run A, subject to the product thinker's review on return; recorded, not asked). A parent verb's sentence names the family's work and its write discipline, never the list of its sub-verbs, because for a top-level verb it is the description a host lists the family's plugin page by; disembark, docs, embark, guard, history, ideate and implement are reworded on that rule, and docs cite, the same shape one level down, with them. The rule is held mechanically on the doing clause alone: a parent's doing clause names no verb, while its refusing clause may still say "refuses an unknown sub-verb". cobra's help and completion stay listed under Set-up with cobra's own text, as the earlier ruling placed them, rather than hidden; the sentence gate walks the tree as it executes and exempts their six commands by name, and a test holds the name list to exactly the visible commands with no sentence. The stale-surface refusal and the snapshot drift test name each reworded sentence the way they name a moved verb. CORRECTION to this lane's report, which said the release guardrail reads a version-2 baseline from the last tag: v0.10.0 carries a version-1 surface.json, no tag carries version 2, and versions 1 to 3 are all readable; the guardrail decodes the tagged version-1 baseline end to end (implementer of lane sentences, fix round 1).

  • dcn-26092500000000232026-09-25

    2026-09-25 — How itd-2609212130136102's consolidation is built where its record leaves a choice: the implementing lane's technical rulings in autonomous run A, subject to the product thinker's review on return (recorded, not asked). The identity mode is spelt --identity, as the intent's scope names it, not --identity-check. A spelling that moved WHOLE (ahoy dry-run, ahoy identity-check, version, docs lint, site check) becomes a stub carrying cobra's Deprecated field, which lists it nowhere and keeps it out of the person's count; it accepts any argument and flag the old spelling took, runs nothing, and answers exit 2 naming its successor, with cobra's deprecation line routed to stderr so a --json caller reads exactly one refusal on stdout. A verb whose BARE form moved while its sub-verbs stay (identity, whose render and init stay; ahoy remote, whose apply stays) keeps its place and only its bare invocation answers; deprecating it would have hidden live sub-verbs. lint identity is what bare identity printed (the block and every surface's verdict), because that is the check; identity render proposes a correction, a distinct act, and stays, which reads the intent's "identity render" among the five spellings as the identity family's check (itd-146's lane read it the same way). Bare lint runs every target that judges the repository: docs, identity and the outbound policy over committed files were already rules (docs-currency, identity-positioning, privacy-hygiene), and the site joins as a site-gates rule, Where-gated on .abcd/site.json, rendering into a temporary directory outside the repository and removing it so bare lint still writes nothing, at warn severity as docs-currency is; lint outbound stays out of the bare run because its subject is text the caller hands it. version --check names update --check, the rest of version names --version; update --check prints the old version --check report, takes no tag, excludes --yes and never constructs the updater. intent new is refused as an unknown sub-verb in every shape, including before prose, so it can never be filed as a draft titled "new …". The snapshot records moved_to at schema version 4 (version 3 stays readable, the last tag's shape); the brief's appendix omits a whole-moved stub and names the successor where the bare form moved, surface_coverage needs no row for a moved spelling and refuses one that names it, and the generated CLI reference omits the stubs. commands/version.md stays as a page with no block that runs --version. The site workflow's release path probes the released binary's lint listing and falls back to site check for a tag cut before this release. The spec's remainder spec for removing the stubs is not minted: a remainder close keeps the intent planned, and the run brief closes it shipped, so the removal is captured as an issue instead (implementer of lane consolidate).

  • dcn-26092500000000222026-09-25

    2026-09-25 — How each verb's sentence is sourced and rendered (itd-2609212113220149): the implementing lane's technical rulings in autonomous run A, subject to the product thinker's review on return (recorded, not asked); decision 1 of the intent (does, writes, refuses, in that order, identical in three places, under the writing-style guide) is not reopened. The surface manifest's sentence field is a table in internal/core/surface/sentences.go, keyed by full command path, because the binary ships without .abcd/ and so cannot read the committed snapshot at run time; the front door sets every visible command's Short from it and no constructor declares one, so there is no second copy, and the snapshot records the sentence at schema version 3 with versions 2 and 1 still readable (the release guardrail reads its baseline from the last tag), and the surface diff never reads it, because a reworded sentence changes no invocation. The form is mechanical: the doing clause, a colon, a writing clause opening "Writes" (a capital after the colon, per the style guide), a semicolon, a refusing clause opening "refuses" or "never refuses", one sentence, at most 160 characters counted as characters. The three places are the command list (a parent's list, the root's groups, the agents block), the verb's own --help, which now opens with the sentence and then the long help for every verb and the root, and the plugin page's description:, the line a host lists the page by, double-quoted because every sentence carries a colon and a space; the generator writes it. A sub-verb has no page of its own, nor do changelog, rules, spec and statusline, so their places are the list and the help; a page with no verb (consult, ingest, prepare-this-repo) is not the manifest's to rewrite. Hidden commands and the framework's help and completion carry no sentence. Criterion 5 is met through the generated CLI reference, which renders every sentence as its own line under the docs lint root: the docs lint walks markdown only, so a Go table cannot be a root of its own, and a test holds each sentence to a line of that page and to the configured banned-token set. The sentences are British English although they are code strings, because they are prose rendered onto pages the docs lint reads. The count is 106 (every visible verb and sub-verb, and the root), not the fifty-three the intent names. Long help bodies are unchanged, as the intent scopes them out, including the few whose first paragraph restates the short line they replaced (implementer of lane sentences).

  • dcn-26092500000000212026-09-25

    2026-09-25 — Help placement of the verbs itd-146's decision 2 does not name: the orchestrator's technical ruling for itd-146, taken by the implementing lane of autonomous run A and subject to the product thinker's review on return (recorded, not asked). The principle applied is the intent's own: a verb goes in the block of whoever runs it, and where a verb could go either way it goes to the agents-and-hosts block, because itd-2609212130136102 AC5 caps the person's list at fourteen verbs and decision 2's thirteen (with build and drain, not yet built and left out until they are) leave room for one. People, set-up: rules (criterion 6 keeps it in the person's default list; a person inspects the rule set the loader injects, and the ahoy marker block tells them to run it), plus cobra's generated help and completion (a person runs both; itd-146 counts them apart from the verbs, "twenty visible verbs, plus help and completion", so they do not press on the fourteen; and neither has a command page an agents-block line could name). Agents and hosts, each line naming the page read next: banlist (commands/banlist.md; its lists are maintained by the agent at the person's word and enforced by the commit gate), docs (docs.md; its lint folds into lint docs under itd-2609212130136102 and cite maintains a baseline), guard (guard.md; the agent asks it before running a shell command, and guard hook is the host's adapter), ideate (ideate.md; the gauntlet runs in the host from the page, and the binary's one act is ideate record), identity (identity.md; folds into lint identity, and init runs inside prepare-this-repo), inbox (inbox.md; the session-start greeting hands it to the agent in abcd's own checkout), peers (peers.md; AGENTS.md has the agent run it before capturing, resolving or picking a record), report (report.md; the agent in a managed repository fills the template), site (site.md; build and check run in the release gate, and the check folds into lint site), version (version.md; hosts and agents read it, and it becomes --version). Decision 2's agent entries take these pages: implement, reading, history, mode their own; changelog commands/launch.md (the page that runs the cut it previews); statusline commands/ahoy.md (the page whose install wires it); guard hook guard.md; intent audit ingest intent.md; ideate record ideate.md. Group ids: set-up, records, checks, portability, release, agents. The snapshot records group and block at schema version 2, and version 1 stays readable because every release tag before this one carries it.

  • dcn-26092500000000202026-09-25

    2026-09-25 — Three further residuals of the narration hard tier, found by the round-4 verification and recorded rather than fixed (the last round on the heuristic): a comma-less fronted adverbial clause before a "no longer" main clause passes ("Once you upgrade the verb no longer writes a receipt."); the split "previously ... now" form passes across two list items, since each item is its own run; and a parenthetical between the subordinator and "no longer" is refused though it states present state ("Retry until, after a pause, the error no longer appears."). None occurs in a shipped doc body; the escape marker and the docs-lint present-tense tier are the backstop (orchestrator abcd-39, autonomous run A).

  • dcn-26092500000000192026-09-25

    2026-09-25 — The launch change-narration gate's hard tier closes its heuristic rounds with fix round 3 of lane launchgates; every gap it leaves is a residual recorded here, not another round, and the itd-65 acceptance criteria stand as written. Round 3 passes a "no longer" in a clause a subordinator opens (until, once, when, whenever, if, unless, after, before, while, whose: "retry until the error no longer appears", "branches whose upstream no longer exists"; iss-2609252045148890), and refuses the "previously … now" form split at a sentence end when one sentence opens with "previously" and the next in the same paragraph opens with "now" ("Previously, the ledger was a flat file. Now it is a folder."; iss-2609252045147575). The subordinators end a clause for the "no longer" reading alone, because "until" and "before" also open the time adverbial the "used to" reading reads through ("until v0.6 the dry-run used to skip the tags"). The residuals, each checked against the gate at the change. Passed although they narrate: "today" as the contrast word ("Previously the record lived in the log; today it lives in the ledger."); "used to" after a bare plural subject or an adverbial outside the lexicon ("Older versions used to print a banner.", "Versions before 0.6 used to write the receipt.", "Back then the tool used to print a banner.", "The dry-run, until v0.6, used to skip the tags."); a subordinator that opens a prepositional phrase or a subject's relative clause rather than the clause holding the "no longer" ("After the upgrade the verb no longer writes a receipt.", "An intent whose criteria the reviewer cannot enumerate can no longer be planned."); and the split form when "previously" does not open the first sentence or a paragraph break falls between the two ("The default was previously JSON. Now it is YAML."). Refused although it states present state: an "-ed" word within two words of a "previously" that modifies a verb ("Reviewers previously assigned are now listed first."), beside the present-state refusals the 2026-09-25 entry above names. The docs-lint present-tense tier and review are the backstop for each passed form, and the docs-lint escape, which every finding names, for each refused one. Survey at the change: 0 findings in the 15 shipped doc bodies; over every Markdown file in the tree the finding locations go from 422 to 410, 12 dropped and none added, every drop a "no longer" after a subordinator in a record, research note, brief chapter or plugin command page, one of them a genuine narration the residual above names (implementer of lane fix3-launchgates).

  • dcn-26092500000000182026-09-25

    2026-09-25 — The launch change-narration gate's hard tier refuses where the words cannot tell narration from present state, rather than passing (fix round 2 of lane launchgates, on iss-2609251940304726; the itd-65 acceptance criteria stand as written: "previously X, now Y" and a genuine "no longer" hard-fail). "no longer" is refused whatever its subject, except as a comparative ("no longer than") or in a relative clause over "is"/"are" ("files that are no longer present"); "renamed … to" is refused whenever a "to" follows before the next punctuation mark, except the present purpose form "is/are renamed to match"; "previously … now" is refused when "previously" opens its clause or a change verb stands within three words (counting words only, not punctuation or determiners); "used to" is refused as the past habit, including after a time adverbial ("until v0.6 the dry-run used to skip the tags"). The residual trade, refused although it states present state: a present passive rename other than "to match" ("the staged file is renamed to its final name"); a reduced or copula-less relative "no longer" ("files no longer present are skipped", "a seam that no longer exists"); a clause-opening "previously" beside an unrelated "now". Each takes the docs-lint escape on its line, which every finding names. Survey at the change: 0 findings in the 15 shipped doc bodies; over every Markdown file in the tree the finding locations go from 74 to 405 (333 added, all in records, research notes, agent instruction files and the changelog, outside the gate's scope; 2 dropped, each a "renamed" with no "to" after it). Rejected: a fixed list of change-subject nouns (round 1), which passed "the registry can no longer be edited" and "it was renamed to abcd lint", so a genuine narration reached a release with neither tier catching "used to" or "renamed to" (implementer of lane fix2-launchgates).

  • dcn-26092500000000172026-09-25

    2026-09-25 — Correction to the round-4 entry above on the shell guard's here-document bodies, with three further rulings (fix round 5 of lane guard, run A, closing review5-guard). Ruling (b) of that entry read an unquoted body line by line, and the round's report held that bash can only end such a body later than the guard, so the guard over-reads and never under-reads. That is false: in a body whose delimiter is unquoted, bash joins a physical line ending in an odd number of backslashes with the next line before it compares the delimiter, so x\ followed by EOF does not end the body, and ending it there read the rest as command text, where a single-quoted span or a # hid a substitution the body runs (iss-2609252214137586). A later end read with a different grammar is an under-read. The body is now read by the logical lines bash compares: joined across an odd trailing run of backslashes, for an unquoted delimiter only; an even run and a quoted delimiter join nothing, and a <<- body strips the leading tabs of the joined line alone. (a) Inside double quotes a ${…} ends at its own }, found as bash's parser finds it: a " in it opens a nested string, a ' pairs with the next ' for the parse only (the substitutions between them still run, and are followed), a bare { opens nothing. echo "${MSG:-"don't"}" and its kin, which blocked as command-unparsable after round 4, run; a ${ that never closes leaves the string as the text it was, and BLOCK stays the answer for a line the tokenizer cannot split (iss-2609252214217550). (c) A word that is wholly "$(cat <<DELIM … DELIM)", whose body the shell does not change (a quoted delimiter, or an unquoted one with no $, backtick or backslash in it), is ALSO read as the document's text wherever it is a payload (sh -c, eval, su -c, env -S), beside the unknown reading, which keeps every signal it raises: a clean document still warns as an uninspectable payload, and a hazard in the document blocks under its own entry. Replacing the unknown reading was weighed and not taken, because a cat redefined earlier in the same line would print something else, and an additive reading cannot weaken a verdict (iss-2609252214215409). (d) One more accepted over-block, named so it is not mistaken for a defect: a here-document whose delimiter is a substitution (cat <<$(echo EOF)) is not run to learn the delimiter, so no line ends the document and the line blocks as heredoc-unterminated, although bash runs it; writing the delimiter out is the way past.

  • dcn-26092500000000162026-09-25

    2026-09-25 — Correction to the two entries above on the shell guard's unknown word (fix round 4 of lane guard, run A, closing review4-guard). Over-block (2) of the round-3 entry is wider than it says: any command word whose basename ends in a substitution ($(date) x, "$(which go)" build ./..., $(command -v X) anything, /usr/bin/$(x) y) followed by any one operand blocks, because killall-by-name and pkill-by-pattern name only a program and an operand; and the verdict carried killall's own lesson ("stop it by pid"). Where the only entries a command fires are ones its unknown program name can be, the verdict is now reported under the reserved id program-name-unknown, in the substitution family, naming the entry the line reads as and the way past, spelling the program's name; the entries stay in its matches, and an entry the line does name outranks it. A narrower $(which NAME)/$(command -v NAME) reading was weighed and not taken. Three further rulings of the round. (a) A line the tokenizer cannot split is BLOCKED on the hook (command-unparsable), not failed open: where the tokenizer is right no shell runs the line either, so the block costs nothing, and where it is wrong (the $'\c' misreading this round fixed, which swallowed the string's closing quote) a fail-open is a bypass of every blocker by construction. itd-103 ac-1 names the binary failing to run, which still fails open loudly, as do an unreadable payload and a registry that will not load; the check verb keeps reporting the error as a fault (exit 2); the 961-line repository corpus holds no unparsable line. (b) An unquoted here-document body is read as bash expands it: the command substitutions in it are commands of the redirecting command's chain and its text is data, and a delimiter written with a backslash (<<\EOF, <<E\OF) is quoted, as bash reads it. (c) A ${…} in which a substitution's output lands is unknown from its ${ on, so a word that is wholly such an expansion falls under allow (1) of the round-2 entry exactly as "$(x)" does, and git push "${X:-$(echo --force)}" origin main is not seen. The plain-variable half ($X, ${X:-git}, a ${…} holding no substitution) stays iss-2609251824244354, deferred with its reason; it is not seen as the program name, as a flag, or inside a payload.

  • dcn-26092500000000152026-09-25

    2026-09-25 — Correction to the entry above on the shell guard's unknown word (fix round 3 of lane guard, run A, closing review3-guard). Its mark was not unforgeable as internal/core/guard/unknown.go claimed: an ANSI-C escape that decodes to NUL ($'\x00', $'\0', $'\u0000') put the mark into a word after Check had dropped the line's own NUL bytes, and a blocked command's name behind one allowed (iss-2609252020432185). It is unforgeable by construction now: Check drops the line's NULs, and an ANSI-C string ends at its first decoded NUL, as bash ends it. An out-of-band flag on the word was weighed and not taken, because every reader in the package holds words as strings and the change would not have been contained. The same round makes the rule total: every reader of a word or a command name reads through unknown.go, an unknown dash-word is read both as a flag that stands alone and one that takes a value (and as a shell's -c or a verb's payload flag) before command position as after it (iss-2609252020507464), and a substitution in command position is every program its known tail allows, a shell, a wrapper and git among them, which resolves the command-position half of iss-2609251824244354; that record now names only the parameter-expansion half (--$X, ${…}), still deferred with its reason, so allow (4) above is that half alone. A test parses the package and fails on a reader of a word's dash or a command's name that is not listed with how it reads the rule. Four over-blocks are accepted in the fail-closed direction, each recorded so it is not mistaken for a defect. (1) An unknown operand can be any subcommand, so a read-only command whose subcommand a substitution prints reads as the hazard its entry names: gh repo $(echo view) o/r blocks under gh-repo-delete and git $(echo status) warns under git-clean. (2) A program name nothing fixes can be pkill or killall, whose entries name nothing but the program and an operand, so an unknown name with any operand blocks under them ("$(which python3)" script.py; spelling the program's name is the way past); a markdown line whose backtick span stands in command position reads the same way, which is the only change the 4,110-line false-positive sweep showed (two prose lines, no command). (3) An unknown name followed by -c '<string>' reads the string as a shell's, so one the guard cannot parse warns as a shell payload would. (4) More than eight substitutions where a command's program name could be, and an unknown dash-word that can be env's -S with a value glued on that the guard cannot read, are refused: the first because every such name costs a read of the whole line, the second because the value is not a plain command.

  • dcn-26092500000000142026-09-25

    2026-09-25 — The shell guard's unknown-word reading and the allows it deliberately keeps (fix round 2 of lane guard, run A, closing review2-guard). What a command substitution prints is not in the command line, so the tokenizer marks where it goes and a word holding one is an unknown word (internal/core/guard/unknown.go), failing closed in every role it could play: led by a dash it is every flag its known text can still become, after a value flag it is that flag's value, and as an operand it is one operand of unknown value. Four allows stay, each named so it is not mistaken for a miss. (1) A word that is WHOLLY a substitution is read as an operand, never as a flag: that is how an everyday command spells its commit message and its branch (git commit -m "$(cat msg)", git push -u origin "$(git branch --show-current)"), and reading it as every flag would refuse both, so git push $(printf -- --force) origin main is not seen. (2) An operand's + refspec prefix is read from its known text only, for the same reason: git push origin $(echo +main:main) is not seen. (3) A commit or push after git config core.hooksPath <dir> in the same line is allowed: the guard reads configuration a command carries for itself (-c, --config-env, GIT_CONFIG_*), not configuration an earlier command writes to a file, and refusing every git config core.hooksPath would refuse the ordinary one-time hook setup a repository documents; the one-command spellings block (iss-2609251640464212). (4) Parameter expansions (--$X) and a substitution in command position are not yet unknown words; that is iss-2609251824244354, deferred with its reason. Two over-blocks are accepted in the other direction: a short flag's attached value holding a substitution (git commit -m"$(cat msg)") reads as every short flag, because the guard does not know which short options take a value; and … | xargs bash reads as a shell reading the pipe, though xargs hands it arguments.

  • dcn-26092500000000132026-09-25

    2026-09-25 — Autonomous run A defers every open capture routed to the product thinker out loud to v0.10.0, under the product thinker's directive of 2026-09-25 ("I want the ledger drained": a capture ends fixed, wontfix with its reason, closed as a duplicate, or deferred out loud where it needs a product-thinker ruling or a planning interview). The product thinker is away, so no one in the run can give those rulings. 190 records each carry deferred_after: "v0.10.0" and a deferral_reason that quotes the ruling owed verbatim. 184 of them renew a v0.9.0 grant that lapsed when v0.10.0 re-anchored, and 6 carried none. Every question is asked once in the run's rulings-owed list, grouped under the routing pass's eleven themes: A, planning interviews already ruled "plan next cycle" (27); B, confirmations owed on rulings already given (8); C, dependency and publish sign-offs (6); D, narrowing a shipped promise (4); E, principles and conventions to adopt (23); F, record schema and lint rules (34); G, security and trust design forks (16); H, autonomous runs, implement and multi-agent planning (22); I, site, docs voice and product story (17); J, future capabilities to plan or close (27); K, parked on a trigger, or a human act outside the tree (6). Within each theme the questions covering a major record come first, and the list is the agenda for the next interview. The same pass closes 9 duplicates and 44 captures on their recorded merits, so none of those is deferred (implementer of lane records1).

  • dcn-26092500000000122026-09-25

    2026-09-25 — The load check's stray rule is "busy for its share" (ruling H1, the product thinker via the interview session, 07:57Z, on iss-2609231947544298). A long-running process outside abcd's lanes is a stray when it uses nearly all the CPU it could get on the machine as loaded: its lifetime CPU share is measured against its fair share, the online cores divided by the runnable demand, not against a fixed 0.9 of one core, so forty busy loops each at a fortieth of the machine all count. The share test applies to the caller's own processes and to other accounts' alike, and other accounts' strays stay counted only. It is not a second sample and not a summed-cores trigger. The build reads the runnable demand as the snapshot's one-minute load average and caps the fair share at one core, so on a machine loaded no higher than its cores the rule is the near-full core it was (machineload.FairShare, spc-2609232027132755). This closes the band between 1.125 and 4 times the cores in which the check said nothing (pinned by TestStrayRuleSilentBand, succeeded by TestStrayRuleCoversTheOversubscribedBand), and lets the load check's remainder spec close and itd-2609231434459890 ship. The check still warns and never refuses (the 2026-09-23 entry above on that intent).

  • dcn-26092500000000112026-09-25

    2026-09-25 — iss-2609251522588539 (the foreign-uid paragraph overstated the refusal) is deferred past v0.10.0 with its wording corrected (lane implementer, autonomous run A, fix round 1, after the tier2 review's finding 7). AGENTS.md and the marker block ahoy writes now say the refusal bounds the walk and a .abcd/ at the working directory is still read. Making that read refuse too is the posture change on the unmerged branch feat/ruled-security-forks (da3efea6: an empty root with PerRepo false, refused by every loader), which touches the rules loader, the guard and the banlist; a second, partial form of it in a fix round would diverge from that branch rather than land it. The capture carries deferred_after: v0.10.0 and returns at the next anchor.

  • dcn-26092500000000102026-09-25

    2026-09-25 — The request spec close emits when it ships an intent carries the ## Routing section intent audit <itd-N> writes; an unreadable routing table does not refuse the close (lane implementer, autonomous run A, fix round 1 on spc-2609180535002478, after the tier2 review's finding 3). The route is a front-door fact, so the core close still emits the request without it and the front door re-emits the owed request with the section once the intent-auditor's route resolves, with the same one-line fallback on stderr. The close is a record move and its emit is report-only (a failed emit already leaves the intent shipped), so a table that cannot be read leaves that request without the section and one stderr warning names the fault and abcd intent audit <itd-N> as the re-emit; refusing the close over a file only its report-only step reads would block the record on the wrong thing. The close carries no --route and no routing member in its result: it is not a delegating verb, and intent audit <itd-N> is the documented way to hand the auditor its request.

  • dcn-26092500000000092026-09-25

    2026-09-25 — One --route per delegating invocation, for the one agent it dispatches; a --route naming any other agent is refused before anything runs, never merged and never ignored (lane implementer, autonomous run A, fix round 1 on spc-2609180535002478, after the tier2 review's finding 1). AC 7 of itd-2609170822093401 says a second --route for a different agent "applies alongside" the first, and the closed spec's plan said it merges. Every delegating invocation dispatches exactly one agent (a dual-mode verb in its payload mode, or reading ingest for the position its output names), so a second agent has no step to apply to: merging would record an override nothing used, and ignoring it would let a mistyped agent name read as honoured. The refusal speaks of the invocation, not the verb ("this invocation dispatches <agent>, not <other>"), because reading ingest registers all four positions and dispatches one per output. The flag's help and the four command pages say one per invocation instead of "repeatable". A verb that one day dispatches two agents in one invocation passes both to ParseRoutes and gets AC 7's "alongside" as written.

  • dcn-26092500000000082026-09-25

    2026-09-25 — Three shape rulings for the model-tier routing's surface (lane implementer, autonomous run A, on spc-2609180535002478 part 2). First, --route sits on the seven verbs whose step an agent in the agents/ roster runs: intent audit and its ingest, launch ship, disembark review, principles, press-release and graveyard, and reading ingest. The spec listed memory ingest as an eighth, but its distiller is the host session itself (commands/memory.md), not a roster agent, so no row could govern it and a flag there could only refuse; it gains the flag when a roster agent takes that step. A dual-mode verb's deterministic mode dispatches no agent, reads no routing table and refuses --route. Second, the receipt is the ingest's result: a route member in its JSON and a route: line in its text. It is not a new field in any durable record, because each verb's durable record differs (a CHANGELOG, a lifeboat file, an intent's Audit Notes, a reading run) and a routing fact belongs in none of them; the request block is likewise a routing member on the steps that precede an agent (intent audit <itd-N>, a ready launch ship cut), plus a ## Routing section in the audit's request document outside the hashed prompt. Third, a routing table that cannot be read refuses a delegating verb at exit 2, where the bare board only omits its lines: the verb is about to ask for a model, and the loud-staging rule does not let it guess past the file that decides which.

  • dcn-26092500000000072026-09-25

    2026-09-25 — Every claimant of a shared namespace in .abcd/config.json lists the union of the keys any writer puts there, not only the keys it reads itself (lane implementer, autonomous run A, on the tier1 review's finding 3; this adds to the entry above on the layered resolver and does not amend it). Stack.Claim holds no registry across callers: each claim refuses every key it does not list, so two claimants listing different subsets each refuse the other's file. For the oracle namespace the union today is backend (written by ahoy install), review (itd-6's reviewer route) and rp (itd-6's oracle.rp.mcp_config_path, which ahoy's setup discovery writes), so itd-6's claimant calls Claim("oracle", "backend", "review", "rp"), and a key a later writer adds under oracle is added to every claimant in the same change. Separately, the ceiling of 1 recorded above makes a routing row's fan_out inert today: every value either equals the ceiling or is clamped to it, and the field only bites once an agent contract declares a ceiling above 1.

  • dcn-26092500000000062026-09-25

    2026-09-25 — Two rulings for the model-tier routing table, which the spec leaves open (lane implementer, autonomous run A, on spc-2609180535002478 part 1). First, a table is accepted when a routing file exists at the repository or the machine layer. Only then does the bundled proposal fill in an agent the table has no row for; with neither file, every agent resolves to none, the harness at host-decides, as AC 1 and the spec's criteria section say. A --route alone accepts nothing: it overrides the one agent it names for one run. Second, no agent contract under agents/ declares a fan-out ceiling, and every agent in the roster is a single prompt that spawns no sub-agent, so each ceiling is 1. The proposal carries it (oracle.Ceiling), and a row's fan_out above it is reported and clamped. The roster test holds the proposal to agents/, so an agent that gains a ceiling field moves the number there.

  • dcn-26092500000000052026-09-25

    2026-09-25 — The layered configuration resolver has one home, internal/core/layered, and two file families; every later consumer reads through it rather than opening a file of its own (lane implementer, autonomous run A, on spc-2609180535002478 part 1). Precedence is flag, then repository, then machine, then bundled, and every value comes back with the layer and the origin that supplied it. The families are layered.Config, which is .abcd/config.json in the checkout the session resolved and ~/.abcd/config.json on the machine, and layered.OracleRouting, which is .abcd/config/oracle-routing.json and ~/.abcd/oracle-routing.json, the files itd-2609170822093401 names. Scalar keys go in Config under a namespace: pace.* (itd-2609201925079472), oracle.review (itd-6), roles.<role>.runner (itd-2609201916056194) and match.threshold (itd-2609212137116617). The per-agent routing table keeps its own file, as its intent names, and no new file family is added without an entry here. Loudness: an absent file is an absent layer; a present file that is malformed, symlinked, carries a key twice, trails content, declares the wrong schema_version, or (machine layer) is not the caller's own owner-only-writable file is an error naming it; a consumer claims its namespace and every key in it (Stack.Claim, with * for an open segment such as the role name), and an unknown key under a claimed namespace is refused. Because ahoy writes oracle.backend into the shared file, whoever claims oracle lists backend too. A winning value that does not decode or fails its check is refused, and nothing falls through to a lower layer or to the default.

  • dcn-26092500000000042026-09-25

    2026-09-25 — Reach of the push-receipt entry above, stated after review (iss-2608210738378295). The receipt's clean-tree test is git status read when the preflight begins and when it ends, and a tree git status cannot see is not vouched for. So scripts/preflight-receipt.sh also refuses to mint while any tracked file is flagged skip-worktree or assume-unchanged (git ls-files -v tags it S or in lower case), because either flag hides that file's edits from the status read; a sparse checkout sets skip-worktree and so never mints. What the receipt still cannot see, stated in the script's header: files git ignores, which are outside the commit yet can be read by a gate (a go.work, which .gitignore lists, changes every Go gate's module resolution); HEAD moved and moved back, or the tree changed and restored, between the two reads; and anything a gate reads from outside the checkout. The receipt stays a local convenience gate and CI the authority; closing those would mean running the gates on a clean export of HEAD, the alternative the entry above did not take (lane hooks fix round, autonomous run A).

  • dcn-26092500000000032026-09-25

    2026-09-25 — A push is gated before it opens its connection, by receipt (iss-2608290810036869, iss-2608210738378295; product thinker's ruling M16 of 2026-09-23, "check before connect"). The committed .githooks/pre-push no longer runs make preflight: git opens the connection before the hook, and a preflight inside it outlasted the transport's idle timeout, so a push reported success and moved nothing. make preflight ends by minting a receipt for HEAD under the checkout's local tier (scripts/preflight-receipt.sh), and only when the working tree matched HEAD (nothing staged, unstaged or untracked) both when the run began, read while the Makefile is parsed, and when it ended, with HEAD unmoved, so the gates read the tree CI checks out. The hook refuses a push whose commit is new to the remote and carries no receipt from any worktree of the repository; a commit the remote already holds (a tag on a merged commit) passes. Alternatives not taken: a push wrapper that runs the preflight and then git push --no-verify (it normalises --no-verify, and a plain git push would go ungated); keepalive settings on the transport (the hook would still hold the connection for ten minutes); a preflight on a clean export of HEAD (a second full tree and build per push, where refusing a divergent tree costs nothing). git push --no-verify skips the hook exactly as before, and CI stays the authority (lane hooks, autonomous run A).

  • dcn-26092500000000022026-09-25

    2026-09-25 — A scope condition's standing is folded by source precedence, not by position, and a re-ingest for an INGESTED receipt whose payload renders differently replaces the ingested verdict (run A orchestrator, ruling on finding 1 of the lane review of itd-2609020625405251 / spc-2609020626046252, branch feat/scope-condition-verb). The spec's fold took the last disposition in document order, on the premise that both writers append; the verdict ingest does not, since it replaces the receipt's OWED stub in place and the stub is parked at ship time, so on every record the writers produce a verdict ingested after a condition block sits above it, and a same-receipt re-ingest was a noop whatever it carried. The documented override (a verdict whose rationale names the occasion) was therefore unreachable. The ruling: (1) a verdict entry replaces a condition entry iff its rationale names that condition's occasion, wherever either sits; condition blocks among themselves, and verdict blocks among themselves, keep document order; consequently a verdict that has named an occasion keeps overriding a later block written for that same occasion, and a researcher re-dispositioning after it cites a new occasion. (2) A re-ingest whose payload renders to the block already on the record stays a noop; one that renders differently replaces it in place after the first ingest's checks; one that does not validate is refused with nothing written, never dead-lettered over a verdict already ingested. No recorded decision makes the ingest write-once: itd-80's ac-5 ("ingest runs again with the same receipt_id … is a no-op: ## Audit Notes is not duplicated") is an acceptance criterion whose stated property, one block per receipt and no duplication, the replacement keeps, and TestIngestIdempotentNoOp still holds. The closed spec carries a dated correction in place. Separately, the lane's commit bumping cold-reading-detection to 0.1.3 while editing itd-199's markers says readings are pinned to an earlier commit; this tree cannot show that pin, and needs none: no study in this repository is mid-flight, because the reading workstream lives in the research fork (the 2026-09-23 entry above on iss-2609021857343626). History is not rewritten.

  • dcn-26092500000000012026-09-25

    2026-09-25 — One fence rule for the tree (the run A orchestrator's technical ruling for the fences lane, recorded by the lane implementer). internal/core/mdrecord is the tree's one notion of fences and HTML comments: Mask and Unclosed follow CommonMark for a top-level fence, and Read(lines, rule) is the single pass every reading goes through. It is extended once, by a Rule: TopLevel is CommonMark's top level, and ListNested also opens a fence indented four or more columns, which only a list item can hold, closes it within three columns of its opener, and ends it at a column-0 line (fenced code never continues lazily). A run at one to three columns is read by ListNested exactly as TopLevel reads it, because whether it sits in a list item turns on the list around it and mdrecord does not parse lists; a committed issue record quotes a frontmatter block in a top-level fence whose indented closer is followed by a column-0 line, and the list-item reading refused it. That reading is kept unexported and consulted by FencedUnderEveryRule, which masks a line only where every reading agrees. The site reads ListNested (it renders fences in list items) with comments masked and refuses an unclosed fence or comment; the lint rules read FencedUnderEveryRule with comments left visible, because a mask that hides prose misses a finding silently. The reading exclusion floor fails closed: its verifier does not share the redactor's site walk, reads a line as code only where every reading agrees, lets no comment hide a heading (comment text travels in the bundle, so an excluded heading inside a comment is refused, not redacted by guess), and refuses a fence either rule leaves unclosed. TestNoSecondFenceRule in mdrecord is the armed guard: it names any non-test Go file that writes a fence delimiter and keeps state across lines, its allowlist is empty, and a stale entry fails it. Captures resolved on this ruling: iss-2609250955207041, iss-2609250955051598, iss-2609250955209513, iss-2609251044055902, iss-2609251045302499.

  • dcn-26092400000000042026-09-24

    2026-09-24 — v0.10.0 is published. PR #693 merged as 1ac8b3a0, and auto-release run 35963282477 tagged it. The release environment was approved under ruling A2 once all 30 checks on the tagged commit had settled (25 success, 5 skipped by design). The release was published at 2026-09-24T06:33:10Z with four binaries, checksums.txt, the plugin archive abcd-plugin-v0.10.0.zip (its sha256 equals the marketplace pin, 1ab2acd1…) and the rendered site, which was deployed. Verified locally afterwards: the darwin-arm64 binary's checksum and its build attestation, and the binary reports v0.10.0.

  • dcn-26092400000000032026-09-24

    2026-09-24 — Release v0.10.0 is cut by autonomous run A, and the run's agenda line is: approve the publish step. Under ruling A2 of the product thinker's run A interview (2026-09-23 07:52Z, "approve the publish step": the product thinker authorises the run to approve the release environment itself once every gate is green), the run approves the release environment's deployment of v0.10.0 only after the merge queue, the verify job and every other gate on the tagged commit report green, and stops with a handover instead if any does not. The cut: v0.10.0, impact breaking, 43 records since v0.9.0 (nine shipped intents, thirty-four resolved or declined issues, four of them breaking), content commit 64ea8f62, the composer's payload accepted on the first ingest and recomposed once for two docs-currency findings. Both semantic gates ran at tier full: docs-currency-reviewer (Fable 5.1) with three findings, two fixed and one deferred because the load check's intent stays planned pending the product thinker's ruling on the stray definition (iss-2609231947544298); the brief-surface cross-check (40 pinned checkers, Opus 5.5, four at a time under the run's ceiling) with 154 findings, all deferred to their records: four user-facing ones captured as iss-2609240519413467, iss-2609240519418856, iss-2609240519471816 and iss-2609240519427388, one inside an appendix chapter captured as iss-2609240519422232, which records itd-147's ac-6 as not met, and the design-record drift to the systematic brief pass iss-2609091956001547.

  • dcn-26092400000000022026-09-24

    2026-09-24 — Correction to the entry above on the 02:02Z ruling: the clause "a fork of an agent is still an agent" is not part of the product thinker's ruling. It is the run's own lane rule for autonomous run A, which counts a fork toward the ceiling because a fork is an agent alive. The ruling itself is the rest of that entry: no pauses, a ceiling of four sub-agents in any mix of roles, and rotation at about 60% of context unchanged (lane implementer, on review of the followup lane; the ledger is append-only, so the entry above stands as written).

  • dcn-26092400000000012026-09-24

    2026-09-24 — An autonomous run works continuously, with no pauses, and keeps at most four sub-agents alive at once, in any mix of roles (product thinker, directly at 02:02Z, relayed to the run A lanes by the run's first orchestrator session). There are no sleep windows: this supersedes the three-hour windows with a two-hour pause recorded above at 09:28Z on 2026-09-23. The ceiling of four supersedes the ceiling of six recorded above at 14:10Z on 2026-09-23; a fork of an agent is still an agent. The orchestrator still rotates to a fresh session at about 60% of its context.

  • dcn-26092300000000232026-09-23

    2026-09-23 — The payload example in spc-2609231435545473 (closed) is stale on one point: its itd-121 quote opens "... what I'd do next,", a truncation the release-page ingest refuses by design, since a quote is a whole quoted sentence as the press release has it. The example's verb is right: the ingest accepts an attribution after says as well as after said, because six intents of that release (itd-119, itd-120, itd-121, itd-123, itd-124, itd-125) quote as says <Name>, <role>.. The closed spec stays as written; TestQuoteSaysFormFromARealRecord carries a working says quote, taken from itd-121 as its record has it (lane implementer, on review 2 of the release-page build).

  • dcn-26092300000000222026-09-23

    2026-09-23 — An autonomous run keeps at most six sub-agents alive at once, in any mix of roles, from the run's session 3 on (product thinker, directly to the run A session at 14:10Z; supersedes the ceiling of five recorded above at 09:09Z).

  • dcn-26092300000000212026-09-23

    2026-09-23 — The load check before abcd's own test lanes warns and never refuses (product thinker, planning interview for itd-2609231434459890; spc-2609231542463113, Decision 2). This changes the fourth condition of the run A interview ruling on iss-2609210828122412, which had the check refusing. The check names foreign sustained CPU (a near-full core for longer than 30 minutes) and an extreme load (four times the online cores), both limits overridable in the caller's ~/.abcd/load-limits; it names the caller's own strays with a remedy and counts other accounts' processes without naming them; it writes a run-log event; it runs once at the start of make preflight and of the eval harness; CI skips it with a stated reason; it always exits 0, and its findings are minor.

  • dcn-26092300000000202026-09-23

    2026-09-23 — Three rulings from the product thinker's run A interview, 14:38Z to 14:41Z, on items F and G. F, abcd's name in an adopted repository's two name-guard hooks and its .gitignore fence (iss-2609231103413459): the 2026-09-11 ruling that the install does not write abcd by name into a target repository (iss-2609110944498549) covers them, but they are its sanctioned exception. The hooks run the binary and the fence tells people not to hand-edit it, so both keep their markers and naming as the one allowed mention of abcd in an adopted repository, with no rename and no migration; whether the record ids in the hook prose count as part of that mention is left to check, since the ruling named the markers, not the ids. G1, the em-dash-in-list-item house-style token in a prepared repository's docs lint: it is offered at install and the adopter chooses whether it blocks or warns, in the product thinker's words "It's offered at abcd install. the user chosen: Either blocking or warning"; not "off". An unattended (--yes) install seeds it as a warning (the 14:41Z follow-up). The run settled what the ruling left open: a bare Enter or end of input takes the displayed default, the warning; an answer naming neither choice, such as the y a piped yes sends, seeds the warning and the install result says what was heard rather than guessing a gate; the chosen severity is recorded as the token's severity in the seeded config itself; and the question is asked only when that config is being created, so a repository with its own config keeps its severity. G2, docs lint with nothing checked: warn, do not fail. The exit status stays 0, since an exit 2 would turn red the CI of every repository prepared before its config carried rules, and the run prints a loud warning that nothing was checked and why (no rule armed, or roots that hold no markdown document), on stderr and in the JSON envelope.

  • dcn-26092300000000192026-09-23

    2026-09-23 — The one sanctioned mention of abcd in an adopted repository (product thinker, ruling F of the run A interview, 14:38Z, on iss-2609231103413459). The 2026-09-11 ruling that ahoy install must not write abcd by name into a repository it adopts (carried by iss-2609110944498549) covers the name-guard hooks (.githooks/pre-commit, .githooks/pre-merge-commit) and the .gitignore fence, and they are its sanctioned exception: both keep their markers and their naming, documented as the one allowed mention of abcd in an adopted repository, because the hooks run the binary and the fence tells people not to hand-edit it. No rename and no migration: detection classifies an adopted repository by exactly that hook marker and fence, so a rename would have to migrate every repository already adopted. The product thinker ruled the markers, not abcd's record ids: the hook templates' citations of abcd's own records (itd-74, spc-20, itd-150, iss-370, and a path into the design record) resolve to nothing in an adopter's repository, so they are dropped from the templates and a test keeps them out. iss-2609231103413459 closes as wontfix on this ruling.

  • dcn-26092300000000182026-09-23

    2026-09-23 — The two rulings that close how a release reaches /plugin update (product thinker, rulings E4 and E5 of the run A interview, 10:23Z and 10:27Z), recorded beside the build they govern; the E1 to E3 entry left E4 owed. E4, the contributor entry, 10:23Z: there is no second, development entry in the marketplace catalog. The public listing carries the pinned release archive alone, and contributors load the plugin from their own checkout, a step documented for contributors only (CONTRIBUTING.md), never in the user docs. E5, binary upgrade integrity, raised by the product thinker in E1, 10:27Z: abcd update verifies a downloaded binary only against the same release's checksums.txt, which catches corruption but not a release page whose binary and checksums were both replaced. A check independent of that release, such as a digest committed in the repository's history or a signed build attestation (a new verification dependency needs sign-off), is next-cycle work; this release keeps the same-page check. It is captured as iss-2609231050273096, deferred past v0.9.0 with this ruling as its reason.

  • dcn-26092300000000172026-09-23

    2026-09-23 — Two corrections to the entry above recording itd-4 AC3 built as ruled, appended because the ledger is append-only. (1) Decision (5) says the drift check is not wired into preflight or CI. That contradicts the criterion it delivers, which says drift detection is ENFORCED, so it is wired: make issue-drift runs abcd intent audit --issue-drift --strict as a make preflight prerequisite, and the CI check job runs the same line on its Linux leg. A promote join that stops reading the same from both ends now fails the pre-push gate and CI. (2) Decision (6) is narrowed: the (historical) marker goes on the authored passages, never inside an INGESTED Audit Notes block, because an audit receipt is written only by the ingest. The retired-promote-back-links ban exempts those receipt lines by the line shapes the ingest renders (a per-criterion verdict, a scope-condition disposition, an evidence pointer), and it exempts the two gap-audit claims that name a retired key by their own text, since a gap-audit claim is a bare nested bullet and exempting that shape would also exempt live prose.

  • dcn-26092300000000162026-09-23

    2026-09-23 — itd-4 AC3 built as ruled (B3): the promote join's back-links are related_issues on the intent and related_intents on the ledger record, and abcd intent audit --issue-drift checks them. Seven implementation decisions the ruling left open, taken by the implementing lane. (1) No reader tolerates the retired promoted_to / promoted_from: the ledger reader refuses and skips a record carrying promoted_to, the intent reader ignores promoted_from, and a promote write meeting either refuses. The refusal, the record gate's finding and the drift finding each name the successor and the remedy, abcd capture migrate --apply, a verb that reports by default, writes only with --apply, and is idempotent. It is a verb and not a one-off script because managed repositories hold the same retired names and need the same repair. (2) "Promoted" is the PAIR, an intent in the record's related_intents that names the record back in its related_issues, because an issue's related_intents already carried loose relations before the rename and still does; the double-promote refusal and the record page's next move read the pair. So the migration completes a join an older abcd wrote from one end only (iss-327 and itd-93, iss-2609091642508005 and itd-2609111003026787), or those records would stop reading as promoted. (3) Link mode on the issue route writes both halves; before the rename it stamped the issue alone, which left a hand-filed draft with no edge back. (4) related_issues holds rdi-N as well as iss-N: a reading item lives in the issue ledger's tree and graduates the same way, and one key per side keeps the join one shape. The first entry is the record the intent was promoted from; a later link appends, so back_edge_kept still reports the first. (5) The drift check reports an intent naming a record that does not name it back, but not an ISSUE naming an intent that does not name it back, since that is a loose relation; a reading item carries no loose relation, so from its end a one-way stamp is drift. A shipped intent naming an issue in wontfix/ is drift, like one in open/, because the itd-4 scope asks whether the issue "actually moved to resolved/". The check is not wired into preflight or CI; --strict is there for whoever wires it. (6) The historical passages in shipped intents, closed specs and adr-0057 carry a (historical) marker beside the retired names, the precedent development/activity set, so the new retired-promote-back-links ban can gate every current record. (7) The impact is breaking: itd-4 declares none, and the rename removes promoted_to from capture list --json, promoted_from from the intent JSON and both link keys from the record page, and makes an unmigrated ledger unreadable until the migration runs.

  • dcn-26092300000000152026-09-23

    2026-09-23 — How a release reaches /plugin update (product thinker, rulings E1 to E3 of the run A interview, 09:50Z to 10:13Z). This supersedes the interview entry's "no criterion amended" for the version-stamped plugin payloads. E1, the form, 09:50Z: a pinned archive. release.yml renders the plugin payload reproducibly as abcd-plugin-vX.zip, the ship pull request commits the marketplace entry with that release's URL and sha256, and release verify refuses a digest mismatch. The product thinker's stated want, in their words: "the user should get the latest cut release from github; verified as such and fingerprinted through a hash". The window between the ship merge and the asset upload, when the listing may name a zip not yet published, is to be confirmed and then closed or documented. E2, the amendments, 09:55Z: itd-67's first acceptance criterion is amended from source ./ to a pinned archive source, and an ADR minted with abcd decide amends adr-19 and adr-20 so that the default branch's marketplace.json carries the latest release's URL and sha256 while the plugin.json version stays out of the working tree; both land with the build, each saying why, with no review before the build. E3, the harness floor, 10:13Z: Claude Code v2.1.224, the minimum the archive source needs, is accepted and stated in the install instructions and the release notes; no install-time detection is asked for. E4 owed: whether contributors keep a source-./ development entry once installs stop following the default branch, and under what name.

  • dcn-26092300000000142026-09-23

    2026-09-23 — Four corrections to the entries of 2026-09-23 above that record the product thinker's run A interview, appended because the ledger is append-only and its gate refuses an in-place edit even of an entry that has not reached the default branch. (1) The interview entry leaves out a clause of ruling B4: itd-43 ships in the next release, so the next cut announces it. That stands against AGENTS.md's rule that a record closed for work an earlier release already carried is stamped shipped_in: with that release, since v0.2.0's changelog already named the GL002 gate (itd-43); the product thinker's ruling resolves the tension, so itd-43 carries no shipped_in: stamp and the next release's changelog names it. (2) In the ceiling entry, the sentence "A fork of an agent is an agent, so a lane does not fork itself to get under it" is the run's own rule for its lanes, not part of the product thinker's ruling. (3) In the proxy-gate entry, a gate that measures a proxy, or exempts the cases that matter, withdraws vigilance more thoroughly than a phantom gate does, as enforcement-claims-are-facts and iss-2608230847432286 say, not "just as" a phantom gate does. (4) In the cold-reading fork entry, the closing sentence "The code that ships here is unaffected by the move" is not part of the ruling and is withdrawn.

  • dcn-26092300000000132026-09-23

    2026-09-23 — A load experiment is trusted only under four conditions (product thinker, ruling on iss-2609210828122412, after orphaned load processes from another repository starved the machine into a crash): background load processes start as one owned process group and are killed together; "clean" is proven by checking what is actually running, never by reading a list of what was started; an experiment on a live development machine needs explicit consent and a cap below the core count; and abcd's own test lanes check machine load before they start and refuse when it is too high, naming what is running. The first three hold as rules now; the last is an intent to plan.

  • dcn-26092300000000122026-09-23

    2026-09-23 — "At every refusal, emit what the tool knows" is a principle (product thinker, ruling on iss-2609100509531349, grading the claim that record from the 2026-09-09/10 field run made): a refusal names the allowed values, the value it had, and the condition it checked. It lives at principles/at-every-refusal-emit-what-the-tool-knows.md. Five open records are breaches of it (iss-2608290810037524, iss-2609100506265392, iss-2608270559313719, iss-2609100508570527, iss-2609100508566033), and the record that proposed it is resolved by the promotion.

  • dcn-26092300000000112026-09-23

    2026-09-23 — Agent guidance that walks a person through a third party's interface carries a verification tag, observed on screen in this session or taken unverified from the vendor's documentation, and asks for a screenshot before a second guess, or reads the page itself where it can; and every redaction rule states its purpose (product thinker, ruling on iss-2609100506256173, adopting both halves). Its home is the managed-repository agent conventions or a principle, still to be written; this entry is the ruling until then.

  • dcn-26092300000000102026-09-23

    2026-09-23 — The four typed relations decompose-before-filing mandates are all supported (product thinker, ruling on iss-2609091256264547, choosing to build over narrowing the rule or sanctioning prose): reverses, duplicates and refines become real typed record fields in the schema and in every reader, beside supersedes. Until that lands, those relations are written in prose, the 2026-09-09 practice, because a typed field the readers do not know hides the record from them. Needs planning.

  • dcn-26092300000000092026-09-23

    2026-09-23 — The cold-reading research workstream lives in a separate fork, not in this repository, so its open rulings are taken there (product thinker, ruling on iss-2609021857343626, the reading of "at the target" in adr-2609021016272867's comparative derivation). That record is closed here as out of scope for this repository, naming the fork as its home. The code that ships here is unaffected by the move.

  • dcn-26092300000000082026-09-23

    2026-09-23 — Delivered work states the verification rung it was checked at, and a project whose blast radius reaches strangers declares that radius before it may lower the rung (product thinker, ruling on iss-2608290944122400). This answers the question rfc-3 names as the one it most needs answered, and rfc-3 records it; the RFC stays open on its other questions, so there is no ADR yet. The carriers are itd-173 and itd-176, both drafts.

  • dcn-26092300000000072026-09-23

    2026-09-23 — The changelog-as-index ruling of 2026-08-26 includes stale closures (product thinker, ruling on iss-2608260941298050): every terminal transition gets a changelog line, principles and ADRs included and internal no longer silenced, and so does an issue closed with no fixing commit. Planned next cycle as its own intent.

  • dcn-26092300000000062026-09-23

    2026-09-23 — The resolution field of a resolved issue gets two detectors, in order (product thinker, ruling on iss-2608250844259345): first a co-edit rule, under which a body change on a resolved record requires a resolution change in the same commit; later, as a second layer, a detector for a resolution that contradicts its body. Both belong to one intent, planned next cycle, for the three unwatched edges of issue resolution, with the inverse open-record detector (iss-2608241612007530) and audit verdicts that never reach resolved issues (iss-2608261635558358).

  • dcn-26092300000000052026-09-23

    2026-09-23 — abcd lint becomes a merge-blocking gate on a narrow, high-precision subset of its findings, and every other finding stays advisory in the same run (product thinker, ruling on iss-2608231000561060; the example given is a real personal home-folder path). The facilitator proposes the blocking set, judged against the current privacy-hygiene errors, and the product thinker confirms it. Until the gate runs, the record's claim that the lint gates CI is not a fact.

  • dcn-26092300000000042026-09-23

    2026-09-23 — The proxy-gate class joins enforcement-claims-are-facts as one paragraph, not as a sibling principle (product thinker, ruling on iss-2608230847432286; one-canonical-primitive): a gate that runs and reports green is evidence only for the property it measures over the subjects it measures, so a gate that measures a proxy, or exempts the cases that matter, withdraws vigilance just as a phantom gate does, and an exemption from a gate carries the gate's own burden of proof. Detectors for the class are commissioned and need planning; itd-147 already cites the class. The adjacent sampling case (iss-2608230817034768), an assurance nobody issued but a reader inferred, is NOT admitted, because it would remove the class's boundary.

  • dcn-26092300000000032026-09-23

    2026-09-23 — An autonomous run works in three-hour windows with a two-hour pause after each (product thinker, directly to the run A session at 09:28Z; supersedes two hours on and five off).

  • dcn-26092300000000022026-09-23

    2026-09-23 — An autonomous run keeps at most five sub-agents alive at once, in any mix of roles (product thinker, directly to the run A session at 09:09Z; supersedes the run's ceiling of 2026-09-22). A fork of an agent is an agent, so a lane does not fork itself to get under it.

  • dcn-26092300000000012026-09-23

    2026-09-23 — The product thinker ruled on the owed items of the autonomous run of 2026-09-23 in one interview, one question at a time (07:51Z to 09:32Z, while the run was paused): two release blockers, two intents, the 35 major captures routed to the product thinker, and two older owed rulings. The release waits for two things: version-stamped plugin payloads (iss-2609230733497536, built by a run lane, with no criterion amended and no deferral) and a release press release composed at the cut from the shipped intents' press releases, which is a new capability and gets an intent and its planning interview before any lane builds it. The run may approve the release environment itself once every gate is green; that agenda line is written in the release commit, not here. itd-4's AC3 is built as written, the --issue-drift check and the rename of the back-links to related_issues / related_intents together, and spc-6 closes only when both land (the 2026-07-17 ruling stands). itd-43's third criterion is moot and dropped, so spc-8 closes. The guard contract is extended to read a host-supplied per-call working directory (iss-2609212142557657, option A), after a probe of what the host does when none is supplied. Four majors are ruled to a build (iss-2608231120121681 write-path smoke, iss-2608290810036869 preflight before the push connects, iss-2609090828371674 per-agent staging locks, iss-2609120505141653 the provenance comment) and do not hold the tag. The rulings that set a rule each have their own entry below; every other routed major is deferred past v0.9.0 with its ruling as the deferral_reason, and the 168 routed minor and nitpick captures take the run's default deferral. The product thinker also asked that the interview be kept as autonomous-run experiment data, towards making a run transparent to the person it serves; the observations feed the run's end-of-run research note. Rejected, as the frame: the run taking any of these rulings itself.

  • dcn-26092200000000042026-09-22

    2026-09-22 — Two intents the product thinker added for the autonomous run of 2026-09-23, interviewed and planned the night before (both READY, both in the run's batch 1b). A managed repository reports back to abcd (itd-2609221656361680): one verb files a written account against an abcd-issued template with a machine-readable block beside the prose, into an inbox in the user account's machine store, never in either repository's tree; abcd says at its next start how many wait and from how many repositories; a read-only verb renders them naming the sender; nothing is filed until a person or a session acts, and what is filed carries the sender's root-commit fingerprint and a generic description, never its name. Two sessions share one run (itd-2609221656373558): the second joins without a word from the first and the first never waits on it; all three division modes are tried, one per window in order (a claim per record, whole batches, build against review-and-land), because the product thinker wants each measured rather than one chosen in advance; a claim is an atomic create with a lease that lapses; the second session holds at most one lane, may never cut a release or take a lane that recalibrates the reading corpus, backs off on contention with a logged reason, and its stop conditions stop only itself; the run's report compares the three modes on lanes landed, wall clock, collisions and agent minutes. Cross-account and cross-machine agent communication stays out of the run: the four drafts (itd-33, itd-2609151838312703, itd-2609151838327688, itd-2609150819440345) get planning briefs only, with the trust question a shared mailbox raises named in the brief.

  • dcn-26092200000000032026-09-22

    2026-09-22 — The control-programme idea is REFRAMED, not adopted as put (product thinker, after the ideate gauntlet; research/notes/2026-09-22-ideate-abcd-operator-console.md). Two kill attempts were fatal to the idea as stated: it named the product thinker as the configurer of operator-register material, which adr-2609151528057260 bars, and it made harness-less operation the destination, inverting the host-delegated boundary whose reversal itd-2609201916151817 records as opt-in only. The reframing, adopted: an operator console SERVED BY THE BINARY over local web (no new dependency), which is also the resident process that hosts the opt-in process driver, with a separate product-thinker pane in their own register (open stops, the plain-language verdict, the pace) — the web page itd-167 already decided on; configuration stays operator-side; many repositories waits for a registered-checkout store; a localhost surface that accepts secrets needs a per-launch token; the whole sequenced after the runner and routing intents; and it must carry a falsifier, since no evidence exists that a GUI control plane beats a CLI plus a status page. Ruled with it: where abcd runs as the binary with no host session, the fallback is a HOST THE OPERATOR CONFIGURED (their main connector), never nothing; and EVERY fall back to the host is recorded — a receipt per event and a count per runner and per role in the run record — as intel on what to improve (itd-2609201916056194, planned; itd-22 widened so that "any harness" includes none).

  • dcn-26092200000000022026-09-22

    2026-09-22 — ideate: abcd-operator-console — verdict reframed. The idea, the three legs, and the rejected alternatives: .abcd/development/research/notes/2026-09-22-ideate-abcd-operator-console.md

  • dcn-26092200000000012026-09-22

    2026-09-22 — Model routing, after an independent research pass (product thinker, at an interactive interview). Jev (TypeSafe AI, on OpenRouter) is a typed-decision model, not a router: it fits abcd's closed-option judgements and nothing generative. Rulings: a provider adapter serves only the models it lists under a vendor denylist no listing overrides, everything else on the host (adr-2609221009491186); the OpenAI-compatible API adapter is planned with OpenRouter as configuration, a one-time walkthrough at ahoy and the key kept out of the harness (itd-2609081951381895); a decision adapter for the typed judgements runs in shadow as an abcd lab and a research note is the evidence a ruling turns a judgement type on with (itd-2609221009495079); escalation inside a lane is a rule on a failed fix round, recorded on the model tier (itd-2609170822093401); model per role, the pick and consistency are not routing and stand as ruled; itd-17's learned router is superseded. Every external credential abcd holds goes through one store with three homes the person chooses (adr-2609221017021499, itd-2609221017023290); the API adapter and the site setup read through it. The research is filed as research/notes/2026-09-22-jev-and-model-routing-sota.md.

  • dcn-26092100000000012026-09-21

    2026-09-21 — Phases and milestones are retired, and the word roadmap with them (product thinker, at an interactive interview after an independent research pass; adr-2609212115255771 supersedes adr-9). Sequencing is dependencies plus the lifecycle shelves, rendered as a Now / Next / Later status block on the abcd board and the site (itd-2609212103568351), never stored; the checkpoint is the derived release plus each intent's acceptance criteria, with an optional target_release the cut reports and moves forward (itd-2609212103572513); the unit below a spec is the step, a section not a family (itd-2609212103565953); an issue carries no spec by design; the batch is the run's internal order; one page maps the families (itd-2609211913453478). itd-24 becomes release retrospectives; itd-34 drops its phase rule. Same interview: build is the verb a person types and implement the loop (itd-2609201916151817 decision 8), the loop takes an issue key (decision 10), only the loop writes a verdict (decision 9); the person's command list is grouped with an agents block behind --agent (itd-146), every verb opens with a does/writes/refuses sentence (itd-2609212113220149), modes become flags and five checks one lint (itd-2609212130136102, breaking); the status-line badge is guarded and reset (itd-2609212130146198); a new capture or draft is matched and linked at filing, never refused (itd-2609212137116617); abcd's text names the product thinker or the technical facilitator and never the maintainer (itd-2609212137129937, captured for the run, no sweep today); the lab conventions become abcd lab (itd-2609212137128014); a managed repository's site goes live by one verb behind a provider seam (itd-2609061543533170).

  • dcn-26091500000000102026-09-15

    2026-09-15 — GHSA-4q78-ccfv-f374 (iss-2609012039102770) is closed by OPTION B, ruled by the maintainer at an interactive question: bind the cache to a record the environment does not choose alone. The owned PATH-copy promotion re-verified the cache only against the binary-meta beside it, and CLAUDE_PLUGIN_DATA is taken from the environment as given, so whoever chose the directory wrote both the bytes and the record that "verified" them — reproduced at v0.7.0 as a one-byte file installed 0755 as ~/.local/bin/abcd with provenance recorded. Now the bootstrap, the one process holding the harness's real data dir that has just established manifest trust for the cache (an authenticated cache hit, or a fresh download verified against the same-origin manifest), writes ~/.abcd/cache-attestation — data_dir, the manifest-authenticated binary_sha256, cache_trust=manifest, attested_at; 0600, temp-and-rename, beside path-entry — and ahoy install promotes a cache only when that record names the directory, the co-located record carries the attested hash, and the artefact hashes to it, whichever route (environment or the root's .data-dir stamp) named the directory; detection offers the heal on the same predicate. An offline run neither writes nor rewrites the attestation, so a cache provisioned offline waits for a networked session before it reaches PATH, said out loud. Why B: the trust floor moves from a value the environment supplies to a write into the caller's own home, which adr-46 decision 4 already treats as the ownership root, so the attestation grants nothing that authority did not hold and costs ahoy install no network (adr-38 stands). Rejected: A (a manifest GET on a disk-only verb, re-fetching what the session already proved); C (a documented residual — weaker than it reads, since a harness honouring a committed settings file's environment block lets a hostile checkout set the variable, and the owned-copy claim is what the hook shims trust); the mechanical partial of cross-checking against the plugin-root binary (breaks dogfood installs whose root binary is a local build); and a terminal rung through the attestation alone (it would heal a dogfood checkout's stable symlink into a release copy). adr-46 is superseded by adr-2609151706587280 (never amended, always superseded; retained because its numbered decisions are cited), spc-35 Design 2 step 1 and Design 3 are revised in place and dated, and brief invariant 12 gains the clause.

  • dcn-26091500000000092026-09-15

    2026-09-15 — The roles and loopback design workstream lands on main, executing the 2026-09-01 ruling that the branch waits for the mint verb and takes its ids at the merge. abcd decide now exists, so the two decisions the branch numbered 0055 and 0056 are re-minted as adr-2609151528057260 (three roles, who each artefact addresses, and when the loop stops) and adr-2609151528057131 (abcd owns the product thinker's surface), content, status and date unchanged; every citation that meant the roles decisions is re-pointed (rfc-3, the phase-8 page, the roles page, the out-of-scope list, three intent drafts, and iss-168, whose 29 August extension cited them by the colliding numbers), and main's own 0055 and 0056 keep their ids. The branch's twelve hand-numbered intent drafts (itd-165 to itd-176) collide with nothing and keep their ids, as adr-45's grandfathering allows. Occasion: itd-200 shipped today refining the two roles decisions, so their citations on main pointed at the wrong records until this landed.

  • dcn-26091500000000082026-09-15

    2026-09-15 — itd-200 / spc-70 ship with five implementation rulings the spec left open, taken by the implementing session and reversible by the maintainer (recorded here so none is silent). (1) The status-line offer is its own consent category, status-line, advisory and never approved by --yes, exactly as the git-identity pin is: it rewrites a harness-wide user setting and takes element choices, so only an answered prompt writes it, and yes | answers it. A decline is never persisted; the offer returns on the next install until the user-level setting exists. (2) Harness detection is positive evidence only: the harness's user settings file exists and parses (its directory from $CLAUDE_CONFIG_DIR, else the harness home); no file means nothing offered and nothing written. Ownership of a status command is decided by shape (<absolute entry with leaf abcd> statusline), which is what makes a dangling entry decidable when the binary is gone. (3) The two record counts on the row are FOLDER counts (files named iss-*.md in the open ledger; itd-*.md in drafts plus planned), not the board's parsing readers, because the verb runs on every status refresh and a parse over a clone-controlled record measured 0.96 s at twenty thousand records; folder membership is the record's own status signal, so the number differs only where a parser would skip an unreadable record. The spec's Scope text is corrected to say so. (4) Two guards the reviews required and the spec did not name: the previous-command fallback refuses to run when its own marker is already in the environment and marks its child, so a recorded command that reaches abcd statusline in any spelling terminates instead of forking without bound, and the install refuses to record such a command at all; and every write to the harness settings re-reads the file immediately before the act and merges into the fresh document, refusing when the status-line key changed under the prompts (itd-193's rule applied to a user file a live harness also writes). (5) abcd mode <state> prints the owed-answer line only when the user-level setting is absent or disabled — the setting is the only evidence of a status surface abcd has — and managed prints nothing; the bare board renders the presence line even when the line is disabled, because the switch silences the line and the board is the fallback. Rejected: making the offer a config-change gap (one consent for the PATH entry and the status line would let the reason paragraph be skipped); counting through the board's readers with a cache (a second mechanism to keep correct for the cheapest surface in the tree). The fidelity audit rcp-636b39d5541a records five criteria met with concerns, all disclosed on the shipped record; the one the record could close is closed: the GRILL rule domain now tells an agent to set the mode before it stops for a verdict.

  • dcn-26091500000000072026-09-15

    2026-09-15 — The 1:n intent–spec rule of adr-2609151513118583 is built, and the spec's intent: back-link is the single source of truth for which specs realise an intent (implementing session, ruling on iss-2609100508566552's build, reversible by the product thinker): the intent's spec_id stays a scalar meaning the spec it was planned with, the set is derived by one canonical comparison shared by the spec store, the intent corpus and the record-lint index (a zero-padded back-link once let one reader ship an intent the other saw as still open), and the bidirectional check becomes membership. spec close <spc> --remainder <slug> mints the follow-on spec before any move and reuses an open one with that slug on retry; --remainder is refused on a shipped intent or a closed spec; --impact at a close that does not ship is refused rather than ignored, because the flag's only effect is the judgement shipped/ requires. The fidelity audit request names every spec that realised the intent and the receipt stays owed once per intent. Noted for the gate itd-2609111003026787 plans on the peer's branch, a commit declaring delivery of an intent must move it to shipped/: under this rule a change may deliver one spec and leave the intent planned with a remainder open, so that gate's condition should read "no open spec remains" when it is built. Rejected: an intent-side list of spec ids (a second writable carrier that can disagree with the store, and eighty-five records to edit); a new verb for the remainder (the close is the moment the remainder is known).

  • dcn-26091500000000062026-09-15

    2026-09-15 — A commit message or pull-request title or body that names an iss-N declares its relation to it, and a bare mention is refused in CI before the merge (product thinker, ruling on iss-2609100507421759, first asking whether a formal resolution trailer can be enforced and then choosing "enforce it, and also hint on the default branch"). Resolves: iss-N says the change fixes it and RS001 then requires the record to move in the same diff; Refs: iss-N says touched but not fixed and demands nothing of the ledger; the vocabulary is closed at those two words, a comma-separated list of ids is admitted on either, and a near-miss (Ref:, See:, Related:) reads as what it is. RS004 covers iss-N only, the family the trailer vocabulary owns; an id inside a record body is prose_citation_resolves's question. The hint is abcd capture mentions, a read-only listing over the default branch of open records whose ids appear in commit history without a resolution, ranked resolves over tree over record, silent on the commit that added the record's own file; it lists and never moves a record. Rejected: any mention of the record's id as proof of a fix (a mention proves the author's attention, not a fix); a detector with no enforcement (a silent fix cannot be seen at all, so the gate has to force the mention into a declaration).

  • dcn-26091500000000052026-09-15

    2026-09-15 — An id written in a record's prose must resolve unless the author marks it illustrative or forward-looking (product thinker, ruling on iss-2609100518527863, where a spec composed in an autonomous run carried two invented ids in ordinary sentences and only a human reading it back noticed). record_schema already resolves the typed frontmatter references; the new prose_citation_resolves rule reads record bodies and free-text frontmatter fields through the one canonical resolver, folding case and padding, with a line-scoped <!-- record-lint: illustrative --> or <!-- record-lint: forward-looking --> marker as the only escape. A slug does not stop an id being an id, so a filename-shaped handle is a citation of its id. The corpus that predates the gate is carried by id, never by file, in .abcd/prose-citations-baseline.json, each entry declaring its class and reason, and the baseline ratchets: a new unresolvable id fails even in a file the baseline names, and a spent entry is reported so the list only shrinks. One entry is a probable defect, iss-2608231243286557, cited five times as settled fact with no record ever minted; it is carried as suspect for a human to correct. Rejected: only structured references count (would not have caught the case that prompted the rule); check prose but only warn (a warning nobody reads is the silent exemption the rule closes).

  • dcn-26091500000000042026-09-15

    2026-09-15 — The decisions log becomes a folder of individually minted records with a derived index, and DECISIONS.md a symlink to that index for now (product thinker, reframing iss-2609100507439414 from "how does adoption propagate abcd's merge-attribute workaround into a managed repository" to "why do the two single append-to-the-bottom files conflict when the five one-file-per-record families did not once across 27 merges", the measurement in iss-2609100508570803). The shape applies to abcd and to every managed repository; the decisions-append gate (DA001–DA004) is retired by the shape, in the same change the shape lands. The rule is adr-2609151138420062, the capability itd-2609151138388536 in drafts/; the changelog's conflict class is itd-2609150819432059's and closes separately. The adoption question the product thinker was first asked — point at the conflict, fix it silently, or fix it and take over the changelog — is dissolved by the shape rather than answered. Rejected: keep the file and propagate the union attribute; the folder for abcd only; keep the file and accept the conflicts.

  • dcn-26091500000000032026-09-15

    2026-09-15 — Banned names get both halves (product thinker, ruling on iss-2609100506269348, choosing "both" once told a home list is invisible to CI): a committed declaration lifts the public visibility fence so a fresh public repository can create its committed banned-names layer on its first commit, and a machine-global private list in the user-level home bans a name in every repository on the machine. CI never reads the home list and nothing from it reaches a committed file. Filed as itd-2609151516525843 (builds_on itd-74, refines adr-56); whether the home is one macOS user's or shared across users stays the product thinker's separate open question. Rejected: move the banlist config out of the hidden directory; make the public list private-visibility only.

  • dcn-26091500000000022026-09-15

    2026-09-15 — An intent owns one or more specs, and it ships when its last spec closes (product thinker, ruling on iss-2609100508566552, where spec close shipped the intent unconditionally and a session meeting a half-delivered intent could only stop). An intent that has been thought through stands as written: a spec that delivers part of it is closed on its own terms, a new spec is minted for the remainder and attached to the same intent (spec closed X, spec open Y, intent still planned/), and the intent moves to shipped/ on the close after which no open spec names it, with --impact demanded at that transition and no earlier. The rule is adr-2609151513118583 and invariant 17 of the brief; the build is owed and the issue stays open until it lands. Rejected: close still means ship and narrow the spec (falsifies a thought-through intent); a spec may close without shipping and the intent is shipped by hand (a step after the merge is the one that gets forgotten); split the intent at close.

  • dcn-26091500000000012026-09-15

    2026-09-15 — Identity redaction masks exactly the byte spans the detector flagged, and nothing else on the line (product thinker, ruling on iss-2609120446083912 against the whole-string rewrite that redact.go had recorded as deliberate). The detector's refusals — a component of a reverse-DNS identifier, a collision inside a longer word, an occurrence inside a URL span — are only real if the rewrite honours them; the whole-string rewrite overrode every one of them whenever a genuine mention shared the line, corrupting the technical content a record exists to hold. Spans are validated against the line before the secret seal and applied after it (the seal preserves byte length), overlapping spans merge into one cluster masked with the widest member's placeholder, and the line is rebuilt from original bytes so no offset is ever applied against a shifted line. The cost is accepted and named: an occurrence the detector deliberately clears — a login inside a URL, including a credentials URL's userinfo — is no longer masked by accident, and the stage-two re-scan does not flag it either; the caller's own home path is not in that residue because the detector flags every occurrence by the same anchor the literal sweep uses. Rejected: keep masking every copy but exempt the shapes the detector exempts (a second copy of the detector's judgement, which drifts); leave it as it is.

  • dcn-26090900000000062026-09-09

    2026-09-09 — The headline product is settled (maintainer, closing the press release's "Product framing after adr-35" open question, both halves). abcd helps a product thinker realise an intent as a high-fidelity prototype or demonstrator, carrying the why from idea to shipped reality: the identity block's story, the one the README strapline and the roles page already tell and the one the roles and product-thinker-surface decisions on the design branch (numbered 0055 and 0056 there, re-minted at merge) are built on. The lifeboat is a key capability of that product rather than its headline, and its widening from whole repositories to a single feature, a lab session or an abandoned worktree enters the press release under the not-yet-real marker, as intention rather than commitment. disembark probe is a user-facing command and keeps its place in the press release's scope list. Rejected: the rescue story as headline (it would re-pin the identity block and every surface held to it); adr-35's "read any repository for its theory" as headline (it is the probe's own promise, now one capability among the surfaces); deferring (the audit of the press release against delivered reality had been blocked on this question since adr-35).

  • dcn-26090900000000052026-09-09

    2026-09-09 — itd-2609091034175565, the claim intent, is split into three records (maintainer, ruling after two adversarial reviews of the widened draft, design/feasibility and record-discipline). The reviews found the expensive parts unsound as drafted: a claimed_by stamp on an issue record is invisible to any peer on an older binary, because issueschema.Known is a closed allow-list whose reader refuses and skips a record carrying an unknown key and record_schema mirrors the refusal into the gate, and version skew is the steady state here (five plugin-cache vintages beside a go run checkout); the write-verb refusals fire after the fix is written, because AGENTS.md puts capture resolve in the same change as the fix; no staleness threshold is safe in both directions for two sessions in one worktree, since the worktree-exists and branch-merged tests are identical for both and a host may fire session-end on a context clear with the human still present; and the pushed half costs a merge-queue pass per claim, measured at fifteen to sixteen minutes on this repository's merge-group ci leg. Every collision on record is one of two claim-free shapes. The ruling: itd-2609091416295622 carries the read-only sibling-worktree ledger diff over git worktree list --porcelain (no claim, no lease, no hook, no threshold; the piece that ships soonest); itd-2609091416304128 carries capture resolve and capture wontfix refusing a record terminal at the local origin/main ref as last fetched, stating the ref's age and fetching nothing, with the same judgement rendered read-only on abcd <record-id>; itd-2609091034175565 keeps the claim, the lease and the refusals as a draft marked not ready, carrying the refusal-surface, liveness and pushed-price questions as open questions and the two-release stamp migration as a hard constraint. The existing record stays the claim so the promoted_from trail from iss-2609020716570699 — whose remedy is the claim and the pushed half — stays true rather than being retitled onto a listing the issue never proposed; the two new records reach the issue through related_intents on the issue and on themselves, and every relation the schema cannot type is stated in prose as a prose cross-reference (iss-2609091256264547). All three sit in drafts/; adoption is the interview's. Rejected: re-scoping the existing record to the listing, which keeps the trail mechanically and breaks it semantically; a fifth relation word for "split from", which is the vague form the decomposition principle forbids.

  • dcn-26090900000000042026-09-09

    2026-09-09 — adr-2609090717039680 is superseded by adr-2609091248201071, one record for that original alone (maintainer, ruling on iss-2609091155525689 that each record describing the real-dir helper at its pre-consolidation home gets its own successor rather than one record covering both). The mechanism is unchanged and its home moved: 24c2f2e3 consolidated the three ensureRealDir copies into fsutil.EnsureRealDir / EnsureRealDirAll, so internal/core/history owns the store's layout and mode and calls the primitive for the create-then-prove step. Rejected: describing the mechanism and naming no symbol, which is the reading under which a fourth copy is a faithful implementation of the record.

  • dcn-26090900000000032026-09-09

    2026-09-09 — adr-2609091014087993 is superseded by adr-2609091248200336, which states the split its Consequences left unstated (maintainer, ruling option (b) on iss-2609091129426411 against accepting the bullet as a prediction fulfilled in two steps or reverting the AGENTS.md edit): the location half of the worktree rule binds now — § Concurrent sessions names ~/.abcd/worktrees/<root-sha>/<name>/ and refuses the sibling and in-checkout forms, as of 805bb023 — and the verb half binds when the store ships, because the original's deferral was about naming a VERB that does not exist, never a location plain git already reaches. The successor carries the trust rule, its five declarations and its rejected alternatives whole, and folds in the helper correction iss-2609091155525689 owed the same original, since an original's superseded_by names one record. The original's decision text is untouched; only its status and its forward link change.

  • dcn-26090900000000022026-09-09

    2026-09-09 — A tool never creates directories in user-owned project space, and agent and session scratch is machine-scoped (maintainer, on finding twenty-two agent worktrees created as siblings of the checkout beside their other projects: "I don't want a user to be surprised that a folder is all of a sudden full of stuff"). The isolation stands — the checkout is the unit of isolation — and the location moves: a session's worktree goes under ~/.abcd/worktrees/<root-sha>/<name>/, keyed the way the history, transcript and voyage stores are keyed, and a store nobody can list is refused as the same pile somewhere less visible, so listing and reclaiming are part of the capability. Decomposed on the maintainer's ruling into three records: adr-2609091014087993 (the trust rule, accepted), itd-2609091014076309 (the store, its list and prune verbs and the status-board line, in drafts pending adoption) and the principle the-users-directory-is-theirs (the stance, with its write-side enforcement stated as the intent's future work). Rejected: the in-tree .abcd/.work.local/worktrees/ placement, because every tree scan walks it; a per-user configured location, because its default would still have to be something. The existing sibling worktrees are a hand cleanup, never a migration: the store moves nothing it did not create.

  • dcn-26090900000000012026-09-09

    2026-09-09 — The ledger's human gates on the ordinary flow are parked, reported and never refusing, until the reading work is rethought (maintainer; iss-2609091009111294). The built-in machinery of the provenance ledger and the cold reading stays as shipped, and so does every refusal that guards a reader's blindness or what a reading may return; what changes is every refusal that stops a person in the ordinary intent-to-ship flow for a sentence the gate cannot judge. intent ready keeps all seven rows and gates on four: the mechanism, scope-condition and grounds rows are advisory, named with their remedies, and the verdict ignores them. capture promote and capture resolve record --grounds when it is given and write nothing for it when it is not; a value that is given is held to the vocabulary and the floor as before. A lapse capture without --lapsed-at records no instant rather than being refused, and the committed-ledger gate no longer raises the absence finding, so gate and reader still agree. This reverses two rulings of 2026-08-30, promoting the grounds readiness check to a refusal and refusing a triage that records no grounds, flagged as a reversal and confirmed by the maintainer rather than filed on the tool's judgement. Rejected: deleting the checks, which would lose the report and the remedy; keeping them armed, which is manual work the product thinker's language does not yet justify; and demoting the reading instrument's own refusals, which stop no human. The armed form returns, if it returns, through the legible-surface phase rather than by flipping this back.

  • dcn-26090800000000012026-09-08

    2026-09-08 — The hook shims' PATH rung is OWNED-ONLY, and the 2026-08-01 itd-105 / spc-21 entry above ("Rejected: a PATH fallback in the hook commands (spc-21 forbids it)" and "A PATH fallback is forbidden by the intent's Decisions and is NOT added") is superseded by this one (maintainer, ruling option A on iss-2609012039107700 / GHSA-gx3m-3224-qqcv, CWE-426). iss-254 added the rung in 20968bdf (v0.5.1) with no entry reversing spc-21, so the ledger and the tree have disagreed since; what is true from here is that a rung EXISTS and is narrow. A hook takes an abcd from PATH only when the lookup yields an absolute path, out of a directory that is neither under the shim's working directory nor world-writable (iss-2609012039117381), AND ~/.abcd/path-entry records that exact path as this machine's installed binary — a path= string comparison, no hashing, because adr-46 rejects hashing ~11 MB on every hook event and this rung fires on every prompt and every tool call. What spc-21 was protecting is what this restores: before the ownership check, a plausible abcd earlier on PATH than the operator's became the session's rules loader and, through PreToolUse's pass-through of the guard's 0/1/2 verdict, an approver of every shell command it was asked about. A refused binary now degrades to the shim's existing loud line naming it and the reason; for PreToolUse that is UNGUARDED and exit 1, never the exit 0 the harness reads as approval. SessionStart is unchanged — it has no PATH rung and fails closed. THE CONTRACT CHANGES WITH IT: the install one-liners in README.md and docs/how-to/install.md write path= and binary_sha256= into ~/.abcd/path-entry (they know both values; plugin_root is optional per readPathEntry), because the documented rescue — "the install one-liner restores it, after which the hooks resolve the PATH binary" — would otherwise stop working the moment the rung became owned-only, and a one-liner run after this change re-points the record at ~/.local/bin even where ahoy install --bin-dir had put the binary elsewhere. Rejected: option B, dropping the rung from PreToolUse alone (smallest change, but it leaves the prompt channel and the transcript path exposed to the same foreign binary); option C, accepting the residual as the operator's own PATH (the same shims do resolve sh, find and printf from PATH, but none of those is handed the guard's verdict, and the advisory is a CWE-426 with a working reproduction). Residual, named rather than papered over: the record is home-scoped and equally writable by any same-UID process, so ownership is provenance against a hijacked PATH, not against a compromised account — the same bound adr-46 decision 4 already states, and the reason the check is called ownership and not verification. Pinned by the four inverted cases in internal/surface/cli/hooks_selfprovision_test.go (owned-runs, unrecorded-refused, record-names-another-file-refused, SessionStart-unchanged), with the PreToolUse exit code asserted as exactly 1.

  • dcn-26090200000000202026-09-02

    2026-09-02 — The entailment reading is handed the OBJECT SET's drafts and planned intents, and none by default (maintainer, at the Phase A review). The framework's section 13 fixes the object set as "Iteration 1's shipped state and claim record" — the fifteen workstream intents, which the record extends by the ten Iteration 2 intents — and the readings companion's section 6.2 makes drafts and planned intents ADMISSIBLE at that position: admissible is a permission, the object set is the scope, and the assembly was handing every draft and planned intent in the repository (147 projected intents on the Phase A tree) because a record row is admitted whole when the object set names none of its records. The drafts and planned rows therefore narrow by the entry's record list exactly as the shipped row does, so a draft or planned intent travels only when the committed entry names it; the companion's admissibility becomes a switch on the entailment entry — admit_drafts_and_planned, yes or no for drafts and planned intents beyond the object set, default no, refused at load on any other position because those two rows are admitted at entailment alone. The committed entailment entry names the ten Iteration 2 intents (itd-194, itd-2609021003095168, itd-2609020625400169, itd-2609020625400194, itd-2609020625400445, itd-2609020625402518, itd-2609020625402599, itd-2609020625405170, itd-2609020625405251, itd-2609020625407419) beside the fifteen, and declares no switch; several of the ten are shipped by the time Phase A completes and travel through the shipped row, which is the same object set either way. Issues, ADRs and every other warm family stay excluded by construction and gain no switch. Divergence register entry 1 is corrected accordingly: it recorded the ten as reaching the position through the companion's admission, which is the reading this ruling replaces.

  • dcn-26090200000000192026-09-02

    2026-09-02 — The claim vocabulary is the documents' word everywhere (maintainer's rule that the documents govern): criterion, causal and context on intents, on principles and on the entailment output contract, with the section heading ## Mechanism unchanged as the causal claim's home (framework 7.1). The shipped intent token mechanism (itd-177, itd-190) moves to causal in its own change, filed as an intent by the implementer and planned by the maintainer; the principles record store uses causal from its first entry. The detection figure of about 611,000 estimated tokens in the object-set entry was measured without the glossary; the presets spec's figure of about 624,000 includes it, and both predate the ledger glossary context and the brief-chapter rows, so the figures the window eval measures at landing are the ones the record keeps.

  • dcn-26090200000000182026-09-02

    2026-09-02 — The per-position configuration the 2026-09-01 ruling asked for ("one shared pile by default, and a per-position include table as configuration when a run needs a position handed only its own object", recorded against iss-2608311501240566) is delivered by the per-position preset entry of the object-set ruling of this day, which carries each position's object set, kinds and window, applied with no operand. One configuration surface, not two: a per-position include-table section beside the preset entry would be a second answer to one question, and the change carrying it is reconciled to the preset entry or waits for the maintainer.

  • dcn-26090200000000172026-09-02

    2026-09-02 — Corrections after the final compliance review (maintainer's rule: the documents govern). (1) Phase A of the implementation is the two-operand invocation, itd-194, the preset windows, the comparative channel and the reading-occasioned origin, the last because the framework's section 6.3 has the origin key written only by commands and no promotion of an accepted reading item may precede its writer; Phase B is the condition disposition, the admission and surprise verbs, the reframe record, the scribe verbs and the principles read object, built at Step 5 after the readings, with the first entries hand-authored where the framework permits. (2) Between the phases the maintainer runs all four readings in the cycle's order, not only the two that open it: the widening reading opens (Step 2), the entailment reading runs on the claim record (Step 3), the comparative reading characterises the widening run's candidates (Step 4) and the detection pass reads the shipped state against the claim record (Step 6), as the framework's section 14 places them; admission follows characterisation. (3) The opening target is the commit at which Phase A is complete, and "Iteration 1's shipped state" is read at that commit: the object set names the ledger's records and delivered paths, and a tension the detection pass surfaces between a Phase A change and a superseded claim in a shipped instrument intent is dispositioned like any other, with the supersession named as the purpose. (4) A run that returns no items is committed at every position as a run with an empty item set, never refused, per the framework's section 13; refusal is for a malformed payload. (5) "Brief current text" is the whole brief bar the evidence chapter, which the include table excludes as verdict material (the same ground as the Audit Notes exclusion), and bar the glossary, which is its own row; the product, constraints, meta, surfaces, internals and delivery chapters are admitted as brief sections at every position that reads the brief, and the preset windows are re-measured at landing. (6) The supply-regime check as this tree stands: the reserved-name refusals are the framework's structural signatures and refuse, enforced; the four prose detectors flag, observed; their withdrawal is the 2026-09-01 ruling carried by an unmerged change, and whichever state the opening target carries is what the case report describes, "enforced" for the reserved-name check only. The entry of this day that described the detectors as already withdrawn is corrected by this one. (7) The blindness core's fourth condition takes the companion's sentence, "items are returned in the order they arise in the object"; the four definitions move together with a patch version.

  • dcn-26090200000000162026-09-02

    2026-09-02 — The interpretations the Iteration 2 materials take where the framework and the companion are genuinely open are registered in the dated research note research/notes/2026-09-02-iteration-2-divergence-register.md, one entry per point with the document section, the choice and its ground (maintainer's rule: divergence only where the specification is open, and always recorded). The register is the place a later reader checks before calling the instrument non-conformant.

  • dcn-26090200000000152026-09-02

    2026-09-02 — On the supply-regime check, the 2026-09-01 maintainer ruling governs and the "stay in flag mode" entry of this day is superseded by it: the framework's section 8.9 names two structural signatures (aggregation at evaluative, fix-proposing at registrative) and a record-shape check at explicative, and those refuse, enforced; the four prose detectors were an addition the framework never asked for, proved noisy on synthetic evidence, and are withdrawn rather than left flagging. The property the case report claims is therefore enforced for the structural check and unclaimed for prose. No configuration seam is built; the wontfix on iss-2609012259571458 stands on this ground.

  • dcn-26090200000000142026-09-02

    2026-09-02 — The sentence "no committed cold preset names either" in the source-and-tests entry of this day is superseded by the object-set entry of the same day: the default entries at the widening and detection positions name source and test within the object set, every such item marked unscanned; the entailment entry names neither, because its object (companion section 6.2) holds no tree.

  • dcn-26090200000000132026-09-02

    2026-09-02 — The readings open Iteration 2 and the build follows them, as the framework's section 13 states (maintainer, correcting the marker entry of the same day). Four intents complete Iteration 1's instrument and land before any reading runs: the two-operand invocation, itd-194, the preset windows and the comparative channel, together with the eval gate and the ledger hygiene. The opening widening reading and detection pass then run over Iteration 1's shipped state and claim record with the construal as it stands, marker included (framework section 12: a construal is readable while marked), and their outputs are dispositioned. The six remaining intents (admission and surprise verbs, reframe record, principles as a read object, condition disposition, reading-occasioned origin, scribe verbs) are the framework's own section 13 build list, planned in advance because the documents commit to them, and built at Step 5 after the dispositions, with the first admissions, surprises, reframes and condition dispositions hand-authored in the target format until each verb lands (framework 13, "schema before commands"; companion 5.6). The marker's lift is not a precondition of the widening run; it lifts when the maintainer judges the ledger the construal describes to be real. The sentence "the widening reading does not run before then" in the earlier marker entry is superseded by this one.

  • dcn-26090200000000122026-09-02

    2026-09-02 — What a reading is handed has two committed dimensions, both the documents' own (maintainer): the OBJECT SET (the framework's term, section 13: which records and delivered paths the run is about; for Iteration 2, Iteration 1's shipped state, which here is the ledger: itd-177 to itd-189, itd-198, itd-199, spc-55 to spc-69, and the packages and pages they delivered) and the KINDS within it (the companion's four, section 4.5). A committed preset entry per position carries both plus the window it measures at; nothing at the invocation chooses either. A reading of the object set includes all kinds when the object set fits the reader's window, with the size report stating any figure over the two-hundred-thousand target; measured on 2026-09-02, the ledger at the detection position with all kinds is about 611,000 estimated tokens, which fits a million-token reader and is stated over target. A kind that proves useless leaves the default entry by a commit, which is how the record learns; a larger object set in future narrows kinds the same way. The word "object" alone stays the companion's, for what a position reads; "object set" is the run's, and "object of interest" is its plain-language gloss.

  • dcn-26090200000000112026-09-02

    2026-09-02 — adr-56's third rule is refined, not contradicted, by the source-and-tests ruling (maintainer): a control that admits an input it cannot examine may pass it only with a per-item unscanned mark in its attestation, so the second rule (an attestation never says more than the examination) carries what the third rule carried; refusal stays the rule for an input the control claims to have examined and could not. Invariant 16 amended to say so. Every ADR is now checked against the framework v4 and the companion v4: adr-58 is superseded by adr-2609021016286571, adr-2609021016272867 is corrected to the derived run, and none of adr-55, adr-57, adr-2609021016275803, adr-2609021016270132, adr-2609021016288378 or adr-2609021016286571 contradicts either document. The two-hundred-thousand-token target is a clarification the documents do not speak to, kept as such.

  • dcn-26090200000000102026-09-02

    2026-09-02 — The invocation is a position and a target state and nothing else, as the design specifies (maintainer: "all I want is to run Iteration 2 exactly as designed in v4"). adr-2609021016286571 supersedes adr-58: the scope operand and the override stamp go, the committed preset for the position supplies what the reading is handed, and changing it is a commit. adr-2609021016272867 is corrected the same day from a named candidate-run operand to a derived selection: the comparative assembly takes the one committed widening run at the target whose items carry no disposition and no admission, and refuses naming the runs when none or more than one qualifies. Both corrections close the only two points at which the record contradicted the framework's and the companion's letter on the invocation; the earlier entry today that recorded the named operand is superseded by this one.

  • dcn-26090200000000092026-09-02

    2026-09-02 — Two hundred thousand estimated tokens is a target for a committed preset, not a limit (maintainer): any figure inside the reader's window is acceptable, a figure over the target is stated to the operator by the size report in one line, and nothing is refused for size. The preset-windows intent carries the criterion.

  • dcn-26090200000000082026-09-02

    2026-09-02 — The NOT YET REAL marker on the construal lifts only once what the construal describes has been implemented (maintainer: "lift it once it's true"). Iteration 2's eight intents are planned and not built, so the marker stays; the maintainer lifts it at the readiness statement, and the widening reading does not run before then.

  • dcn-26090200000000072026-09-02

    2026-09-02 — The supply-regime signatures stay in flag mode, code-pinned by a test, and no configuration seam is built (maintainer; the 2026-09-01 ruling that degraded the four semantic signatures on the measured over-catching already records the weakening the framework's section 8.9 requires, and the mode is reconsidered on the evidence of the first real reading rather than flipped by a setting). iss-2609012259571458 is settled as will-not-fix.

  • dcn-26090200000000062026-09-02

    2026-09-02 — The Iteration 2 interpretations are fixed in advance, as the framework's section 13 and the companion's section 7.6 state them, and are recorded here before any reading runs: the opening readings are the widening reading and the detection pass over Iteration 1's shipped state; one closing run is scheduled over the same object set after the dispositions and whatever revisions they occasion; amnesia is a repository property held by the eval and not evidenced by a case run; a detection rejected with a named purpose over a state deliberately unchanged that returns is the purpose-durability finding; a detection accepted and acted upon whose tension returns is the convergence finding; silence at the closing run is weak evidence of settlement and is reported as such; where the opening readings surface nothing, the iteration proceeds on the researcher's own conjectures, the null result is recorded as a run with an empty item set, and no further reading is commissioned to manufacture a finding; where the widening reading returns fewer than two configurations, the comparative reading is not exercised and that outcome is a committed comparative run with an empty item set; recurrence matching is warm work and the recognition is itself a disposition judgement.

  • dcn-26090200000000052026-09-02

    2026-09-02 — The workstream's own fifteen shipped intents keep their missing mechanism claims and their None stated. conditions as the Iteration 1 baseline (maintainer, from the framework's section 10: existing records are untouched, sparseness is information, and an absent stamp on an older record is never backfilled). iss-2609012259581057 is settled as will-not-fix on that rule; the entailment reading's yield bound is reported beside its findings instead (the companion's section 6.6, delivered by the size report as iss-2609012259585189 asks, folded into the preset-windows intent).

  • dcn-26090200000000042026-09-02

    2026-09-02 — The widening position does not receive the shipped intents (maintainer, from the documents: the framework's W12 object and the companion's section 5.2 both list the widening object without them). The shipped-intent projection row's positions exclude widening; iss-2609012259587904 is settled and its code change lands with itd-194's include-table work.

  • dcn-26090200000000032026-09-02

    2026-09-02 — adr-2609021016272867, adr-2609021016275803, adr-2609021016270132 and adr-2609021016288378 are adopted (maintainer, at the same interview, each checked against the framework and the companion first). adr-2609021016272867: the comparative reading receives two body fields of one named widening run's items as the single exception to the prior-run exhaust, through a fourth closed operand naming the run; the maintainer chose the named operand over a derived selection because two widening runs coexist after the closing run, on the condition that an absent operand lists the runs the operator may choose from. adr-2609021016275803: per-run context stamps and a session-separation check that reports held-for-what-was-seen or unobserved, never clean; scribe assemble and scribe ingest with a ledger-only allow list derived from the ledger's directory list. adr-2609021016270132: the principles family is a declared record store with four typed keys, forward-only, read cold by statement and never by citation, with the inheritance check. adr-2609021016288378: in its three-surface form, because the single-section draft contradicted the design's two landings and adr-55's definition of the construal.

  • dcn-26090200000000022026-09-02

    2026-09-02 — Source and tests are opt-in to a reading, never admitted by default, and an opted-in item travels whole and marked unscanned (maintainer, at the Iteration 2 planning interview, checked against the design framework v4 section 7.2 and the readings companion v4 section 4.5, which both name code, tests, documentation and configuration as the shipped tree a reading may see). The source and test kinds stay in the include table so the object stays as the documents state it; no committed cold preset names either; a preset or a scope that opts one in gets it whole, and the manifest marks each such item as unscanned so the exclusion floor's assertion is made only for items it parsed (invariant 16). The detection definition's Object is unchanged. itd-194 is planned on this ruling: the floor refuses markdown it cannot resolve and marks what it does not parse; the strict alternative, removing the test kind from the table, was declined because it contradicts both documents, and the alternative of widening the floor to scan every type stays declined (2026-08-30). Cost of the narrowing under the committed cold presets: none, since none admits source or tests; the live fixture leak at itm-0736 is absent from every committed preset and disclosed as unscanned wherever a preset opts tests in.

  • dcn-26090200000000012026-09-02

    2026-09-02 — The 2026-09-01 supply-regime ruling reverses the 2026-08-31 degrade-to-flag decision (recorded at the maintainer's ruling, flagged as a reversal for the record). On 2026-08-31 the four prose signatures were degraded from refusing to flagging, so an honest report that tripped one landed with a review flag; the 2026-09-01 ruling names accept-and-flag as rejected and keeps only the structural rule, a reserved name as a key of the reader's own output. The implementation withdraws the signature registry and the review-flag plumbing it alone fed, since a detector that produces nothing is dead scaffolding, and re-stamps iss-2608311518056854, which the 31 August change had already resolved, under the new ruling with no Resolves: trailer, because RS001 refuses a trailer for an id that entered resolved/ before the branch diverged.

  • dcn-26090100000000072026-09-01

    2026-09-01 — ADRs take timestamp ids through the same seam as issues (maintainer, the turn adr-45 ruling 3 deferred). Two branches minted 0055 and 0056 on the same day for different decisions, so the hand-numbered ordinal has the add/add collision the timestamp mint removed for captures. From here an ADR id is minted by the binary as adr-<timestamp> with a filename ordered by that stamp; 0001–0058 keep their ids and filenames, and nothing is renumbered. Rejected: minting ordinals from one checkout only (a convention, not a gate), and renumbering at merge (the collision tonight was found by reading, and a reader is not a gate). The mint verb and the lint rule that admits both shapes are implementation, tracked in the ledger.

  • dcn-26090100000000062026-09-01

    2026-09-01 — The strict up-to-date policy stays in front of the merge queue, and the branch update is automated instead (maintainer, ruling on iss-2609012202237613 against the two directions it names). Every auto-merge pull request opened tonight sat BEHIND outside the queue until a hand-run update, because auto-merge enqueues only a CLEAN pull request and the strict policy makes a behind pull request never CLEAN; the queue that exists to test a pull request against the current base therefore never received it. The queue's group commit does gate the merged result, so dropping strict would preserve the duplicate-id gate iss-172 records as an invariant, but the maintainer keeps strict and ships iss-172's first rung: scripts/pr-keep-current.sh walks every armed pull request and asks the forge to merge the base into any that is BEHIND and not queued, --watch repeating until none is armed. Rejected for now: relaxing strict (belt and braces are kept on purpose); a scaffolded update-branch workflow (rung 2, still needing a token whose pushes trigger checks, carried by itd-107). CONTRIBUTING no longer claims branches never need updating.

  • dcn-26090100000000052026-09-01

    2026-09-01 — The brief is the shipped state, consolidated without a new intent (maintainer). The request "a product thinker must be able to understand the current shipped state of the repository by looking only at the brief" is already adr-5's decision and is delivered by two existing drafts, itd-60 (the doc-fidelity pass that gates spec close on the brief reflecting delivery) and itd-147 (generated surface blocks so a shape claim cannot drift), so no umbrella intent is filed; the drift records from the v0.7.0 receipts link to them and the two exact duplicate pairs close as duplicates. Added to the decision: brief, record and release stay in sync, with one legitimate lead — a brief edited after a release was cut is ahead of that release until the next cut, and the gap closes at the cut rather than between cuts. The work is sequenced as Phase 8, "the brief is the shipped state"; the design branch's unmerged "closed loop" phase takes 9 when it merges. itd-61, the reverse direction, stays adjacent as an open question of the phase.

  • dcn-26090100000000042026-09-01

    2026-09-01 — The design branch stays as it is (maintainer). design/roles-loopback-workstream is 471 commits behind main and carries two decision records numbered 0055 and 0056 that main has since used; with decisions moving to timestamp ids, the next design session merges main and takes the ids then, when the mint verb may exist, rather than renumbering by hand tonight.

  • dcn-26090100000000032026-09-01

    2026-09-01 — The supply-regime gate refuses only a real decision field (maintainer, ruling on iss-2608311518056854). Fourteen of thirty-four realistic readings were refused for quoting the document they read, because the disposition detector fires on the bare token followed by a colon or equals anywhere in prose, and a reading that REPORTS a disposition is most of what a reading legitimately does. From here the detector matches the structural shape only: a top-level field in the reader's own output carrying the reserved name, never the name inside a sentence or a quotation. Rejected: accepting and flagging for a human (the gate exists so a human is not the filter); banning the words in the readers' prompts (a detection reading must be able to say that one section says merged and another says pending).

  • dcn-26090100000000022026-09-01

    2026-09-01 — The changelog composer writes only Added and Fixed until it can see the previous release (maintainer, ruling on iss-2609011207114761). The composer's inputs are the records that shipped and their bodies, never the base tag's surface, yet Changed, Deprecated and Removed are claims about exactly that surface, and in v0.7.0 it wrote three such lines about a verb that did not exist in v0.6.9. From here the composer emits no Changed, Deprecated or Removed section, the ingest refuses a composed changelog that carries one, and the release notes say so once so the absence reads as a rule rather than an oversight. Rejected: handing the composer the base tag's command reference (the right long-term input, deferred until the release surface is exported in a form the composer can diff); leaving it to the pre-tag review (a review is not a gate).

  • dcn-26090100000000012026-09-01

    2026-09-01 — Reading positions share one pile by default, and a position can be given its own (maintainer, ruling on iss-2608311501240566). Three of the four positions receive a byte-identical item set today although each is defined over a different object. The default stays one shared assembly, because the readers' definitions already tell each position what to attend to and a shared pile keeps the four readings comparable; a per-position include table is added as configuration so a position can be handed only its own object (the comparative position only the widening output, for instance) when a run needs it. Rejected: making per-position piles the default (four assemblies per run, and the comparability the closing run relies on is lost by default); waiting for a real run to show harm (the record already shows the definitions and the delivery disagree).

2026-08162

  • dcn-26083100000000142026-08-31

    2026-08-31 — Degrade itd-185's four semantic supply-regime signatures (RG-EVAL-ORDERING, RG-EVAL-RECOMMENDATION, RG-REG-FIXPROPOSAL, RG-EXPL-DISPOSITION) from enforce to flag: a hit raises a review flag on the run record and the item lands. This is the reserved degradation path spc-63 names, taken deliberately, and it weakens the claimed property from ENFORCED to OBSERVED. The structural halves are untouched and stay absolute — the reserved names and the strict per-position schema still refuse. THE EVIDENCE IS SYNTHETIC, and saying so is the point: the itd-185 fidelity audit constructed a corpus of 34 realistic reading outputs and 14 were caught, every one of them for REPORTING what the read document said rather than for proposing anything (the disposition detector fires on any claim quoting the token this repository's records carry everywhere; "section 3 says the fix is already merged while section 8 says it is pending" is the canonical shape of a detection finding and fires too). No reading has ever been run through this verb — every payload the delivery has validated is synthetic — so the ruled condition, "degradation only on observed noise" (BUILD-PLAN.md:70, spc-63), is NOT met and this departs from the ruled design. Taken anyway because the alternative departs further: the gate is currently enforced over a calibration that has never been taken, which is the standing tension itd-185 already records against widen-options' "calibrated before it gates", and waiting for observed noise means enforcing indefinitely on no calibration, because the assembled input is about 9.8 MB and cannot be handed to a reading at all (iss-2608311501186646). Of the two departures this one cannot produce a false refusal of a real reading, and it is reversible by the same one-line mode change. REVISIT POINT: the first real reading. When the instrument can be run, the flags it raises are the observed calibration, and the mode is reconsidered on that evidence rather than left at flag by default. Rejected: keep enforcing — defensible under the letter of "degradation only on observed noise" and indefensible under "calibrated before it gates", and on the synthetic evidence it would refuse roughly two in five legitimate outputs the first time a reading ran. Consequences recorded in the same change: TestEverySignatureShipsEnforced is replaced by a test pinning each entry's mode by name so a silent flip in either direction fails; itd-185's ac-5 and ac-9 are rewritten to say flag rather than refuse; the ingested audit verdict rcp-fe3450ca55ff records those two criteria MET on the strength of a refusal and therefore describes superseded behaviour needing re-issue at the next audit; and the disclosed residue on itd-185 and spc-63 is widened to name over-catching beside under-catching, with the propose-versus-report distinction as the reason.

  • dcn-26083100000000132026-08-31

    2026-08-31 — The abcd lab convention: experiments run in throwaway snapshots at the operator level, never inside or committed to the repo. Home: ~/.abcd/lab/<timestamp>-<source-sha7>/, keyed by mint-time timestamp plus 7-char source-root sha — several labs may share one baseline, and the directory must exist before the first mutation; this diverges from the voyage log's root-sha keying (voyage keys one event per source state; a lab keys a session whose identity is its intention), and the divergence is stated rather than claimed as fidelity. Layout: INTENTION.md (question, hypothesis, measures, STOP conditions — written before any mutation), snapshot/ (a throwaway clone mutated freely; records mint freely inside it and never promote — harvests re-file into the real corpus), transcripts/, harvest/, amendments.md, plus an append-only ~/.abcd/lab/index.jsonl registry (id, source sha, status, harvest pointer). DISCARD ends the lab session, not the lab home: the snapshot's live tree is archived to snapshot.bundle and deleted, and every mutation session inside a snapshot ends with a commit inside the snapshot before archiving, so minted records and the snapshot's own .abcd/ tier survive in the bundle; INTENTION.md, transcripts/, harvest/, and amendments.md survive discard, and a later lab clones its base world from an earlier lab's bundle. The real repo is touched only when a harvest files records through normal ceremony, each carrying found_during: lab-<id> provenance and the lab's base sha. Harness-isolation preflight re-runs per lab against that lab's own snapshot world. Hand-maintained until a lab verb exists; the verb is a capstone candidate.

  • dcn-26083100000000122026-08-31

    2026-08-31 — A fact a source can settle is read, not recalled, adopted as itd-197 at the documented-protocol rung on the maintainer's instruction. Recall locates a source and never quotes one; the rule binds any assertion about to be written into a record, a commit message or a brief, or used as the grounds for a decision, and leaves conversation free to be provisional so long as it says which it is. Occasioned by four errors in one session, each about a document its author had read carefully hours earlier: the grounds put to the maintainer for degrading the supply-regime gate cited a licence the design does not give, since its condition is "degradation only on observed noise" and the evidence was a constructed corpus over an instrument that has never run; a captured issue asserted that no non-test file referenced the agent definitions when one already declared the directory constant; a residue paragraph claimed an enumeration could not fall behind while two written lists survived inside it; and a synthetic battery's result was reported as measured. The pattern is the finding: confidence tracked FAMILIARITY rather than accuracy, and the material nobody had read that day produced no false claims because nobody felt able to assert anything about it. Routed by the four-piece table: the stance and its gate to a discipline record; no capability, because the remedy is to open the file; no ADR, because it governs method rather than architecture; no trust rule. Filed as a discipline rather than left as agent memory BECAUSE it was already agent memory: a note from a previous session saying to check a principle's letter before citing it was in context from the first turn and did not bind, which is memory-graduates-to-record's promotion signal in its stronger form, a lesson recalled and then not followed, showing the home rather than the lesson to be at fault. Rejected: leaving it as a memory item, which is what had already failed, and writing a detector, because whether an assertion was read or recalled is not visible in the text. REACH IS THIS REPOSITORY ONLY.

  • dcn-26083100000000112026-08-31

    2026-08-31 — A capability is rehearsed end to end before it ships, at three rungs, adopted as itd-196 at the documented-protocol rung on the maintainer's instruction. Per intent, run what that intent delivers; per intent cumulatively, rerun what the PHASE can deliver so far; at the phase's close, one full run against the corpus the phase is meant to serve. Always over a real repository state, always in a throwaway snapshot, and the result recorded whether or not it is good news. Occasioned by the cold-reading workstream, where thirteen intents, six adversarial delta reviews, five fidelity audits and three review rounds on one eval all passed, and the first end-to-end run found in about fifteen minutes that the artefact a reading is handed is around 9.8 MB, roughly 2.45 million tokens, so no reading can be given one, and that three of the four positions receive a byte-identical item set although their definitions state four distinct objects. Routed by the four-piece table: the stance and its gate to a discipline record; no capability, because the rehearsal is a hand-run over verbs that already exist and script-first-mvp puts the documented protocol at this rung; no ADR, because it governs method rather than architecture; no trust rule, because nothing here is a trust boundary. The cumulative rung is the load-bearing one and it is the addition the maintainer made: the size defect belongs to an assembler shipped in an EARLIER phase which passed its own tests, review and audit, and none of the three intents rehearsed at the end delivers anything that hands a reading an artefact on its own, so only the question "what can this phase deliver right now" reaches a defect living in the composition. A phase that carries a cumulative rehearsal is runnable at every point rather than being a list of merged intents, which makes the demonstration a deliverable rather than a by-product. Rejected: a single rehearsal at the phase close, which is what was actually done here and which found the defect one whole phase after the intent that caused it. REACH IS THIS REPOSITORY ONLY; a rule reaching every abcd-managed repo is a bundled default domain compiled into the binary, which is a code change and its own intent.

  • dcn-26083100000000102026-08-31

    2026-08-31 — The cold-reading evals' CI job is NOT added to the branch ruleset's required-check list yet, and the sequencing is the decision rather than the delay. The job and its make target exist only on experiment/cold-reading; neither is on main, which was checked rather than assumed. A required status check blocks a pull request until that context reports, and a context no workflow on the base branch produces never reports — so arming cold-reading-evals on the active main protection ruleset before the workflow reaches main would wedge every merge to main, including the very pull request that would deliver the workflow. The order is therefore: merge the workstream to main first, confirm the job runs and reports its context on a real pull request, and only then add it to the live ruleset and to the committed mirror at .abcd/work/rulesets/main-protection.json in one change. Rejected: updating the mirror now to record the intent, because a mirror asserting a required check that is not required is a false record of exactly the kind this phase spent the day removing, and it would read as done. Until the arming lands, itd-186's always-run lane runs on every pull request and gates none of them, which is a green for work that did happen but binds nothing — the weaker half of the failure spc-64 was written against. Tracked at iss-2608311051046981.

  • dcn-26083100000000092026-08-31

    2026-08-31 — itd-185 folds invisible and compatibility-equivalent runes (Unicode spaces, Cf + Other_Default_Ignorable_Code_Point + Variation_Selector, NFKC) before signature matching and before every blankness rule, and DISCLOSES the script-confusable class as open. Ground: the registry's own phrasing with a byte substituted is an evasion of the gate, not the calibration residue; a confusables table is a new dependency and the maintainer's call. Rejected: filing the invisible-rune class under the disclosed residue.

  • dcn-26083100000000082026-08-31

    2026-08-31 — itd-185's ingest containment is layered and the layers are mutually redundant: writeJSONIn's contained write is currently unreachable because refuseARerun probes the same path through the root first, and nothing asserts that ordering. Recorded rather than fixed, because the property is proved by mutating containment as a whole; a future edit that moves or drops the rerun probe must re-check it. Rejected: a per-layer test, which would pin an ordering the design does not promise.

  • dcn-26083100000000072026-08-31

    2026-08-31 — itd-185's record-size limit is DECIDED in capture.IngestReading on the assembled bytes, not estimated from the payload; reading's recordBytes stays as a cheap early filter that buys item-level granularity. Ground: two attempts to decide it upstream each modelled one lengthening step (the escaper) and missed the next (the redactor, which exceeds 2x and scales with body length), and a record past the limit is durable and permanently undispositionable. Rejected: a third coefficient.

  • dcn-26083100000000062026-08-31

    2026-08-31 — The position/regime disagreement is refused in reading.LoadDefinition, not cross-checked in the ingest verb. Ground: the locator is the one thing that claims to resolve a position to its regime, and a resolver returning a confidently wrong answer would hand the supply-regime gate the wrong licence silently. Rejected: a cross-check inside the ingest path, which would be a second table of one fact and leave the primitive broken for the status render.

  • dcn-26083100000000052026-08-31

    2026-08-31 — The ingest stage holds a write-aside MARKER, not the rendered reading records; capture.IngestReading writes them against the real ledger. Ground: that writer mints every item id under the ledger lock precisely so its collision probe sees the tree it is about to write into, and staging into a second issues root would move the probe off the real ledger. The orphan sweep rolls the run back instead, bounded by the rdi-N.md filename grammar. Rejected: staging rendered records per spc-63's first draft.

  • dcn-26083100000000042026-08-31

    2026-08-31 — itd-185's payload item is FLAT (pattern plus the position's own body fields, read from issueschema.ReadingBodyFields), not spc-63's drafted {pattern_named, body} with shortened names. Ground: the four shipped definitions instruct the flat shape and the record schema's field names, so the drafted table would have refused every output the shipped instrument can produce and would have put a rename between the payload and the record for no gain. Rejected: keeping the spec's table and translating at ingest.

  • dcn-26083100000000032026-08-31

    2026-08-31 — The wave plan is re-cut, because itd-184 and itd-185 are not independent: spc-63's regime gate resolves a run's position to agents/cold-reading-<position>.md and reads its regime key, and recomputes that file's hash for instrument identity, so itd-185 cannot be built until itd-184's four definition files and their locator exist. The real graph is two file-disjoint lanes — itd-184 then itd-185 over internal/core/reading and agents/, itd-186 then itd-187 over evals/, the Makefile and ci.yml — so the ceiling of two concurrent agents is held by running one lane in each rather than by pairing the two deepest. itd-186 and itd-187 need no assembler change: spc-64's four demands on spc-61's interface (dry-run, an operator-named output directory, separate bundle and manifest artefacts, position and target flags, non-zero exit) are all already shipped. Rejected: building itd-185 first against fixture definitions, which would ship the keystone verb unwired to the definitions that are its source of truth.

  • dcn-26083100000000022026-08-31

    2026-08-31 — Phase 0 of the last four intents executed: the ruled criteria split, applied to itd-184, itd-185, itd-186 and itd-187 before any builder started, with the four specs' mapping tables rewritten in the same change so intent and spec cannot drift. Splits: itd-184's regime criterion separated the value stated in the definition from the absence of any operator surface that sets it, the latter given its own observable and an executable enumeration rather than a written list; itd-185's malformed-output criterion separated refusal-with-no-partial-write from the crash window between staging and the commit marker, and its registrative and explicative criteria each separated the reserved-name half the schema holds absolutely from the semantic half bounded by the signature registry; itd-187's second criterion was replaced by three, because its Given — a nondeterminism introduced into the shipped assembler — is unestablishable by any artefact, an eval being forbidden to patch the code under test, and the remainder is disclosed as a recorded hand-run. Every residue is stated in the record beside the criterion it qualifies, so a later audit reads the bound rather than rediscovering it. BEYOND THE LETTER OF THE RULING, and cheap to reverse because each sits contiguously at the end of its list: three criteria added to itd-185 (named provenance at every regime, the payload regime that disagrees with the definition, and verb-minted item ids) and two to itd-186 (the oracle's structural independence from the assembler, and the anti-vacuity guard that every declared sentinel is planted). Each covers a promise already in the intent's scope and already carrying a named test in its spec, and leaving a load-bearing promise unmeasured is the same failure as an unmeetable criterion, taken from the other side. Item-level refusal granularity in itd-185 is the one such gap left unclosed, and is queued rather than added. Rejected: splitting at build time (the criterion is rewritten in minutes before the work and re-litigated in an audit after it) and leaving the semantic halves conjoined under MET_WITH_CONCERNS (which stops carrying information once it is the default outcome, and on the present trajectory it is).

  • dcn-26083100000000012026-08-31

    2026-08-31 — Three rulings from the two fidelity audits. (1) The grounds obligation gets a FORWARD-ONLY gate: a terminal-folder record must carry an entry if it was created after the gate is armed, and the cutover is the ARMING COMMIT rather than a date, because a date in prose is the fact itd-195 says not to state. Precedent is this cycle's own forward-only intent-side gate, and the reason is that the ~689 records that would otherwise be refused were made by the repo's ordinary working practice. Rejected: no gate at all (honest but leaves three-quarters of new records escaping a claim the press release makes universal) and forcing the verb to be the only door (universal, but 689 migrations and a fight with daily practice). (2) The four remaining intents' ACCEPTANCE CRITERIA are reviewed BEFORE building, and any criterion conjoining a structural half a machine can enforce with a judged half it cannot is split — the remedy itd-183's audit proposed for its own ac-5. Five criteria have now been audited and none reached MET; two are unmeetable by nature, and MWC stops carrying information once it is the default. (3) The grounds body-lockout is lowered to minor and the hand edit accepted as the repair: the guard is correct, the exit exists in a text editor, exposure is latent, and validating at capture time would contradict the adopted rule that capture stays frictionless.

  • dcn-26083000000000262026-08-30

    2026-08-30 — The in-place mutation hazard graduates from a session habit to the committed record as itd-193, a discipline: a verifier works on a copy, and whoever acts on a tree proves it clean immediately before the act rather than inheriting an earlier check. Occasioned by a reviewer running its mutation matrix against a live build worktree while a peer review, correctly, reported the modification as untouchable peer work it could not distinguish from real work. Routed by the four-piece table: the stance and its gate to a discipline record; the operational line to the AGENTS.md concurrent-sessions section beside the peer-work rule it complements; no capability, because the documented protocol is the MVP at this rung (script-first-mvp); no ADR, because it governs method rather than architecture. Adjacent to the one-writer-per-file principle and deliberately not folded into it: that principle governs committed records across merge windows and puts per-worktree files out of scope, while this governs the working tree inside a single window. REACH IS THIS REPOSITORY ONLY and the record says so — a rule reaches every abcd-managed repo through a bundled default domain compiled into the binary, which is a code change and its own intent; rung 2 (a recall-injected domain rule) and rung 3 (a mechanical clean-tree assertion) are named in the record and neither is claimed.

  • dcn-26083000000000252026-08-30

    2026-08-30 — The two cold-reading evals get their own always-run CI job rather than riding the smoke job that stands down on record-only pull requests. The stand-down is anti-correlated with the risk these evals exist to catch: they read the live record tree, and docs/, .abcd/development/, .abcd/work/ and the root prose files are both the classifier's inert allowlist and the material the assembler includes, so the diff most able to introduce warm content is exactly the diff that skips the check. A stood-down job still reports its context green, so the current shape manufactures a green for work that did not happen, which the loud-staging principle refuses. The remedy follows the reasoning ci.yml already documents for the ubuntu unit lane, which never stands down precisely because its tests read the live tree: a small job with no inert condition running these two evals alone, the rest of the smoke harness unchanged, the workflow edit landing with itd-186/187 so it is reviewed beside the evals it serves. Ruled before the build rather than after, because spc-64 and spc-65 both promised no workflow edit would be needed and that promise is what changes.

  • dcn-26083000000000242026-08-30

    2026-08-30 — The disposition vocabulary ships four states and the fifth stays unnamed, which is spc-58's decision restated rather than a new one: the shipped enum is accepted, rejected, declined, held, the schema is data so a fifth is one line the day it is named, and naming it is a vocabulary judgement belonging to the researcher rather than to a build. admitted is not the missing fifth — ruling (19) already folds admission into accepted because position lives on the envelope, so introducing it would reverse that ruling rather than complete it. The recurs citation is likewise ruled out by spc-58 as never a state, and nothing meaning "already covered" exists at any position because an undispositioned item is reported as outstanding instead. The open candidate the record leaves is the selection vocabulary's deferred, which makes this the same question as whether held is available at the widening position — already deferred to the first widening run's dispositions, and settled there or not at all.

  • dcn-26083000000000232026-08-30

    2026-08-30 — The scribe-protocol rehearsal is owned by the facilitator and runs in this cycle, scoped to the process alone: whether the protocol works, not whether it matches the product thinker's intentions. The product thinker is unavailable, so the fidelity half cannot be exercised and is deliberately out of scope for this rehearsal rather than silently skipped; a rehearsal that tested only what one participant could judge would otherwise be reported as if it had tested both. This is the remaining half of the Phase 0 item (d) whose phase home was ruled earlier; the step-2 admission-record owner stays unnamed, and the roadmap now records why nothing is owed there before a widening reading runs.

  • dcn-26083000000000222026-08-30

    2026-08-30 — Correction to the itd-179 delta-close entry above, which is substantively right and wrong in two words. It says "consequence A" — a label that exists nowhere in the repository, the orchestrator's briefing shorthand leaked into the durable record; the record it points at enumerates its consequences as 1, 2, 3. And it says "the record says so", which the record does not: its resolution field names the diagnosis and mint-ordering halves only, so consequence 1 reads as fixed to anyone arriving fresh. The residual — an unclosed comment or fence in an issue BODY still locking the record out of all three triage verbs — now has its own open marker at iss-2608301908270888, which is where a later session should find it rather than by following a pointer to a record that does not mention it. Everything else in that entry stands, including both rejected alternatives.

  • dcn-26083000000000212026-08-30

    2026-08-30 — itd-179 delta close: mdrecord.findBacktickRun's superlinear shape stays, on a measurement rather than a shrug. A line of 120 distinct-length backtick runs costs ~200us and an ordinary record line ~76ns; precomputing the runs into a slice takes the bad line to ~7us and the ordinary line to ~115ns with one allocation per line, and stepping between runs with strings.IndexByte takes the bad line to ~243us. Both trade the case that always happens for a case no record body has. Rejected: landing the precomputed-run version, which reads as an optimisation and is a regression on this repo's workload. The two benchmarks and the numbers live in the package so the trade is not re-litigated.

  • dcn-26083000000000202026-08-30

    2026-08-30 — itd-179 delta close: body scope does NOT close consequence A, and the record says so. An unclosed opener in the BODY still masks the body, so an appended entry still cannot read back and every triage route still refuses — verified by a test that stayed red at the body-scope commit and only passed at the next one. What makes that survivable is the other two halves: the refusal names the opener's line and construct instead of the grounds operand, and promote dry-runs the append against the pre-flight bytes so a deterministic refusal mints nothing (iss-2608301803423101). Rejected: refusing every record carrying an unclosed opener, which would refuse writes that succeed — a ## Grounds section ABOVE the opener takes the entry perfectly well. Rejected: a file-relative line number in the refusal, because the triage verbs append after setting their note field and the number would name a line the unwritten record on disk does not have; the number is body-relative and the opener's text is quoted beside it.

  • dcn-26083000000000192026-08-30

    2026-08-30 — itd-179 delta close: the grounds APPEND and its read-back run over the record BODY, spliced back onto the frontmatter, rather than over the whole file. frontmatter.Split is the one lossless answer to where the block stops and grounds.Body is what both halves ask, so the writer judges the bytes the reader consults and the writer/reader disagreement is unrepresentable rather than banned one spelling at a time (iss-2608301805069999). The intent half's reader moves to the same scope, where the whole-file reading would have found an empty pseudo-section. Rejected: refusing a frontmatter # Grounds comment, which bans the one spelling that was reported and leaves the scope split that produced it.

  • dcn-26083000000000182026-08-30

    2026-08-30 — itd-179 round-5, correction to the round-4 letter-floor entry above: unicode.Other_Default_Ignorable_Code_Point does NOT "name exactly those four letters and nothing else", and the remainder is not "format characters and variation selectors". Measured over the whole code space: the table holds 3776 code points, of which exactly seven are assigned — the four Hangul filler letters (Lo) and three non-spacing marks (Mn) — and the other 3769 are unassigned; it carries zero format characters and zero variation selectors, which reach Default_Ignorable_Code_Point through the other contributors to that derived property. The conclusion the round-4 entry drew is unchanged and was verified exhaustively — the only LETTERS the table can exclude are those four — but the description of the rest of it was wrong, so it is corrected here rather than left to be re-derived (iss-2608301657350399).

  • dcn-26083000000000172026-08-30

    2026-08-30 — itd-179 round-5: a RELOCATION is not a BACKFILL, and the forward-only rule forbids only the second. Moving a pre-tooling ## Grounds (pursued) section from a spec onto its intent (commit 09f7d91a, thirteen specs) put text authored at the moment of pursuit where it belongs; nothing was reconstructed, which is the whole of what "never backfilled" refuses. Three shipped intents therefore carry a ## Grounds section — itd-177, itd-182, itd-188 — and the surface claim now says so instead of asserting the corpus carries none (iss-2608301657357989). The enforcement is unchanged and stays maximally strict: RecordGrounds refuses a shipped or superseded record whatever the provenance of the text, because nothing in it can tell relocated text from invented text, so the relocated state is deliberately not reachable through abcd intent ready --grounds. Rejected: weakening the refusal to admit a --relocate escape, which would make the distinction a caller's assertion rather than a reviewable fact about a commit.

  • dcn-26083000000000162026-08-30

    2026-08-30 — itd-179 round-5: the ISSUE ledger's grounds become APPEND-ONLY, as a ## Grounds body section mirroring the intent half, and the frontmatter grounds: scalar is retired (16 committed records migrated in the same change). A scalar is SET, so a resolve or wontfix silently destroyed the conjecture a promote recorded — on the ledger's mainline sequence, since fourteen resolved records carry promoted_to — and the result still reported success (iss-2608301657354776). Rejected: refusing a transition that would overwrite a non-empty grounds, as the record proposed; promote, resolve AND wontfix all REQUIRE grounds, so the refusal would make a promoted issue impossible to resolve. Rejected: last-write-wins declared as a chosen tradeoff, because intent/grounds.go already argues the opposite for the same data — the earlier conjecture is precisely what a later reader checks the outcome against. One-canonical-primitive: the record form (heading, section reader, append, readability check) moved to core/grounds, and the generic markdown-body machinery under it to a new leaf core/mdrecord, so both record families share ONE definition rather than holding two. Rejected: leaving the form in core/intent and having capture call it, which is one implementation but puts an issue-record body parser behind the intent package's door. The retired key is TOLERATED in issueschema.Known, not refused: a refusal makes capture SKIP the record, and a record invisible to every surface while it still sits in the ledger is worse than a value nothing reads — the record lint's record_schema blocks the misplacement and names the section instead.

  • dcn-26083000000000152026-08-30

    2026-08-30 — itd-179 round-4: the grounds floor's character half counts LETTERS (MinTextLetters = 20, isTextLetter) and is asked AFTER the unit half. Both halves stay, as the round-3 entry above requires — what changes is the unit each is measured in and the order they are asked in. A rune count is answered by whatever occupies a rune: a b c plus seventeen dots cleared twenty "characters" carrying three letters of reasoning, and a text of Hangul fillers cleared the whole floor while rendering as nothing end to end. Rejected: asking the letter count first, which makes the scriptio-continua refusal unreachable — every unit that refusal speaks for is a single letter, so a text with twenty letters has twenty units and can never be below the three-unit floor, and one with fewer would be refused for its letters instead. Rejected: filtering only the zero-width format characters, which leaves the filler class open because U+115F, U+1160, U+3164 and U+FFA0 are category Lo; unicode.Other_Default_Ignorable_Code_Point names exactly those four letters and nothing else. Corpus: the 25 recorded grounds texts in the tree are refused by neither the old floor nor the new one.

  • dcn-26083000000000142026-08-30

    2026-08-30 — itd-179 round-4: the grounds floor's unit is a WORD where the script separates words and a LETTER where it does not (textUnits + a named, deliberately partial scriptioContinua set: Han, Hiragana, Katakana, Thai, Lao, Khmer, Myanmar, Tibetan, Javanese), and MinTextWords = 3 is unchanged. The letter test is load-bearing, not tidy: a Unicode SCRIPT table carries its script's digits, punctuation and combining marks too, so counting table members would have made twenty Thai digits — or twenty Tibetan tsheg, which are twenty dots — a twenty-unit text and reopened iss-2608301206034359 once per script. Rejected: the review-converged shape of "contains a scriptio-continua rune → skip the run count and apply the rune floor", because supercalifragilistic 中 then clears a 20-rune floor on one word; the shipped counting refuses it at two units, though the closure is one ideograph deep (supercalifragilistic 中中 passes, as supercalifragilistic 中 中 already did before this change). Rejected: Hangul in the set — Korean is spaced, and counting its syllables would let two Korean words clear a three-word floor. Limit stated in the doc comment: a scriptio-continua script not named in the set still counts as one word and is still refused, and the set is where that is fixed, one script at a time.

  • dcn-26083000000000132026-08-30

    2026-08-30 — itd-179 round-3: the double-quoted frontmatter scalar decoder's canonical home is internal/core/frontmatter (Unquote), joining IsNull there, rather than exporting capture.unquote. Rejected: lint importing capture, which is an import cycle — capture's own tests import lint.

  • dcn-26083000000000122026-08-30

    2026-08-30 — itd-179 round-3: the grounds substance floor is measured in letter-runs (MinTextWords = 3) alongside the character count, not instead of it. Rejected: replacing the character floor, which would admit "a b c"; raising the word count further, which the corpus (shortest real entry, 32 words) does not need and which would start refusing terse honest reasoning.

  • dcn-26083000000000112026-08-30

    2026-08-30 — Phase 1 adversarial review (ruthless-reviewer, fresh context) findings captured as iss-2608300114352100 (a first name disclosed through a homonym in the session-1 lapse record; the wording is replaced, and the pushed branch's history still carries it until the PR is squash-merged), iss-2608300114357633 (this log contradicting the branch, remedied by the two lines above), and iss-2608300114359543 (record consistency: one role name for the 2026-08-28 rulings, the ratified marker form in itd-143, the framing section statement-first, no adoption-date marker on invariant 15, the phase count, and "Phase 2 planning" reworded so it cannot read as roadmap Phase 2). All three resolved in the same change.

  • dcn-26083000000000102026-08-30

    2026-08-30 — The brief-lifeboat mapping row for the framing section lands in the Phase 1 filing after all (orchestrator's improvisation, logged for the facilitator): TestEveryBriefSectionHasARow refuses a brief section without a row, an armed test cannot stay red, and the construal must file first; the row is its own commit, droppable if the facilitator prefers to hold it for itd-143's build. This supersedes the deferral recorded above.

  • dcn-26083000000000092026-08-30

    2026-08-30 — Ruled at the checkpoint (facilitator): the workstream's roadmap phase home is a new Phase 7, the next free number; the phase document files with the Phase 1 records. This supersedes the deferral recorded above.

  • dcn-26083000000000082026-08-30

    2026-08-30 — Deferred with revisit point at Phase 2 planning: the workstream's roadmap phase home (options presented: Phase 3; Phase 2; a new Phase 7; a split) and the [HAND] owners for the scribe-protocol rehearsal and the step-2 admission records (facilitator, product thinker, or either-first).

  • dcn-26083000000000072026-08-30

    2026-08-30 — Framing section sited as 01-product/06-framing.md, appended rather than inserted so existing chapter links hold (facilitator). The brief↔lifeboat mapping row and the 00-meta.md regeneration are deferred to itd-143's build, carried from session 1: the filing PR carries no code beyond the lapse enum line.

  • dcn-26083000000000062026-08-30

    2026-08-30 — Deferred (facilitator): whether held is available at the widening position or a deferred configuration belongs to the selection vocabulary's deferred; revisit point is the first widening run's dispositions, a later cycle. Non-gating: the per-position availability row stays unfilled until then.

  • dcn-26083000000000052026-08-30

    2026-08-30 — Confirmed (facilitator): the six-criterion selection slate (plausibility, generativity, cost, risk, learning value, practical importance) files as the selection-criteria discipline as committed 2026-08-28.

  • dcn-26083000000000042026-08-30

    2026-08-30 — The ledger's construal is filed (pre-tooling entry 01 resolves to this pointer): .abcd/development/brief/01-product/06-framing.md, section "Construal". Production mode: dictated by the product thinker, formatted by the orchestrator against docs/reference/writing-style.md with zero text operations (the one rule it meets, capital after a colon, is waived for the lowercase-by-design name), confirmed per item by the facilitator before filing. The 150-word outward-facing form is held on the local ledger side, unfiled, until a home is assigned. Ambiguity flag from the two adversarial reviews carried, not ruled: "ledger" also names the issue ledger; the section heading names whose construal it is, and a glossary term remains an open option.

  • dcn-26083000000000032026-08-30

    2026-08-30 — Ratified (facilitator): the not-yet-real marker is a passage-level token — a blockquote line holding exactly **Status: NOT YET REAL.**, a blank line, then the statement as the first paragraph — so a bold opening sentence can never be mistaken for the token. The ledger's construal passage carries it.

  • dcn-26083000000000022026-08-30

    2026-08-30 — Cycle 1 restarts on v0.6.9 (facilitator): baseline v0.6.9-4-g976575f9; the orchestrator is Fable, research and implementation sub-agents are Opus 5 in fresh contexts; the merge target is the integration branch experiment/cold-reading in a worktree outside the checkout, never main — the final PR to main is the facilitator's to test and merge. Widening decision (20): the orchestrator also runs the two adversarial reviews and the dependency-ordered merges onto the integration branch autonomously; the only stops are gate weakening, a security BLOCK genuinely unresolvable, and a new Go dependency (allowed only if absolutely necessary, logged). Improvisation inside the rules is allowed and logged, never quiet.

  • dcn-26083000000000012026-08-30

    2026-08-30 — Every release object older than v0.6.9 is deleted from the forge (v0.1.0, v0.2.0, v0.3.0, v0.4.2, v0.5.1, v0.6.7, v0.6.8; the v0.6.0–v0.6.6 tags never had one), and every tag is kept. The three v0.6.9 advisories mark <= 0.6.8 vulnerable, and a release object is the only thing that makes a vulnerable binary downloadable by version: the installer, the bootstrap hook and abcd update all resolve latest, so removing old assets affects only a deliberate pin, which is the point. Tags are the immutable audit trail the release gate relies on (adr-52), and the build-provenance and receipt attestations that named those releases stay in the attestation store even though the artefacts they attest are gone; the deletion is recorded here because no earlier release removed a predecessor and the decision log carried no practice for it. Reversing it means re-cutting a release from the surviving tag, never re-uploading old assets by hand.

  • dcn-26082900000000042026-08-29

    2026-08-29 — Roles for the cold-reading cycle (facilitator): the session user is the facilitator; the co-author is the product thinker, who dictates the construal. Both are named by role only, never by name, in every record and commit. The construal is the ledger's construal for this cycle, not abcd-wide. Frame origination is reserved to the warm side: the orchestrator formats and may widen options, never recommends a construal or rules whether one fits.

  • dcn-26082900000000032026-08-29

    2026-08-29 — v0.6.9 security pass, three process decisions recorded so they are not re-litigated. (a) The four GitHub bug-hunt issues (#485–#488) were verified before any capture and found already fixed on main by the 2026-08-27 security cut; they were closed against their fixing commits rather than re-captured, because a duplicate record beside a resolved one is noise the ledger's status signal cannot carry. (b) The installer's proxy/CA-bundle lockdown keeps no environment-variable escape hatch: the lockdown is the GHSA-x4v8 fix and an env opt-out reopens the vector; the availability cost (NixOS, corporate proxies) is captured as an open record for a product decision, and only the failure message was improved. (c) Every fix branch received two independent adversarial reviews (security + code) from reviewers that did not author the change, repeated until neither returned FIX-FIRST, and the assembled multi-branch diff received the same two again before the PR; the fix PR merges with a merge commit, never squash or rebase, so every resolved_by.commit stamp stays reachable (RS003).

  • dcn-26082900000000022026-08-29

    2026-08-29 — The gitleaks adapter admits a binary under an allow-shape, not a deny-list (GHSA-fg9r-3f8g-89m6, iss-2608291807456485): absolute path, resolved OUTSIDE the repository both lexically and after symlink resolution, regular, executable — applied identically to a committed path and to the PATH lookup result. Refusal is ErrConfiguredPathRefused, as loud as not-found, and a refused configured path never falls back to PATH. PATH itself stays trusted as the operator's environment (abcd already resolves git, gh and grep from it; a hostile checkout cannot set it); what the admission rule closes is a PATH entry or config that reaches INTO the checkout. Rejected: a fixed safe search path for the fallback (would break Homebrew/asdf/custom installs for no gain against an operator-level PATH compromise) and executing with an isolated env (the env is the operator's, like PATH — gitleaks does honour GITLEAKS_CONFIG, but a checkout cannot set it; cwd is pinned to the private temp dir instead). Containment routes through fsutil.PathWithin with the case-folding predicate AND an os.SameFile ancestor walk, because a byte-exact compare admitted a case-variant or NFD respelling of the root on APFS.

  • dcn-26082900000000012026-08-29

    2026-08-29 — v0.6.8 semantic gates: two maintainer judgements recorded so they are not re-litigated. (a) The iss35 cross-check was RE-RUN against the final content commit (00f1509d) rather than accepting an earlier full-tier run whose tree was amended in flight: a receipt attests one sha and the earlier run could not honestly name one; at ~13 minutes wall and ~1.7M tokens a re-run is cheaper than the ambiguity. (b) PROMOTE with a disposition on every finding (60, all independently re-verified, 0 refuted) rather than HOLD: the findings are the design brief lagging the shipped surface (iss-2608231346137587, whose corpus rule forbids hand-fixing ahead of the mining intent), not something the release introduced or ships, and a HOLD would block a correct changelog behind debt the record already owns. Also noted: the local_username payload rule collides with product vocabulary on a machine whose account name is a common word (iss-2608291444328326); the release push used a HOME symlink alias so the pre-push preflight could run in full, never --no-verify, and CI re-ran every gate under its own account.

  • dcn-26082800000000062026-08-28

    2026-08-28 — Grounds recording extends the ADR family rather than duplicating it: the family holds decision-granularity grounds (Alternatives Considered); the ledger adds conjecture granularity as a grounds argument on the selection surfaces, one canonical primitive, no parallel store.

  • dcn-26082800000000052026-08-28

    2026-08-28 — Ledger mechanism and ledger content are distinct: the mechanism is engineering (schemas, commands, gates, evals), reviewable and reworkable; the content is the recorded reasoning, populated only by actual use and never reconstructed. A defect in the mechanism is fixed; a defect in the content is disclosed.

  • dcn-26082800000000042026-08-28

    2026-08-28 — Cold-reading workstream rulings adopted (facilitator; committed in design discussion, disclosed as a pre-tooling lapse): (1) the construal-admissibility extension of adr-50 files first — the construal as it presently stands is committed record and readable by automated readers, its revision history is not (adr-55 carries the full rules); the construal is sited as a brief section under 01-product/. (2) The reading record (type name ruled at (17)) is a distinct record type in the issue tier with a separate disposition record and its own disposition vocabulary — the five-state slate with availability by position, per (19); the existing issue states are not reused for it; status is the presence of the keyed disposition, never folder membership. (3) One closing reading run is scheduled over the same object set after dispositions, with interpretations fixed in advance: silence is weak evidence of settlement; an accepted-and-acted detection returning is a finding; a rejected-with-purpose detection returning bears on whether the purpose resolved the tension. Amnesia is proven by a repository eval, never by a case run. A clean opening run is recorded as a run with an empty item set; the cycle proceeds and no further reading is commissioned. (4) The supply-regime check is built now: a regime field on the output contract, validated at ingest; enforcement is the default, and degradation to record-and-flag happens only on observed noise, recorded. (5) Reading invocation carries no free text: position and target state only. (6) The lapse log is a value in capture's validated category list, not the source enum. (7) Elicitation: the articulation round produces one intent, the exit noting candidates; the escalation rule is adopted (a defaults question that turns out conjectural escalates to the options regime); a held working principle permits articulation to proceed with the mechanism recorded as an explicit nullity, flagged in the readiness summary. (8) From the readings design, agreed as proposed: the reading record carries a position-typed item body (one record type, four bodies — registrative, generative, explicative, evaluative); the selection criteria are a recorded discipline with the committed six-criterion slate, never supplied at invocation; the comparative reading's candidate set is the widening reading's pre-admission output, with admission following the comparative characterisation; the no-input-is-authoritative condition enters the blindness core (no document passed to a reading is the fixed side of any comparison), and the widening/entailment asymmetry over draft and planned intents is stated explicitly in the assembler's include list — both confirmed at the facilitator's review, 2026-08-28; the disposition-side recurs citation is adopted as the recorded form of warm recurrence recognition. (9) Ruled 2026-08-28 (revised the same day): the manifest is committed to the durable tier at .abcd/development/readings/<run-id>/, alongside the run record — a new record family; lifecycle selects the tier, and commit reference plus per-item hashes make the assembly re-runnable and diffable. (10) Adopted 2026-08-28: brief invariant 15 — reading contexts and the ledger never meet, the scribe is not a transcript consumer, and the session-transcript store is reached through one door by an enumerated allow list (custodian writes and reads; lifeboat session-hunting consult-only; session-separation metadata; opt-in memory curation); a new consumer is an invariant change, never merely a code path, and only the history core package touches the store's path, held by a boundary test. (11) Adopted 2026-08-28: the escalation-logging addition — every escalation in the elicitation interview is logged as data, which question and on what grounds. (12) Ruled 2026-08-28: run metadata's instrument identity comprises the model identity, the definition's content hash, and the assembler version. (13) Ruled 2026-08-28: kinds bind as stamped — the instrument trio as one bundle with a shared spec, the rest standalone, the two disciplines as disciplines. (14) Ratified 2026-08-28: the 2026-08-27 grill-pass resolutions, as implemented in the drafts. (15) Ruled 2026-08-28: warm transcript consultation proceeds with the redaction residue disclosed; transcript content is not quoted into committed records until the secret-scan work closes the residue. (16) Ruled 2026-08-28: the construal extension refines adr-50 — adr-50 stays accepted, the extension states the refinement, and adr-50's related_adrs gains the minted id at filing (adr-55). (17) Ruled 2026-08-28: the record type is the reading record (folder issues/readings/<run-id>/); "detection" stays the name of the Step-6 instrument and its registrative body. (18) Ruled 2026-08-28: pattern-named is an envelope field; the two assembler rules (no include names a directory containing a record family; a reading's object excludes what it exists to change) are adopted; the read-block eval also asserts the instrument's own prior outputs never reach a reading; where the widening reading returns fewer than two configurations, the comparative reading is not exercised and the outcome is recorded as such. (19) Ruled 2026-08-28 (R7): five disposition states with availability by position — admission is accepted (position lives on the envelope); declining a widening proposal is declined, never rejected; the grounds field is disposition_grounds, required on every state except held; the disposition record validates its state against the envelope's position. (20) Authorised 2026-08-28 (facilitator): the build session runs the intent → spec → ship ceremony autonomously for this workstream's filings — adoption, spec creation and approval, readiness, kind binding, shipped moves, and audit ingest — with every act logged; PR merges, reversal flags, new dependencies, and records outside the workstream remain human-gated. The autonomy is deliberate and is itself part of what the cycle observes; ownership of every act rests with the committing identity, per the provenance rules.

  • dcn-26082800000000032026-08-28

    2026-08-28 — Release-pipeline gates: two decisions land together. (a) The semantic receipt_gate moves to the safe side of the tag (adr-52, Alternative 1 accepted): its arming — content-commit resolution plus the fail-closed record-lint --release-gate — now runs in release.yml's verify job, alongside the deterministic gates, gated off the rehearsal path (github.event_name != 'workflow_dispatch') so a receipt-less rehearsal never refuses. The release job keeps only provenance signing (re-derive + attest), and the tag itself is untouched — only the gate moved (iss-2608231226347380). Caveat recorded for a real-release run: auto-release.yml still mints the tag in its tag job before it calls release.yml, so fully eliminating a consumed version on the auto-release path also needs auto-release's tag gated on verify — out of this change's scope, maintainer-verified separately. (b) The reviewed content commit is now derived from the RECEIPTS DIRECTORY (record-lint --derive-content-sha, reading .abcd/work/reviews/<sha>/ of the released tree) rather than HEAD^2^/HEAD^ ancestry, because a batched merge-queue push makes github.sha the batch tip and HEAD^2^ can resolve an unrelated PR's commit past the ancestry guard (iss-355). New Go derivation (lint.DeriveReleaseContentSha + gitutil.IsAncestor) with tests covering the merge, batched-queue, nearest-ancestor, stray/off-lineage, and fail-closed cases; release.yml and the scaffold template (self-scaffold parity held) and the rehearsal (now a batched-queue regression) all use it.

  • dcn-26082800000000022026-08-28

    2026-08-28 — Transcript deep-secret coverage lands as an OPT-IN gitleaks adapter, off by default (iss-96). The native scanner stays the always-on default; a repo arms deeper coverage by dropping an enabled .abcd/config/gitleaks.json, whereupon internal/adapter/gitleaks shells out to a gitleaks binary (PATH or configured path) over the transcript and its findings AUGMENT native redaction through the same scanner.Redact discipline. This realises option (c) of the iss-96 grill (labelled+delimited+high-entropy reach the prefix-anchored native set misses) as the host-delegated/opt-in-adapter pattern (adr: LLM/CLI oracles are opt-in adapters), NOT an always-on entropy detector (option (a), rejected for its redaction false-positive cost on prose) and NOT a hard gitleaks dependency in the default build. Fail-closed, never a silent no-op: an armed-but-absent binary makes capture refuse the write with gitleaks configured but not found. Default-off invokes nothing — no lookup, no process, no cost — so the unopted path is byte-for-byte unchanged. iss-96's residue beyond (c)'s reach (bare no-keyname values, sub-entropy-floor tokens) stays open.

  • dcn-26082800000000012026-08-28

    2026-08-28 — Punctuation enforcement stays mechanical-only (adr-54): the em-dash core shipped as the punctuation/em-dash-in-list-item banned token, corpus evidence (0 TP, unclosable FP classes) rules the colon/semicolon casing lints unbuildable under the warn-then-promote policy, and itd-141 is superseded at its planning interview. Same session: audience-by- placement ratified (adr-53) with the Audience section landing in the writing-style guide; both decisions rest on the 2026-08-28 docs-audience research note.

  • dcn-26082700000000012026-08-27

    2026-08-27: .abcd/work/attribution-rewrite-2026-08-06/ promoted to .abcd/development/research/data/ (iss-2608271707587825) — the tables are historical and complete, durable-record shape; this supersedes the highlight-not-inventory adjudication for that path (intake.md's clearance stands unchanged).

  • dcn-26082600000000072026-08-26

    2026-08-26 — Bug-hunt round 9 (bughunt-b): baseline green on the unshallowed clone. Five parallel hunters, per-finding adversarial refutation: 12 substantive and 5 nitpick findings confirmed and fixed, 4 refuted or prior art — the renderReviewMD provenance gap (open GitHub #325), the receipt sha-width split (two different jobs, machine-derived 40-hex everywhere), the principles-README universal claim (iss-390's scope), and the DECISIONS ordering inversions (order-independent by declared union-merge design). Fixed with provenance: capture --blocked-by existence probe, intent verbs resolving spec_id by number, ScanSpecLinks failing closed, cleanLessonProse delegating to CleanProse, firstRootSHA bounded, RD002's one-pass DMRT history scan with a cases harness, record_schema's required-frontmatter invariant with the issueschema leaf plus the repaired live record, the RS001 terminal-folder wording at three sites, the plugin-command count, the derived-changelog Breaking clause with adr-37 amended, the data-theme claim, CI-account rosters, the disciplines intent-auditor sweep with spc-28's late-sweep amendment, itd-5's task_classes source of truth, itd-43's glossary reconcile, itd-24's core/epic entry, and the install-template eol pin. Recorded open: the unknown-property half of the ledger-visibility gap and itd-5's struck-tiebreak residue.

  • dcn-26082600000000062026-08-26

    2026-08-26 — Bug-hunt round 9 (bughunt-a): baseline green after unshallowing the environment's clone. Five parallel hunters returned 21 candidates across the four dimensions; per-finding adversarial refutation confirmed 5 substantive and 4 fixable nitpicks and refuted or deferred 12. Fixed and resolved with provenance: the memory-store guarded-read sweep (every reader outside ingest followed a committed symlink unbounded — five reproduced hangs), the issue-resolution gate's swallowed git probes (a dubious-ownership refusal read as an empty ledger, exit 0), lint-config severity validation with strict decoding (off-enum severities counted toward no exit code), the docs-lint renderer's unsanitised config-derived fields, runBounded's whole-buffer trim corrupting the first NUL-list entry, privacy-hygiene's silent skip of unreadable tracked files, the terminology page's corpus "ships" overclaim, the intake S4 container pin below the module toolchain, and the site command description's missing check-write disclosure. Recorded open: the scanIntentTree ENOENT-parting alignment (all claimed triggers proved closed upstream). Refuted with prior art: the spc-28 planned/drafts sweep (iss-94 convention), the verification-matrix capture-promote row (iss-2608231346137587 embargo), the attribution fence guard (iss-270 wontfix; zero verdict flips across all historical PR bodies), isHexSHA 40-hex (prior round's refutation stands), frontmatterOpen's comment latch, the skew-meta precedence claim, guard check's exit-2-on-disabled (specified), the prepare-this-repo bucket gloss, the MADR label, the itd-27 pronoun candidate (a cited real person is outside the persona rule), and the record-lint job-name mismatch (mirror is correct by construction). nitpicks-only: no.

  • dcn-26082600000000052026-08-26

    2026-08-26 — Bug-hunt round 8 (bughunt-b): baseline green after unshallowing the environment's clone (the shallow false-red itself became a finding). Five parallel hunters returned 16 substantive candidates and 7 nitpicks across the four dimensions; per-finding adversarial refutation confirmed 9 substantive and 4 fixable nitpicks and refuted 5 — the merge-queue RS001/RS002 skip (RS003 at the batch head plus the push-to-main range cover it, the attribution/external-review exemption shape), the ungated mkdocs half (adr-48's deploy-fail-closed design plus the preview job on every main push), the CODEOWNERS baseline gap (round-3 prior adjudication; external-review is strictly stronger), the site verb-roster counts (inside iss-2608231346137587's do-not-hand-fix corpus), and the site-render depth-1 gate (shallow history changes bytes, never the exit). Fixed and resolved with provenance: gitutil.RepoShaped three-state fail-closed (privacy-hygiene scan, private banlist write gate), capture/record-lint quoted-null parity at the gate, the RS001 deleted-record hole, shallow-checkout refusal in both history gates, the pre-push roster plus its detector blind spot, scanner config containment via ReadGuardedInRoot, phase-audit design-target corrections, invariant 12's SessionEnd clause assertion, the install guide's installer subject, verify-as-subset framing, skew-tripwire messages, and persona pronouns in two planned intents. Recorded open: the memory store-lock S_IFMT mask (rides iss-129), the quoted-enum impact split, and a deferral-currency detector seed.

  • dcn-26082600000000042026-08-26

    2026-08-26 — Bug-hunt round 8 (bughunt-a, state #368): baseline green; five parallel Opus 4.8 hunters across the four dimensions, each candidate adversarially refuted by a fresh independent subagent. 9 substantive confirmed and fixed, 3 refuted as prior art/design. Code: iss-2608261206490430 — the disembark scan fell open to a wide read on an all-ignored repository (an empty ls-files listing was conflated with a git failure; now parted, with a watched-fail test). Infra: iss-2608261206505385 — site check ran in no gate before a release published, so a check-only trip failed after the binaries shipped (now run in the Makefile site-render recipe and the ci.yml step); iss-2608261206507510 — RS001 unioned its leaves-open and enters-closed id sets, so a bare git rm of an open record satisfied a Resolves trailer while the record vanished from the ledger — corrected to require the id to ENTER a terminal folder (the refuter's intersect recommendation would have broken fresh-capture-and-resolve in the same PR; caught and verified before shipping). Docs/record: iss-2608261206491486 — disembark's .gitignore guarantee scoped to the free-text tree scan, since pack copies declared records verbatim regardless; iss-2608261206506035 / iss-2608261206505136 / iss-2608261206508851 — the shipped/ intent-auditor entry precondition, the roadmap Planned spec-link claim, and the surface contract's "shipped/ is empty" all corrected to the close-only lifecycle (20/43 planned intents legally hold spec_id null; shipped/ holds 18); iss-2608261206504574 — CONTRIBUTING repointed from the hand-written CHANGELOG flow to the derived one; iss-2608261206504710 — eleven live brief citations moved from the retired adr-18 to its successor adr-28. Refuted: the ScrubbedEnv/GIT_CONFIG_GLOBAL candidate (already adjudicated round 5), install.md SessionStart stderr (deferred iss-2608251011427187 / open iss-253), and the submodule-walk drop (aligned with the vendor-skip design; iss-133 wording family). nitpicks-only: no.

  • dcn-26082600000000032026-08-26

    2026-08-26 — The changelog is an INDEX of record transitions, not a curated release note: every record reaching a terminal folder earns its line, with no inclusion judgement. Rationale lives in the record; the changelog is the trace from record to version, which is why a record does not carry its own release. Consequences: impact keeps its version arithmetic and LOSES its silencing job; two families the cut ignores today (principles, ADRs) come into scope; bundling stays, because fewer lines carrying the same information is the "better" half, while dropping a record for dullness is not. shipped_in (iss-2608241612087533) is reclassified as MIGRATION-ONLY: abcd was built before RS001 made resolution ride the fixing commit, and a repo managed from its first commit should never set it. Not yet implemented — captured, so the change lands behind a record like everything else.

  • dcn-26082600000000022026-08-26

    2026-08-26 — "Less, but better" (Rams) adopted as a guiding principle. Design for the STEADY state, not the migration in front of you; name a migration accommodation in the mechanism itself or it becomes permanent by default. Recorded as a principle.

  • dcn-26082600000000012026-08-26

    2026-08-26 — bughunt round 7 (state #368): hardened the new issue-resolution gate scripts. check-issue-resolution.sh now cd's to the repo root (RS003 no longer passes vacuously from a subdirectory), extracts iss-ids non-fatally (a non-record file last in the diff no longer silently aborts RS001/RS002 under set -e), and RS002 reads each changed record's frontmatter via a helper shared with RS003 instead of the raw diff (a body-level commit: example is no longer reachability-checked); check-issue-resolution-cases.sh gained the check-attribution-cases hermetic git-env scrub (iss-28/iss-313 sibling authored four days after that fix). iss-2608261040378346, iss-2608261041020040. Doc corrections: the 05-internals and 04-surfaces indexes no longer call the shipped site check gates / explorer / deploy design targets (10-site.md is the correct side; adr-48), brief/README nine→ten internals chapters, capture.md --shipped-in named as derivation-time not resolve-time validation, CONTEXT surface_coverage bullet names the sub-verb CLI-tree pass. iss-2608261041027043, iss-2608261041029596, iss-2608261041027268, iss-2608261041020419. Recorded not fixed (autonomous-scope limits): release.yml feeds an unvalidated tag into make build's -ldflags shell recipe — a shape-check-parity gap vs site.yml, insider-bounded, deferred because CI cannot exercise the release pipeline (iss-2608261041218890); the principle spec-moves-with-the-surface sits unpromoted while its named surface_coverage gate is armed at blocker — promotion is a governance act for the maintainer (iss-2608261041210476). Refuted: a resolved_by bare-null "regression" (the shape is unwritable and the new rejection removes a phantom empty-pointer); the release.yml verify job "not mirroring ci" (a deliberate, gate_lockstep-checked subset).

  • dcn-26082400000000022026-08-24

    2026-08-24 — Bug-hunt round 5 (bughunt-a): baseline green; five parallel hunters (core code, newer code, infrastructure, docs-vs-functionality, internal record consistency) on this v0.6.3 tree returned four genuine nulls and one confirmed substantive record finding, adversarially refuter-survived. Fixed iss-2608240806090544 — planned/README.md categorically claimed every intent carries a spec_id: spc-N link, but 20 of 43 planned intents legally hold spec_id: null (the lint-enforced intent_lifecycle state, the surface contract 05-intent.md, and adr-34's orthogonality); the subheading silently reintroduced the over-narrow framing adr-34 already corrected in the parent intents/README (resolved iss-3). Rewritten to the authoritative wording. drafts/README refuter-cleared (describes the promotion transition, not current contents) — kept out of scope. Persona-pronoun drift in a frozen dated implementation-prompt transcript logged as considered-and-rejected (historical artefact; the shipped intent itd-135 already reads they/them).

  • dcn-26082400000000012026-08-24

    2026-08-24 — bughunt round 5 (state #368): corrected the shipped-intents bucket README drift — the false "directory is empty" claim (18 shipped intents present; the parent index already reads populated) and the retired intent-fidelity-reviewer name (→ intent-auditor, spc-28; the sibling front-door the iss-334 sweep of the parent index missed). iss-2608240815458212, iss-2608240815453131. A concurrent second firing of the hunt-a routine took the bughunt-a/round-5 branch and PR #480 (planned/ bucket README) at the same time; these disjoint shipped/ findings ship on bughunt-a/round-5-2 rather than clobber a live peer's branch. The persona nitpick in the abcdev-site prompt was dropped (that firing logged it considered-and-rejected as a frozen historical artefact); the one code candidate — frontmatter.Fields duplicate-key first-wins — was refuted (every lint status read shares the one first-wins map, first-wins is the documented contract, the exemption was already audited in iss-39).

  • dcn-26082300000000042026-08-23

    2026-08-23 — Manual-test triage rulings (maintainer): (1) spc-38's "every visual has a table twin" is amended — a twin is dropped wherever the visual already carries the same labels and numbers as text; the relationship chart's list twin stays (spc-39 AC 4). (2) spc-39's reduced-motion behaviour (list in place of the chart) is re-confirmed as ruled — not a defect. (3) Record sub-nav iconography uses text glyphs as ui.json interface strings, never image assets (keeps adr-47's picture rule untouched). (4) The Genealogy release-cadence list is dropped now; a commits-per-release-window ridgeline is its candidate replacement, designed within the IA-restructure intent seed (iss-2608230752354909).

  • dcn-26082300000000032026-08-23

    2026-08-23 — ideate: abcd-research-verb — verdict killed. The idea, the three legs, and the rejected alternatives: .abcd/development/research/notes/2026-08-23-ideate-abcd-research-verb.md

  • dcn-26082300000000022026-08-23

    2026-08-23 — SOTA-protocol proposal adversarially reviewed (two fresh-context reviewers, disjoint lenses, authorship stripped): verdict REFRAME — the no-verb deferral stands, but on script-first-mvp's actual trigger (contract uncertainty) alone. Withdrawn: the thin-corpus argument (the genre corpus is ~13 notes, and ideate's own validator was minted after three manual runs, so corpus size is not the criterion). Repaired: reviewer yields reclassified as session testimony; feeder claim downgraded to expectation (no ideate run has consumed a *-sota.md note yet); protocol gains step 6 — every survey note records its review verdicts inline, without which the revisit condition is undetectable. Repairs applied to the protocol note and both survey notes.

  • dcn-26082300000000012026-08-23

    2026-08-23 — abcd site check excludes docs/ at the page walk, rather than teaching the parser to tolerate HTML comments on SSG-authored pages (iss-2608230838592910's own candidate fix, rejected). Tolerating comments would admit mkdocs-material output into gates whose rules were written for generator output — the provenance walk and banned-token gate already exempt the tree via isComposedSurface, so only the mobile and figure-label gates would newly run over markup this repo cannot act on. Those pages never entered the page list on any prior revision either (the parser has always refused comments), so the exclusion removes no coverage that existed; it states the boundary the overflow audit already draws. The cost is recorded honestly in the gate's own scope comment: a green report describes the pages abcd renders and no others, and docs/ layout stays the SSG's own concern.

  • dcn-26082200000000122026-08-22

    2026-08-22 — ideate: cli-verb-taxonomy-restructure — verdict reframed. The idea, the three legs, and the rejected alternatives: .abcd/development/research/notes/2026-08-22-ideate-cli-verb-taxonomy-restructure.md

  • dcn-26082200000000112026-08-22

    2026-08-22 — SOTA research protocol captured, no /abcd:research verb minted (session assessment; adoption is the maintainer's gate). Three research runs (context-window management ×2 passes, local MLX models) followed the same shape — parallel research pass, dated *-sota.md synthesis with per-technique fit challenges, lint gates, fresh-context adversarial reviewers with disjoint lenses (source fidelity / repo fidelity), every finding applied. Assessment: /abcd:ideate does NOT cover SOTA research (idea-with-verdict vs question-with-survey; a survey is ideate's leg-1 feeder, not its overlap); /abcd:consult + /abcd:ingest cover the sources-corpus side; execution stays host-delegated. Rejected alternative: minting a research-record validator verb now — fails script-first-mvp (thin genre corpus, tier vocabulary still moving). Protocol + revisit condition recorded in .abcd/development/research/notes/2026-08-22-sota-research-protocol.md.

  • dcn-26082200000000102026-08-22

    2026-08-22 — Website build rulings, from the slice reviews (the interview's nine rulings stand; these refine them): the featured-quote derivation skips a press release that is one of the two minted placeholder templates — mechanical template match, no other filtering, order still entered-shipped descending then id descending. abcd site check holds /references/ to the composed rules even though the manifest selects no span there — a page must not escape the single-source rule by being unnamed — and implements the attribution escape as verification against the trailers git carries, never as an exemption. The deploy stamp contract: production passes --version bare (the renderer prepends v; vv0.6.1 fails the gate) and previews pass --preview (renders unreleased · <commit>); --date is never injected — the CHANGELOG heading is the release date per adr-37. install.md's lead lands with the first successful deploy, reading spc-40's "same change that first serves the script" as the deploy, so the docs never name an endpoint that 404s. Build order is fixed: site build first, mkdocs -d site/docs second — the purge makes the reverse loud.

  • dcn-26082200000000092026-08-22

    2026-08-22 — All-dimensions bug-hunt round 7 (branch bughunt-b/round-7). Fixed 11 substantive and 4 nitpick findings across five hunt dimensions, each adversarially refuted before fixing and each behaviour change pinned by a watched-fail test. Security/code: the guard tokenizer now recognises $'...' ANSI-C and $"..." locale quoting (a Tier-1 blocker bypass); the hard-fail local_username redaction matcher folds case; five site-generator fixes (SVG prolog/comment/CDATA build-vs-check disagreement, unparsed-page gate masking, unscreened repository href scheme, record-id collision, non-ASCII path dates); the launch scaffold's symlink path leak and its ./internal/... race leg that wedged a bare adopter; a capture skipped[].error absolute-path leak. Infra/docs/record: CODEOWNERS now covers site-src/ and docs/requirements.txt; the shipped abcd site check is called shipped in the brief and pinned in the release-gate manifest; the site-build read set, the writing-style escape scope, the invariants and evidence-chapter banners, and several doc/string nitpicks corrected. The guard brace-expansion bypass ({--force,}) is recorded open (iss-2608221457227161) as a distinct expansion-not-quoting follow-up. Refuted/out of scope this round: the site.md "runs in CI" claim (in-flight PR #436), the iss-315 guard-warn citation, the install-surface transport-pin and -q deltas (defence-in-depth, no reachable attack), the record-lint job-name and prepare-this-repo template path (prior art iss-304/iss-87).

  • dcn-26082200000000082026-08-22

    2026-08-22 — Writing style guide: One canonical reference page (docs/reference/writing-style.md) consolidates the scattered prose rules (British/US split, present tense, Diátaxis) and adds the punctuation rules (no em dash in list items — use a colon; capital after a colon; lower case after a semicolon), every rule labelled machine-enforced or review (enforcement-claims-are-facts). The DOCUMENTATION domain in .abcd/rules.json points at the guide (the OPINIONS pattern — point, don't copy); the machine-checkable punctuation subset is staged as itd-141 (native docs-lint now; Vale recorded in the intent as Related/SOTA and the named preferred future upgrade path; adopting an open-licensed guide — Google / Microsoft / GitLab / errata-ai styles — explored at the intent's SOTA pass). No ADR unless a new rule family emerges.

  • dcn-26082200000000072026-08-22

    2026-08-22 — Interview-workstream records filed (the 2026-08-22 handover's items 5-9, three itd-84 hand-runs graded into the calibration note): itd-142 (the brief-creation interview) filed as a DRAFT with its spec explicitly waiting until the collaborating prototype has run once — no speccing ahead of that run; adr-50 + brief invariant 14 (framing traces never enter the record, automated reviewers never read them; local side lives in .abcd/.work.local/); principle widen-options-never-recommend (at most three construals, ceiling not target, null always available, no recommendation markers); itd-143 (framing chapter under 01-product/, with its brief-lifeboat mapping row) — itd-142 refines itd-90, surfaced by the candidate pass before minting; adr-51 + intent-template additions (optional Mechanism and Scope Conditions sections, enforcement an explicitly deferred discipline question); hold-route seed iss-2608220750029991 stays OPEN (RFC-vs-intent undecided, tied to the hold-register home question now recorded in the evidence chapter); glossary README names the glossary a deliberate frame surface; ACKNOWLEDGEMENTS credits mattpocock/skills for the glossary format and the frontier-questioning pattern in the change that adopts it. Open sign-offs carried in itd-142's Open Questions: the escalation rule, one-vs-three intents at the final round, a held working-principle at the final round.

  • dcn-26082200000000062026-08-22

    2026-08-22 — Bug-hunt round 7 merge gate (PR #415, resumed after the round's session ended between PR-open and gate). origin/main (the site-build and itd-112 merges) merged into bughunt-b/round-7 cleanly; baseline green on the merged tree; all 12 CI checks green. Dual pre-merge review: the Opus 5 reviewer returned NO-SHIP with three remediable blockers, the Fable 5 reviewer SHIP with the same frontmatter residual flagged non-blocking. All three remediated with tests watched to fail under mutation of each fix: the update dispatch-refusal receipt now redacts target_path at construction (refusalReport seam; it had shipped the raw home root beside the redacted detail), capture list --json now emits [] not null for empty issues/skipped (the CHANGELOG claim is now true), and the repolint cap+1 grown-file branch is pinned through a capRead seam (the prior boundary test passed against the pre-fix read, so nothing guarded the +1 — the round-7 "closed by construction" exception is retired). Residuals captured open, not widened into the PR: iss-2608221126066379 the frontmatter BOM tolerance now diverges from the sibling parsers whose comments promise byte-exact parity (fail-closed, comment-invariant falsified); iss-2608221126066631 the guard process-substitution redirection family still allows a glued blocker flag (pre-existing, same family as the fixed &>). The reviewer's probe-horizon concern was refuted in-session: isBinary self-caps at 8 KiB, so both oversize branches agree.

  • dcn-26082200000000052026-08-22

    2026-08-22 — Website decision interview (nine questions, all ruled): retired ADRs render as baseline stubs, no tombstone files (revisit labels on real use); /record/ pages carry full bodies, the issue ledger is opted in for this repo, and every condensed view is countable-only — counts, dates, ids, titles — never prose written for the site; the featured intent is derived (newest entered-shipped/, id descending tie-break, no pin); the README migration lands as drafted, every heading entering the repo before the site may select it; the contributors page publishes per-model Assisted-by tallies under the attribution escape with a separate labelled bots-and- tools row (.mailmap canonicalises the pre-policy commit); analytics are declined outright — no scripts, no trackers, nothing that could require a consent banner (edge request counts suffice); the prototype's artifact URL stays out of the committed record; the prototype itself stays in local scratch until the private-banlist sources-sync anchors its short patterns (iss-2608220150157507); token usage becomes a local-only history-store datapoint with explicit-ask pricing (iss-2608220150157508). Amendment traceability added to itd-137 (last-touched links the record's git history); a foundations page (principles and disciplines, lists-and-links) added to itd-136; itd-140 cross-references script-first-mvp as its general form.

  • dcn-26082200000000042026-08-22

    2026-08-22 — The abcdev.app website enters the record: adr-47 (rendered from this repository alone; single-source rule; the adr-30 amendment "never bundled, rendered read-only"; the generic/specific boundary carrying the reframed generalisation verdict) and adr-48 (deploys per release from the tag via the release chain — release: published never fires for GITHUB_TOKEN-created releases — with a source-built labelled preview on main and dispatch-from-latest-tag emergencies). Intents itd-135 (landing page, umbrella), itd-136 (record explorer pages), itd-137 (relationship chart + genealogy), itd-138 (install.sh); itd-139 (generic explorer on a second instance) held in drafts pending its fixture demonstration; itd-140 (generic/specific boundary discipline). README migration and the site verb family recorded as plumbing in brief 05-internals/10-site.md. The migration bundle stays zipped in research/abcdev-site/ because record-lint links_resolve rightly refuses an unpacked copy whose links resolve only at their Phase-1 destinations. A same-day adversarial review reframed the "standardised README for every managed repo" idea to offered-never-imposed (2026-08-22 research note; future-work seed in the ledger).

  • dcn-26082200000000032026-08-22

    2026-08-22 — ideate: record-explorer-generalisation — verdict reframed. The idea, the three legs, and the rejected alternatives: .abcd/development/research/notes/2026-08-22-ideate-record-explorer-generalisation.md

  • dcn-26082200000000022026-08-22

    2026-08-22 — ideate: abcdev-site — verdict survives. The idea, the three legs, and the rejected alternatives: .abcd/development/research/notes/2026-08-22-ideate-abcdev-site.md

  • dcn-26082200000000012026-08-22

    2026-08-22 — Bug-hunt round 7, branch bughunt-b/round-7. Baseline (make preflight

    • gofmt -l .) green before any change and on the final tree; started from main at 9db1316. Five parallel Opus 5 hunters swept the four dimensions; each candidate was adversarially refuted by an independent Opus 5 subagent before capture. Findings: 8 substantive (2 major, 6 minor) + 8 nitpick confirmed, 7 refuted/prior-art; nitpicks-only: no. Fixed and resolved this round, each behaviour-changing code fix carrying a test watched fail before the change and pass after (the repolint size TOCTOU excepted — closed by construction, its boundary test guards the cap not the race): iss-2608220131352917 the guard tokenizer read a leading & as a background/&& operator, so a glued or spaced &>/&>> both-streams redirection split the simple command and dropped its dangerous flag out of command position — a silent allow on every blocker-tier entry; now recognised as a redirection before the list split, target dropped, fd digit kept. iss-2608220134344680 the frontmatter scanners anchored on line 0 and TrimSpace does not strip a UTF-8 BOM, so a BOM- or multi-line-comment-led record slipped the no_git_metadata blocker and the record_schema gates; shared frontmatter.TrimBOM plus a stateful multi-line-comment skip in the lint and glossary scanners. iss-2608220142158516 abcd update and abcd history leaked the absolute home root into their success/refusal envelopes (text and --json), including the plugin-session refusal the plugin relays into agent chat; redacted to ~ via a new fsutil.RedactHome at the render boundary. iss-2608220136593438 ahoy tested .git for dir-ness, so a linked worktree or submodule (gitfile .git) was misclassified as an unmanaged folder and ahoy install exited 0 aborted with a wrong reason; now tests existence, the last isDir(.git) holdout after iss-72. iss-2608220136597127 ahoy --json serialised a never-computed all-false guard object for an unmanaged folder; the field is now a pointer omitted for a folder, matching the Banlist sibling. iss-2608220144233519 the repolint privacy scanner read exactly the cap, so a file grown past it during the read was scanned as a truncated prefix and reported clean; now cap+1 with the grown file routed to the not-scanned path. iss-2608220147106835 spec/intent/memory/capture emitted bare null for an empty --json collection; the constructors seed them non-nil so an empty store marshals []. iss-2608220150151397 the mental-model brief claimed zero live bundles while four planned intents declare a bundle-member of spc-83 (residual of iss-123's README-only fix). Nitpicks: iss-2608220142154022 update.Plan had no default so an unknown target kind fell through to swap (now fail-closed); iss-2608220145356167 docs lint returned an engine fault as exit 1 not 2; iss-2608220148289898 abcd adr-N routed by a fixed %04d filename prefix, missing a differently-padded ADR file (spc-26 amended); iss-2608220149008905 the pull_request_target checkout guard external-review.yml states in prose was unarmed (now a workflow-walking test); plus the doc corrections iss-2608220150157497 (adr-22/26 links), iss-2608220150154972 (version.md install_mode), iss-2608220150152332 (CI classifier standdown), iss-2608220150152535 (docs requirements transitives). Refuted / prior art (kept out of the ledger): the abcd-cli name in commands/launch.md (the live internal project name, record-lint-prescribed); the spc-3 predecessor-store collision in intents/README (a new instance of open iss-239, carried there); the .abcd/work roster intake.md/attribution-rewrite omission (round 4's highlight-not-inventory doctrine still governs); the CI gitleaks same-origin checksum (adr-46's accepted trust bar, residual tracked as open iss-379); the go.mod vs setup-go patch coupling (GOTOOLCHAIN=auto self-corrects); the Makefile CRLF eol pin (GNU make strips the CR on POSIX); and the wrangler/mkdocs docs-site deploy pin (dashboard-side, not an in-repo mechanism). Model routing: orchestration on Claude Fable 5; five parallel hunters and twenty-two per-finding adversarial refuters on Claude Opus 5; the dual pre-merge review runs one reviewer as Claude Opus 5 and one as Claude Fable 5.
  • dcn-26082100000000042026-08-21

    2026-08-21 — Bug-hunt round 6, branch bughunt-b/round-6. Baseline (make preflight

    • gofmt -l .) green before any change and on the final tree. Five parallel Opus 5 hunters swept the four dimensions; each candidate was adversarially refuted by an independent Opus 5 subagent before capture. Findings: 8 substantive + 2 confirmed doc/CLI, 5 refuted, 1 (I2) reverted on implementation. Fixed and resolved this round (each behaviour-changing code/script fix carries a test watched fail before the change, the lifeboat probe size-TOCTOU excepted — that race is closed by construction and its boundary test guards the cap, not the race): iss-2608211849467013 the guard tokenizer did not know shell redirection operators, so a glued redirection (git push --force>/dev/null) mutated the flag token and the blocker missed — a silent allow — and a leading redirection degraded a Tier-1 block to a warn; the tokenizer now drops a redirection and its target. iss-2608211849463840 the record/docs lint reporting walk read cfg.Roots with a raw os.ReadFile and no containment while the sibling citation collector guards the same field, so a cloned repo's committed lint config could read/lint/follow a file outside the tree (reproduced: escaping root, symlinked leaf, /dev/zero OOM) — routed through containedRepoPath/resolvedInsideRoot/containedRealPath/ReadGuarded, and the sibling glossary_dir walk in loadForbiddenSynonyms (the same cloned-repo-config read path, caught by both pre-merge reviews) was swept through the same stack; the remaining config-derived record reads in the lint package are tracked as a follow-up (iss-2608211914592726). iss-2608211849461061 frontmatter.Fields requires --- on line 0, so a comment-led record (13 glossary term files) slipped the no_git_metadata blocker; the lint-local frontmatterFields now slices past the comment, preserving absolute line numbers. iss-2608211849466878 citation DaysBetween took each date's local calendar day and restamped UTC, making staleness and the release-gate overdue blocker timezone-dependent; both ends now convert to UTC first. iss-2608211849468791 the attribution gate's trailer/None presence checks are line-end-anchored over a class excluding CR, so a CRLF web-UI pull-request body false-red a correct trailer on the required check; check_text now normalises CRLF before every rule, with CRLF corpus cases. iss-2608211850070541 identity init faults exit 2 (was 1); iss-2608211850074600 the lifeboat probe read cap+1 and refuses a file grown past the cap (size TOCTOU); iss-2608211850070318 history list --json emits [] not null. Doc/record: iss-2608211849581263 + iss-2608211849583757 the persona brief said the picker chooses at random and omitted Nia (a residual of resolved iss-300 — selection is by role, never by name; roster is fourteen); iss-2608211849583208 the bundled INTENTS default persona rule reached this repo's own intent authors because .abcd/rules.json never overrode INTENTS, so an INTENTS override now points authors at the registry (the default stays correct for a registry-less adopter); iss-2608211849580624 the README described download-on-every-update and a no-op .binary-meta remedy, rewritten for the spc-35 persistent cache; iss-2608211849582190 CONTRIBUTING granted the fenced-quotation carve-out for commit messages too, now scoped to the pull-request body. Refuted / considered-and-rejected (kept out of the ledger): R3 the release-gate manifest prompt naming ten of twenty commands (an illustrative grounding string, not a gated inventory, and editing it ripples into receipt hashes); R4/R5 related_adrs and prose citations of superseded ADRs (resolve via the retired-set mechanism, deliberate historical provenance); R6 "11 adapters" vs "five capability seams" (implementations vs categories, not a contradiction); R7 the adr-13 bare path to itd-36's old bucket (a benign ungated breadcrumb; the authoritative related_intents resolves by id); the update.go redirect-host case-fold (fails closed, availability only, impractical to test through a loopback redirect). I2 (release.yml "dormant until the public flip" comments) was implemented then reverted: release.yml is a scaffold template rendered for adopters who may be private, so the visibility-flip framing is generic-correct there, unlike the abcd-specific runbook round 4 corrected. Model routing: orchestration on Claude Fable 5; five parallel hunters and eight per-finding adversarial refuters on Claude Opus 5; the dual pre-merge review runs one reviewer as Claude Opus 5 and one as Claude Fable 5.
  • dcn-26082100000000032026-08-21

    2026-08-21 — Bug-hunt round 5, branch bughunt-b/round-5. Baseline (make preflight

    • gofmt -l .) green before any change. Five parallel Opus 5 hunters swept the four dimensions; each candidate was adversarially refuted by an independent Opus 5 subagent before capture. Findings: 4 substantive, 9 nitpick, 9 refuted. The C1 ScrubbedEnv/GIT_CONFIG_GLOBAL candidate split the refuters (one CONFIRMED, one REFUTED); adjudicated REFUTED — keeping the developer's global git config readable is deliberate and test-pinned (TestScrubbedEnvStripsHijackKeepsGlobalConfig), the attack needs control of abcd's process env (out of scope under the trusted-env model), and the obvious fix (scrub to /dev/null) would blind the redaction probe for every developer whose identity lives in global config. Fixed and resolved this round (code, each with a watched-fail test): iss-2608211432258689 launch --dry-run printed WouldRefuseOn unsanitised so a committed control-char filename injected raw terminal escapes into the preview and CI log (now termsafe); iss-2608211432257954 the same dry-run leaked a raw absolute path in lockstep.detail (a success envelope that never passes the error-surface scrub) — stripped at loadJSON; iss-2608211432258975 abcd lint mapped a rule-engine fault to exit 1 (the tri-state's warnings-only code) so a CI gate keying on >=2 read a lint that never ran as an advisory pass — now exit 2; iss-2608211432254405 launch scaffold deriveBranch assumed .git is a directory, stamping the fallback branch main into the generated release workflows from a linked worktree — now resolves the gitfile (worktree gitdir HEAD + shared commondir origin/HEAD). Nitpicks fixed: iss-2608211432389181 the intent verdict reader was the last CLI operand on Lstat-then-os.ReadFile (false benign-TOCTOU comment) — routed through fsutil.ReadGuarded; iss-2608211432384430 the history rootSHA diagnostic named only 40 chars though the regex accepts 64 (SHA-256); iss-2608211432384091/389477/389791 three user-facing doc claims (README SessionEnd self-bootstrap overclaim, memory.md source.class vs source_class, ahoy.md missing the shadowed-on-PATH install_mode suffix); iss-2608211432489481/489288/482363/483805 record hygiene (seven display-text/href link mismatches, two bare paths to absent dirs, the rfc-1/itd-26 one-sided pair, the work-tier roster omitting the issue ledger/reviews/rulesets). Refuted / prior art (kept out of the ledger): C1 above; C2 folding local_username to case-insensitive (net-negative — broadens a documented hard_fail false-positive class and reopens iss-31); S3 widening hasControlChar (the render sanitiser, not the integrity gate, is the fix); S4 launch --no-index dropping a force-added tracked file (dry-run preview writes no artefact, exclusion is visible and over-exclusion is the safe direction); D2 guard check exit-2 enumeration (the governing "could not be evaluated at all" definition already covers a disabled registry); R2 itd-3 spc-1 (a documented, minting-honored reservation). Model routing: orchestration on Claude Fable 5; five parallel hunters and nine per-finding adversarial refuters on Claude Opus 5; the dual pre-merge review runs one reviewer as Claude Opus 5 and one as Claude Fable 5.
  • dcn-26082100000000022026-08-21

    2026-08-21 — Visual identity roles (itd-133, maintainer-ruled at the planning interview): the block-pixel duckling is the mascot; the a-b-c-d signal-flag hoist (true ICS geometry at full size) is the official logo of the terminal surfaces (CLI and plugin); a small lifeboat marks the lifeboat verbs; the existing docs/assets/img/logo.png remains the forge/web logo for now. One pixel-grid source of truth in the Go tree; all terminal rendering behaviour stays with itd-112. This forecloses itd-112's object-vs-text-logo open question — the object is the flag hoist.

  • dcn-26082100000000012026-08-21

    2026-08-21 — Bug-hunt round 4, branch bughunt-b/round-4. Baseline (make preflight

    • gofmt -l .) green before any change. Five parallel Opus 5 hunters swept the four dimensions; each candidate was adversarially refuted by an independent Opus 5 subagent before capture. Findings: 8 substantive, 7 nitpick, 2 refuted. Fixed and resolved this round (code, each with a watched-fail test): iss-2608211132061930 (MAJOR) lint.LoadConfig read the docs-lint/record-lint config with a raw os.ReadFile while its .abcd/*.json siblings guard.Load/rules.Load/positioning.LoadConfig all guard it — hook-reachable (ahoy.Detect) and cross-repo-clonable, so a committed config symlink to a FIFO wedged docs lint/lint/ahoy/hook/cite refresh, /dev/zero OOMed the CLI, and an out-of-repo target ran the whole ruleset from a file the repo does not own; now fsutil.ReadGuarded + an Lstat dir-symlink refusal. iss-2608211134281912 four stdin operand readers (ideate/lessons/synthesis/readSource) read exactly cap and silently truncated an over-cap payload — worst on history capture (stored an 8 MiB prefix under a sha256 idempotency key over the prefix, breaking spc-4's refuse-whole invariant); added readCappedStdin (cap+1 probe). iss-2608211139076040 the iss-392 canonRecordID fix left four sibling lint keyspaces raw (delivery_state bucket + citation, spec intent-existence, superseded_by, spec_id_unique), so a zero-padded id slipped a gate open or false-blocked a link; routed every key and lookup through canonRecordID. iss-2608211140410761 abcd adr-N confirmed the frontmatter id byte-exact while record-lint and the citation resolver treat padded/quoted/cased ids as one handle, reporting a present ADR absent (and abcd adr-0003 routing then refusing); now a parsed-handle compare rendering the canonical id. Docs/record fixes: iss-2608211142146585 + iss-2608211142142469 the release-gate runbook claimed the verify job runs macOS+Linux (it is ubuntu-only; ci.yml's check job is the matrix and the merge gate) and framed the semantic-receipt gate as dormant-until-public-flip though it is public and has fail-closed two releases (v0.3.0/iss-108, v0.6.0/iss-326). iss-2608211142496517 cmd/scaffold-sync named a "scaffold-sync workflow" that was built and rejected (iss-209). iss-2608211143184945
    • iss-2608211143185943 the README Go badge (1.25→1.26) and the retired "next free id" capture description. iss-2608211144265046 commands/lint.md documented a line:0 sentinel the omitempty JSON never emits. iss-2608211144555085 the ADR index omitted the accepted adr-45 row (third recurrence of the class; iss-38 wants such indexes gated). iss-2608211145448208 the DCO deferral text adr-43 retired survived in AGENTS.md and scripts/check-attribution.sh. iss-2608211146222734 the banned pre-adr-30 "roadmap/intents" literal survived in AGENTS.md and .abcd/README.md, outside the lint roots. iss-2608211146562243 RD001 was documented unconditional though check-reviews.sh exempts 7 of 10 live dirs (sha-keyed receipts). iss-2608211147403129 the ADR-RFC frontmatter pairing contract disagreed across three surfaces; reconciled rfcs/README.md and rfc-2. Refuted (kept out of the ledger): the CHANGELOG [Unreleased] Fixed-vs-additive sectioning (the cut discards Unreleased prose and re-derives sections from records; owned by open iss-256); the .abcd/work tier map "omission" (highlight enumerations, not inventories; iss-333 already blessed the table); and the launch DenyNamespaces case-fold symlink slip (inert — the hardlink alias map rejects via aliasDenied). Model routing: orchestration on Claude Fable 5; five parallel hunters and ten per-finding adversarial refuters on Claude Opus 5; the dual pre-merge review runs one reviewer as Claude Fable 5 and one as Claude Opus 5.
  • dcn-26082000000000092026-08-20

    2026-08-20 — ideate: deterministic-delivery-pipeline — verdict reframed. The idea, the three legs, and the rejected alternatives: .abcd/development/research/notes/2026-08-20-ideate-deterministic-delivery-pipeline.md

  • dcn-26082000000000082026-08-20

    2026-08-20 — Bug-hunt round 3 (hunt B), branch bughunt-b/round-3. Baseline (make preflight + gofmt -l .) green before any change. Captured iss-382..iss-392 (11 records), each adversarially refuted before capture. Fixed and resolved this round: iss-382 disembark plan's RenderManifest printed source-repo file paths raw while the same view sanitised its neighbours (terminal-escape injection over an untrusted source repo); iss-383 the history transcript store's read path used raw os.ReadFile while its write path was fully hardened, so a planted FIFO wedged history capture under the store flock and a symlink was followed (both reads now fsutil.ReadGuarded); iss-384 Baseline.validate sanitised final_url alone while echoing the entry key and quoted fields raw to the terminal through the CLI error surface (incomplete-fix residue of iss-359); iss-386 launch scaffold stripped the go.mod patch and refused one back, shipping every adopter a floating go-version (the adopter-side residue of iss-289); iss-385 commands/version.md still named only two network verbs after two rewrites (docs cite refresh and memory ingest also fetch); iss-387 the release-gate manifest pinned 17 briefDocs while four shipped surface chapters (guard/ideate/identity/banlist) sat outside it, so every full-tier crosscheck attested coverage it never ran; iss-388 the phases README called the shipped itd-88 planned; iss-389 the examples-use-reserved-identifiers principle described its shipped iss-154 lint as not-yet-built; iss-391 research/notes/README routed to the adr-30-rejected research/phase and research/adr layouts; iss-392 the confirmed nitpick batch (canonical id-uniqueness key closing the zero-padded-filename hole, .yaml coverage in the go-version lockstep sweep, scripts/.sh eol=lf, the lifeboat-reviewer 0.1.1 reconciliation, and the commands/abcd/ path repoint across five live records). Recorded, not fixed: iss-390 — the pre-decided promotion of the reserved-identifiers principle to a discipline-kind intent is a maintainer ceremony, so it stays open as the tracker. Refuted this round (kept out of the ledger): the scanner genericHomeRe case-fold (iss-308 already adjudicated against folding the POSIX /users/ arm — real API-route false positives, and home_path_other is warn-tier anyway); the ahoy refounding-candidate case compare (documented mutable labels; the miss lands on the designed decline path; iss-221 owns the real repair); govulncheck non-gating (documented deliberate advisory, DECISIONS 2026-08-19 and commit 61a15b4); the CODEOWNERS publish-surface omissions (the .abcd/ paths reach no installed user and the Go-tree reading proves too much; sole-maintainer bypass makes the scenario moot — a golden-file test for the bare scaffold render is the real follow-up if a write rung is ever granted); isHexSHA 40-hex (display-only, sha256 repos unreachable, iss-206 owns the sibling); the coverage_index.json raw read (already named by open #365); commands/docs.md's scoped "on behalf of documentation" heading; the agents/ host-agnosticism claim (docs-lint bans harness names, not the model id, which is the sanctioned disclosure token); the make smoke vacuous-gate and runbook-parity claims. Model routing: orchestration on Claude Fable 5; five parallel hunters, seven per-finding adversarial refuters on Claude Opus 5; the dual pre-merge review runs one reviewer as Claude Fable 5 and one as Claude Opus 5.

  • dcn-26082000000000072026-08-20

    2026-08-20 — the spc-33 mint mechanics are ruled and the native mint ships for captures: random-suffix width is 4 digits (16-digit ids, the top of the range itd-114 priced — entropy alone carries the cross-branch same-second case), and the same-instant tiebreak keeps the O_EXCL reservation but REDRAWS a fresh id on clash rather than bumping (a bump is a miniature max+1). The capture family now mints iss-<yymmddHHMMSS><rrrr> through the family-generic recordid seam; itd/spc stay on the legacy refs-union allocator until they adopt the seam as configuration. Capture's refs scan and mint_warning retire with the maximum it warned about; the uniqueness detectors stay armed as the scheme's fail-safe. Once this lands on main, the per-task defensive minting protocols (fetch-and-verify twice, scanning unmerged hunt ledgers) retire for captures, per adr-45.

  • dcn-26082000000000062026-08-20

    2026-08-20 — Homebrew distribution recorded and parked. Viable now that the repo is public, and it is what the reference class (gh, lazygit, k9s) leans on; a personal tap is the solo-maintainer shape and homebrew-core needs notability. Deferred until after a binary-update verb exists, because the two interact: an updater must gate on install-channel detection and print brew upgrade abcd instead of self-replacing when the binary's RESOLVED path sits under a brew prefix (/opt/homebrew, /usr/local, /home/linuxbrew/.linuxbrew — a prefix test, never a "Cellar" substring match). The named incident is flyctl's autoupdate postmortem, "Flyctl Versions, Autoupdating, and the CLI Apocalypse" (https://community.fly.io/t/flyctl-versions-autoupdating-and-the-cli-apocalypse/13794): brew-path update loops, Nix read-only breakage, Windows UAC. Note for the revisit: goreleaser's homebrew_casks pipe is the current SOTA route, but abcd's release pipeline is bespoke (semantic-gate attestations, no goreleaser), so the tap push would be a hand-rolled release-workflow step.

  • dcn-26082000000000052026-08-20

    2026-08-20 — bughunt round 3 (branch bughunt-a/round-3): captured twelve findings (iss-360..iss-369, plus two renumbered to iss-373/iss-374 after round 2's own collision re-mint landed inside this round's block — the week's fourth collision, each adversarially refuted before capture; ids minted above the sibling bughunt-b/round-2's iss-357 via the cross-ref floor). Fixed eleven, one recorded-not-fixed. Code/security: iss-361 the lifeboat coverage renderer (per-repo and aggregate) printed untrusted cross-repo status/tier/tiers_present/section fields to the terminal with no termsafe — only the repo name was sanitised — so a crafted probe report injected raw ANSI/OSC-8/bidi (reproduced); both renders now route every repo-derived string through sanitize with widths from the sanitised strings; iss-366 termsafe.Sanitize masked the deprecated FEFF joiner but not its Unicode successor U+2060 WORD JOINER, the U+2061-2064 invisible operators, or U+00AD SOFT HYPHEN — all now masked; iss-364 the capture related_specs validator pinned the retired fn-N namespace (reFnID) instead of the live spc-N, making the field unusable — switched to reSpcID, dropped the orphaned reFnID, corrected issues/README.md. Surface (additive): iss-362 abcd banlist --json omitted the reach caveat its command file tells an agent to relay verbatim — added a reach field to PrivateReport (unconditional, mirroring the ahoy status board). Docs (fix): iss-363 commands/lint.md and prepare-this-repo.md enumerated five lint conventions omitting the shipped identity-positioning rule; iss-367 commands/launch.md documented a nonexistent top-level files count for launch --dry-run --json (the list is bundle.files). Infra (fix): iss-365 the govulncheck CI job pinned @v1.1.4 whose bundled x/tools caps its type-checker at go1.24 while go.mod declares go 1.25.6, so the scan failed at package loading and exited before analysing anything — masked as an advisory red since it landed 2026-08-19; bumped to @v1.7.0 (verified locally to load go1.25). Record (internal): iss-373 three ADRs (adr-11/13/20) ended with leaked tool-call scaffolding (</content></invoke>) — deleted; iss-374 the ADR index listed adr-44 proposed vs the record's accepted — corrected; iss-360 adr-7 carried no frontmatter against the ADR contract (sole outlier of 36) — added; iss-368 the core/disembark glossary term linked its counterpart to the interview-context embark (a different bounded context) rather than the /abcd:embark unpack surface — repointed. Ledger hygiene: resolved the stale iss-338 (round 2's persona-pronoun record already fixed by round 1's iss-321; all ten cited sites are they/them). Recorded not fixed (stays open): iss-369 readTranscript opens the hook-supplied transcript path without O_NOFOLLOW — the last bespoke external-input read not routed through fsutil.ReadGuarded; refuted as no reachable exploit (harness-supplied path, no path policy, so a direct path already reads any file), defence-in-depth only, left for a scoped consolidation. Model routing: orchestration on Claude Fable 5; five parallel hunters, six per-finding refuters, and one of the two pre-merge reviewers on Claude Opus 5; the second pre-merge reviewer on Claude Fable 5 (dual-model merge gate).

  • dcn-26082000000000042026-08-20

    2026-08-20 — itd-114 (collision-proof record ids) is pulled forward: two live parallel-mint collisions in one day (iss-330; the round-2 renumber), with a third structurally predicted whenever two minters start from the same max. The 2026-08-20 multi-minter morning is pre-registered as its field test (research/notes/2026-08-20-itd-114-collision-field-test.md); the planning interview opens with that note's graded results.

  • dcn-26082000000000032026-08-20

    2026-08-20 — Bug-hunt round 1 (hunt A), landed late: the round ran 2026-08-19 on a branch that waited while v0.6.1 and bughunt round 2 merged; reconciled onto main today rather than replayed. Captured iss-305..iss-325 (21 findings, each adversarially refuted before capture). Ported with their tests: the privacy-rule leading-boundary gate and Windows-arm case fold (iss-305/308), the scanner ipv4/mac trailing-\b redaction miss (iss-307), the memory-ingest guarded read (iss-310), the record-lint/scaffold-sync isolated-env root discovery (iss-311), the hermetic attribution corpus (iss-313), the .PHONY completion (iss-314), the guard python/perl false "loud warn" claim across all four surfaces (iss-315), the AGENTS/ci.yml job list and dev-README record-map/personas corrections (iss-318/319), and they/them across seven intents (iss-321). Superseded, not re-applied: the SemVer over-int64 rejection (iss-309) — hunt B's iss-293 landed the same fix on main first with tests covering all three component positions, so main's implementation stands and the branch's code and test were dropped; likewise githubRemoteRe's (?i) (iss-306 = round 2's iss-339) and the wrapper-probe cwd isolation (iss-312, fixed on main with a sync.OnceValue probeDir). Re-derived rather than replayed: the doc fixes — main had already fixed iss-316/317/320 its own way (round 2's anchor sweep is on main verbatim), so only the still-true corrections were applied. Open record-only: iss-322..iss-325.

  • dcn-26082000000000022026-08-20

    2026-08-20 — bughunt round 2 (branch bughunt-b/round-2): captured the round-2 records (iss-346..iss-357, with the two colliding ids re-minted as iss-358/iss-359), fixed eleven records, closed iss-201, and wontfixed iss-358 on pre-merge review evidence. Code: iss-358 lanHostRe/deviceHostRe trailing-\b redaction miss (the iss-307 sweep's residual) — BUILT, then REVERTED: the pre-merge adversarial review proved the loosened pattern flags snake_case selectors (stream.local_addr, args.local_rank) and Stage-1 redaction rewrites findings into the irreversible history store, so the warn-tier miss is the accepted cost, pinned by TestSnakeCaseSelectorsStayQuiet; iss-359 redirect-controlled FinalURL carried C1/bidi/zero-width runes raw into --json and the committed baseline (fetch boundary percent-encodes, baseline validates, termsafe/coverage doc claims corrected); iss-346 guard also-matched dropped a matched warn under a synthetic block; iss-347 readTranscript symlink-follow + truncation (now fsutil.ReadGuarded); iss-201 hook stdin over-cap misdiagnosis (cap+1 probe at readHookInput and the guard hook); iss-356 batch (urlguard RFC 6890 ranges incl. CGNAT, repolint not-scanned warn, 64-hex resolve sha, CLI help truths, release.yml wording + templates, dependabot pip). iss-357 records the memory-ingest FinalURL sibling site the cite fix did not reach. Records: iss-348/349/350 user-facing doc truths; iss-351 discipline roster -> pointer; iss-352 phantom research/adr repointed; iss-353 note naming yields to adr-30; iss-354 go-version lockstep test (mutation-verified). Recorded not fixed: iss-355 — a batched merge-queue push tags the batch tip, so auto-release + the HEAD^2^ derivation wedge a release roll merged as a non-final queue entry (iss-326's outcome by a route itd-93 cannot close); required-check workflow logic, left with two proposed fixes. Refuted this round (kept out of the ledger): the external-review pull_request_target check-sha wedge (check runs attach to the PR head, proven from run history), the docs-site ungated claim (docs-lint gates docs/ on every PR; iss-234 records the inert design), the empty Diataxis indexes (owned by iss-216 and the facilitator plan), identity email case-folding (byte-exact parity with the sh pre-commit gate is the contract), and the guard backtick parser gap as a fix target (iss-148 records the reverted attempt; only its missing help-text disclosure was new). Dedup boundary: iss-307/311/317/319/321/325 and the v0.6.0 wedge (iss-326/327) were already held by hunt A or the maintainer and were not re-reported.

  • dcn-26082000000000012026-08-20

    2026-08-20 — bughunt round 2 (branch bughunt-a/round-2): captured iss-331..iss-343 and fixed (ids 339-343 re-minted from an initial 326-330 after main concurrently took those numbers in the v0.6.1 cut) ten (six fix-impact, four internal). Code/security: iss-339 the scanner's githubRemoteRe matched the github.com host case-sensitively, so a mixed-case remote (git@GitHub.com:…) left GitRemoteUsername empty and the github_username redaction kind never armed — the caller's handle survived history-capture redaction and the PII scan (added (?i)); iss-340 abcd history show/list printed the untrusted transcript body and metadata fields with no termsafe, replaying ESC/CSI/C1/bidi sequences raw (now SanitizeBlock on the body, Sanitize on the fields); iss-341 readLifeboatFile kept an Lstat→root.Open window over an untrusted lifeboat (FIFO hang / symlink-follow) — routed through fsutil.ReadGuardedInRoot, dropping the unused abs param; iss-342 SourceContext.ListDir opened directory entries with a blocking open, so a statically-planted FIFO named docs hung disembark probe/plan/pack over an untrusted target repo with no race (now O_RDONLY|nonBlock, matching ReadFile). Docs (fix): iss-343 prepare-this-repo.md named the pre-flattening commands/abcd/ path and "three levels up" (now flat commands/ and "two levels up", tied to CLAUDE_PLUGIN_ROOT); iss-331 lint.md presented the abcd-lint:allow waiver as global when only privacy-hygiene honours it. Record (internal): iss-332 development/README.md denied the issue ledger adr-32 created; iss-333 the brief's 05-internals/03-configuration.md development tree drew the pre-adr-30 layout (roadmap/intents, research/adr, research/phase, .abcd/specs) — redrawn flat by artefact type; iss-334 intents/README.md taught the v0.6.0-retired intent review verb and intent-fidelity-reviewer agent (swept to intent audit / intent-auditor); iss-335 the issues/ store contract omitted the mandatory impact field and the agent-observation source. Recorded not fixed (stay open): iss-336 gate_lockstep blank-path silent disarm (nitpick, no external arming path — defence-in-depth only); iss-337 probe.go inner-descent OpenRoot FIFO race (needs a raw openat restructure, os.Root.OpenRoot takes no flags); iss-338 seven registry personas given gendered pronouns against the itd-79 they/them discipline (nitpick cosmetics batch). Refuted this round: govulncheck non-gating (documented deliberate advisory — commit 61a15b4 and ci.yml:362-363), and the CHANGELOG bijection gap (the bijection reads the composer's JSON payload, never CHANGELOG.md; the residual is the already-open iss-256). Model routing: orchestration on Claude Fable 5; hunters, per-finding refuters, and one of the two pre-merge reviewers on Claude Opus 5; the second pre-merge reviewer on Claude Fable 5 (dual-model merge gate).

  • dcn-26081900000000052026-08-19

    2026-08-19 — Design review of the candidate record extensions (scope conditions on intents, selection grounds at plan time and capture triage, per-record provenance of contributed material, a knowledge record, a framing passage in the brief) and of the cold-reading build path: one independent adversarial pass over the plan plus two SOTA surveys, written up as the two dated research notes 2026-08-19-*-sota.md. Six decisions. (1) No never-bluffs principle is minted — the brief's marking discipline is loud-staging applied to prose, and a framing passage cites loud-staging directly; the sensemaking entry's one-principle precedent (no near-copies) applies. (2) itd-60 is not a prerequisite for brief rewrites — the rewrite is existing human practice at ship time; itd-60 stays an unplanned ambition. (3) Nothing in itd-87 must be settled before itd-86 builds: capture carries no semantic dedup (id-collision guards only), so there is no store for a re-raising detector to fight; recurrence handling stays deferred to itd-87. (4) Promise-questioning — "delivered as promised, but the promise itself is in question" — if ever built, is its own surface with its own ADR extending adr-40's closed bucket list; it is never a slot inside the intent-fidelity verdict, whose one act is reality-vs-commitment. Nearest published vocabulary is Lean's hypothesis-invalidated / pivot; no surveyed practice has a machine-readable verdict separating built-wrong from wrongly-specified. (5) itd-86 is not plannable until its isolation mechanism is named in scope: no allowlist invocation surface exists, installed agents read the whole tree, and host subagents inherit project-context files by default — the blindness contract's mechanical half is a build item, and whatever remains disciplinary is reported as such per loud-staging. (6) The record extensions land as hand-run conventions before any automation, per script-first-mvp; the ideate rejected-alternatives shape and the wontfix_reason invariants are the two in-repo patterns they extend (one-canonical-primitive). Grounds and sources in the two SOTA notes.

  • dcn-26081900000000042026-08-19

    2026-08-19 — The cold reading's ACKNOWLEDGEMENTS.md entry is not owed and no longer gates itd-86. The 2026-07-13 sensemaking-method note had deferred the entry pending the originator's crediting preference; the originator is a co-author and now co-maintainer of abcd — an author of record, not a third party the acknowledgements file exists to credit. The note's provenance paragraph is amended accordingly.

  • dcn-26081900000000032026-08-19

    2026-08-19 — bughunt round 1 (branch bughunt-b/round-1): captured iss-291..iss-304 and fixed ten. Code: iss-291 the guard exec-string cluster reader ignored value-taking short flags, so script -Tc out.txt -c '<blocker>' was a silent allow that also disarmed the Tier-2 fail-safe (value flags now abort the cluster read); iss-293 ParseSemver swallowed strconv.Atoi's range error, clamping an oversized component to MaxInt64 (now propagated, matching spec.go); iss-292 the wrapper-probe test wrote junk files (0,1,PATH,root) into the tracked tree because runsCommand had no cmd.Dir (now a temp dir; the four committed artefacts removed). Docs/record: iss-294 version --check "only network" claim, iss-295 README unshipped brief-onboarding claim, iss-296 ADR-index + ruleset-README count drift, iss-297 adr-40 verb-rename residue in roadmap+brief, iss-298 all 18 broken/stale brief heading anchors and section citations (anchorcheck now 0), iss-299 phantom "in-session dispatch" internals chapter, iss-300 persona glossary role-first contradiction. Recorded not fixed (stay open): iss-301/iss-302 external-review.yml approval-tally (paginated per-page --jq) and error-masking (|| echo none + under-permissioned collaborators endpoint) — required-check workflow, unverifiable without a real Actions run; iss-303 links_resolve never validates heading anchors (systemic fix behind the anchor cluster); iss-304 deferred nitpicks (a-4 memory ingest --source size TOCTOU, b-4 completion/help omitted from the CLI reference, d-12 the CI job id record-lint runs the reviews-charter script). Refuted this round: the scripts/ payload over-inclusion (knowingly-deferred open dependency, iss-34), the attribution/reviews gates running from the PR tree (CODEOWNERS contains it), AGENTS.md's CI-job list (ci.yml-scoped, iss-182), the release Go-version float (deliberate), and the 05-personas.md random-picker line (prior art iss-49).

  • dcn-26081900000000022026-08-19

    2026-08-19 — Review agents keep their Bash grant: running the project's tests is part of what makes their reviews evidence, and the exposure that motivated the question is closed by the intake rule that external-contribution review runs only in CI or a network-less container (.abcd/work/intake.md S4). iss-278 narrows to the unbuilt PQ linter. Maintainer decision.

  • dcn-26081900000000012026-08-19

    2026-08-19 — The .abcd/work/issues/ ledger is the single canonical issue store; forge issues (GitHub) are a derived, opt-in mirror surface — consistent with the host-delegated boundary (forges are hosts). Per-field ownership: the ledger owns existence, content, and resolution; the forge owns nothing. Sync is one-way mirror-out, the forge id written back into the record as the echo suppressor; forge-side activity (triage labels, a close) is never auto-synced — it generates an import proposal a human accepts via an explicit import that writes the canonical file with provenance. A forge-side close never imported is reopened by the next mirror pass: the mirror is self-healing by construction. Autonomous hunts file findings as fingerprint-keyed iss-N records inside the gated PR they already open, validated by record-lint (the armed detector) — never as forge issues. Grounded in commissioned SOTA research (see ../development/research/notes/2026-08-19-issue-ledger-forge-sync-sota.md): one-way canonical sync is the surviving pattern (coreos/issue-sync post-mortem); agent findings as records-via-reviewed-PR is 2025-26 practice (GitHub advisory-database, ClusterFuzz fingerprint dedup); ungated agent filing degrades the whole record (curl, 2025). Architecture-shaping: graduate to an ADR.

  • dcn-26081800000000042026-08-18

    2026-08-18 — Two adversarial reviews of the adr-42 implementation; three findings that changed the code, all reproduced against the binary first. (1) DoS, 23.6s at the 1 MiB cap: maxSpeculativeWindow bounds the token COUNT and an execute-a-string payload is ONE token of unbounded length, so 64 starts each re-tokenized a 1 MiB payload. Two more bounds added — a payload-BYTES budget and a whole-line START budget, both per Check, after a per-segment byte budget still left 1,200 short segments at 8.4s. The lesson generalises: every per-item bound needs a whole-input bound behind it, and the ADR had said in advance that the benchmark must exercise the payload path — the first bound test pinned the cheaper half anyway. The bound test is now four adversarial shapes, each verified by mutation to fail on the bound it names. (2) FALSE BLOCK, and a suppression behind it: scanExecString ran to the end of the segment, so flock /tmp/lock /bin/echo -c "<hazard>" read a -c that real flock passes to /bin/echo as an argument (verified: it prints them). That both blocked a harmless command AND made the segment look understood, switching Tier 2 off for it — a flock prefix was a one-token off switch, the payload-level twin of the per-line suppression decision 4 rejects. Fixed with a per-verb count of the operands the verb owns before the launched command begins; only flock has one, because su genuinely permutes (su root /bin/echo -c 'echo SEVEN' prints SEVEN). This falsified the code's own claim that a mis-parse "never yields a false block". (3) The wrapper probe would have FAILED ON CI: chrt -f 1 needs CAP_SYS_NICE and a GitHub runner is unprivileged, and the per-wrapper needsRoot blanket also hid the nsenter -W counterexample the file exists for. Replaced with a DERIVED control probe (if the wrapper cannot run its own baseline here, nothing it says is evidence) plus per-flag reasons. The candidate list — itself a hand-maintained enumeration, i.e. the CWE-184 shape inside the test written to defeat it — now comes from the binary's own --help, which is trusted to ENUMERATE and never to CLASSIFY. That immediately found three real misses: nice --adjustment, runuser -w and runuser -s, each degrading a precise block to a warn. 44 classifications became 121. Also: every synthetic id that contributed is now listed in Matches (a Tier 2 fire used to lose the slot to any earlier payload warn and vanish — which the warn-rate gate counts, so the blind spot hid itself); the cap warn no longer fires when only losslessly-skipped tokens remain; the warn ceiling is an absolute 2 rather than a 1% rate that permitted 9; matchesAny deleted as dead; and the three surfaces no longer list "launched through a wrapper outside the known set" as something an allow does not see, which is the case this change converts to a warn.

  • dcn-26081800000000032026-08-18

    2026-08-18 — adr-42 parts B and C built; iss-272 closed. Part B named fourteen wrappers (nice setsid stdbuf ionice eatmydata proxychains chrt taskset unshare nsenter flock chroot runuser busybox), which upgrades each from part A's loud warn to a precise Tier 1 block. Every flag list is DERIVED BY PROBING the installed binary in a test, never from --help, and the probe caught two errors before they shipped: nsenter -W/--wd consumes NOTHING while unshare -w/--wd — same letter, same package, same version — is required-argument (listing nsenter's would have made the walk step over the COMMAND, a miss the table would have INVENTED); and taskset -c is a format switch for the MASK operand, not a value flag. A flag this environment cannot classify is listed as unprobed WITH ITS REASON (setsid --ctty needs a controlling terminal, chrt --sched-runtime needs SCHED_DEADLINE, nsenter/chroot/ runuser need privileges) — silence is what gh-299 shipped. Part C added an exec-string TABLE for su/runuser/script/flock, not a shellCPayload generalisation, which would have resolved the short spellings free and silently allowed six long ones (su --command, --command=, --session-command, runuser --command, script --command, flock --command); each has a test. Classification runs on the raw token chain before commandOf because runuser and flock are also wrappers. Recorded limit kept honest: su -c runs the TARGET user's login shell, overridable with -s, so the payload is not guaranteed POSIX grammar — a false-negative cost only. All ten of iss-272's bypasses now produce a verdict; the acceptance test asserts that in the issue's own terms.

  • dcn-26081800000000022026-08-18

    2026-08-18 — adr-42 parts D and A built. TWO amendments the build forced, both recorded in the ADR. (1) The ~64-start cap does NOT bound the cost on its own: every speculative start pays commandOf, which walks the whole leading wrapper chain, so 64 starts on a 1 MiB line of env env env ... measured 14.2s inside the PreToolUse hook — linear in line length and still an outage. A second bound (maxSpeculativeWindow = 512 tokens read per start) takes it to ~120ms; a truncated window warns through the same fail-loud path as an exhausted start cap, so the coverage trade is never silent. Pinned by a test at the real 1 MiB stdin cap, watched failing at 14s with the window removed. (2) A speculative start must NOT skip known wrappers, though commandOf would step them: the wrapper is exactly where a payload lives, and myrunner env -S '<hazard>' needs env in command position for expandPayloads to read the -S value at all. Skipping wrappers is lossless for MATCHING and lossy for EXPANSION — caught by the demotion test, which failed as an allow. The warn-storm STOP is DISCHARGED with committed evidence: 961 mined command lines with zero Tier 2 fires, plus a labelled adversarial corpus (23 quiet / 18 caught / 5 Tier 1 blocks / 2 accepted false positives), both under internal/core/guard/testdata/corpus/ with the ceiling enforced by a test. The shipped fail-safe is much quieter than the argv[0]-gated prototype predicted, because a hazard inside a quoted argument or a path never reaches command position. git bisect run and git submodule foreach now warn, exactly as the not-argv[0] gate predicted.

  • dcn-26081800000000012026-08-18

    2026-08-18 — The guard's parse layer is a MISTAKE FILTER, not a security boundary (adr-42, iss-272). Enumeration-completeness is abandoned as the matching strategy: Tier 1 (position-anchored, blocks) keeps the registry match; Tier 2 (position-agnostic, warns) speculatively re-matches from each later command-position token when NO ENTRY MATCHED, each suffix run through expandPayloads, converting the unbounded WRAPPER class from silent allow to loud warn without enumerating anything — 6 of the 10 verified bypasses, 7 once each speculative suffix runs through expandPayloads. It does NOT reach the exec-string class (su/runuser/script -c keep an opaque payload isShellFamily will not open), which stays silent until part C lands. Forced by three facts: the defect is the wrapper path's missing fail-safe (the interpreter path has shellUnresolved, the wrapper path has nothing), the wrapper set is unbounded in principle and its tractable part cannot be read off the documentation (nsenter's --help renders -S as optional-arg and unshare's renders the same letter, same package, same version, as required-arg, while BOTH binaries consume the next token — so only probing the installed binary is sound; gh-299 is the in-repo proof — its first list was taken from the bug report and was wrong three ways, omitting --shallow-file (a live force-push bypass in git since 1.9) and counting --exec-path/--super-prefix as value-taking when neither is, and it TOTALLED NINE EITHER WAY, so a size assertion certified the wrong list as complete), and every vendor shipping this control documents it as steering, not enforcement. Tier 2 is BOUNDED against a measured quadratic DoS — the drafted form ran 14.9s at 6000 tokens, ~8h of CPU at the 1 MiB stdin cap, inside the PreToolUse hook — so O(N) starts, a ~64 cap, short-circuit, pinned by a benchmark. The gate is "no entry matched THIS SEGMENT" — never "argv[0] unknown", which would switch speculation off for git, and never per-Check, which would hand an author a one-token suppression (git clean -fd ; nice git push --force matches git-clean, so a whole-command gate disarms the fail-safe for the whole line). Per-segment is also what makes the false-positive figures a floor, but only with "unknown command" pinned to commandOf's OUTPUT (wrappers, assignments and reserved words stepped, basename taken) rather than the literal first token: matchSegment keys on exactly that value, so a segment commandOf resolves to something no entry names cannot match any entry, and the nesting is by construction. Under the literal reading it is false — env git clean -fd gh repo delete . resolves to git and matches git-clean, while a literal-token gate would see env and fire on git clean's own pathspecs. Also decided: a synthetic verdict raised from a speculative suffix (expandPayloads emits two blockers, envSpecialBlockSignal and depthBlockSignal) is DEMOTED to warn, never honoured at its own tier and never dropped — honouring blocks on two layers of uncertainty, dropping invents a second silent suppression path inside the fail-safe. The ~64-start cap is PER SEGMENT for the same warn-rate reason. Enumeration continues, demoted to an upgrade (warn → precise block) and safe to be incomplete. The exec-string family (su/runuser/script/flock -c) gets a small table, NOT a generalisation of shellCPayload, which would ship six new SILENT allows on the long spellings. Sequencing D → A → B → C. Rejected with evidence: add-the-missing-names as the primary fix (third instance of one defect); descend-into-any-spaced-token (breaks the 100% known-good floor — the spc-16 incident-capture fixture fires); flag-shaped-prefix-only (silences most true positives); allowlist (recorded for a future fail-closed mode, wrong for arbitrary developer work). Accepted cost: false positives on unquoted hazard-shaped text wherever no entry matched — 0/1144 repo-mined lines, 21/79 adversarial, but BOTH corpora were run against an argv[0]-gated prototype, i.e. the gate this decision rejects, so the figures are a FLOOR (per the nesting above) with an unmeasured margin, and re-measuring under the adopted gate is a merge precondition. The fail-safe covers the WRAPPER enumeration only: a missing interpreter name (fish -c) and a missing git value flag are still silent allows under Tier 2, so this record covers the predicted fourth instance only if it lands in the wrapper set. The warn-storm STOP from the 2026-08-15 note binds: measure on real agent commands before merge.

  • dcn-26081700000000042026-08-17

    2026-08-17 — The attribution gate's list-container fence limit is ACCEPTED as a standing residual (iss-270, wontfix), not deferred. A fence opened inside a first-level list item sits at column 2 (ordered: column 3), under the matcher's absolute three-space limit, so it is read as document-level and a footer inside that span is stripped although the forge renders it as an ordinary paragraph. All three remedies are worse than the hole: tracking container context means a markdown block parser inside a bash gate; refusing to strip from any document containing a list marker is safe by construction but would disable the fence concession in almost every real body here, reverting iss-268 in practice while appearing to keep it; and forcing openers to column 0 was tested by the security review and LEAKS, because under-recognising an opener is not conservative — markdown then closes its block at a line the matcher treats as the opener, shifting the whole span. Acceptance is defensible because the gate's defended property is untouched: it exists for a footer a tool appends BY DEFAULT (itd-91, 78 pull requests), a tool appends last, and footer-last is caught whatever precedes it — fuzzed at 0 violations in 2400 differential bodies against a real CommonMark parser. This shape needs a body CONSTRUCTED AROUND the footer, which the design already declines to defend, and such an author would delete the footer instead. Pinned in the corpus for bulleted and ordered items so a change is visible. Rejected: all three remedies above; and leaving the record open, which would invite the indent-relaxing "fix" that widens the hole. Reopen only if the gate is asked to defend against a deliberate author — a different design.

  • dcn-26081700000000032026-08-17

    2026-08-17 — Command parents owe TWO guarantees, not one (iss-266, #293). A parent refuses a mistyped sub-verb only if it is Runnable AND declares an Args validator; missing either exits 0 silently (no RunE ⇒ cobra returns flag.ErrHelp before ValidateArgs; Args nil ⇒ legacyArgs falls through to ArbitraryArgs). The house convention is therefore RunE: helpRunE plus an explicit validator on every parent, asserted structurally over the live command tree rather than a hand-kept list. capture and intent are a named exemption — their positional is free text, guarded by their own suspected-typo check — and the exemption list is itself tested against reality so a stale name cannot quietly drop a parent from the sweep. Consequence accepted and filed as iss-267: exit 2 is the blocking status on the hook plane, so hook sub-verb names are now a compatibility contract and a future rename must carry an alias rather than rely on the old silent-exit-0 cushion. Rejected: fixing only the parents named in the issue (the same hole would return with the next parent added), and asserting the behaviour with a hand-maintained list of parents (it had already drifted — identity and intent audit were absent yet not exempt).

  • dcn-26081700000000022026-08-17

    2026-08-17 — README bucket-vocabulary alignment (#289), made unattended against adr-40's own table rather than by taste: grading delivered work against acceptance criteria is an audit (reality vs a recorded commitment), so four "review" call sites move to audit wording, agreeing with the one call site that already said "intent auditor". Two further calls inside the same passage: (1) "a privacy review" becomes "a privacy-hygiene lint" — a cross-cutting rule every feature must satisfy is adr-40's definition of a lint, and abcd's own privacy-hygiene emits a rule id and an exit code, not SHIP/NEEDS_WORK, so the example contradicted the sentence defining it; (2) "owned by the AI-engineering team" becomes "run by the AI-engineering team, read by you" — the role table gives the product thinker the audit bucket, so owned by pointed the reader at the wrong end of the handover and made the one bucket they do own read as someone else's property. Also corrected a factual gap: cross-cutting rules do not merely "go straight into the brief", they have a record home in intents/disciplines/ (kind: discipline; itd-1/5/37/79/81/84 live there today). Rejected: leaving the prose loose on the grounds that user-facing writing need not track the code's vocabulary — adr-40 closed the bucket list precisely because an autonomous run given a criterion will interpret it, and the README is the first thing both a contributor and an agent read.

  • dcn-26081700000000012026-08-17

    2026-08-17 — spc-27 population calls, made unattended within adr-40's test ("what is compared to what") and recorded for re-litigation avoidance: (1) every ahoy sub-verb bucketed — — doctor/identity-check are install diagnostics of the ops environment, not assessments of the record/repo/change the adr-40 roles reason about; (2) launch ship carries bucket gate, representing the binding "launch changelog guardrail = gate" pre-ruling on the verb that runs the guardrail (the guardrail is not separately registered); (3) intent's unbuilt design-target sub-verbs (refine / grill / ship / consistency / shape / reclassify) get NO staged rows yet — intent consistency is the adr-40 multi-act case whose split is design-time work, so bucketing it now would guess into a closed list; the registry prose still names them design targets and the armed check stops any live claim. Rejected: a partial surface status (ruled out at planning), and staged rows with guessed buckets.

  • dcn-26081600000000082026-08-16

    2026-08-16 — the v0.5.1 release gate ruled PROMOTE ×2 at content commit 264d9b1 — the first fully derived cut: changelog composed from the cut's resolved records and ingested behind the completeness bijection (three entries citing iss-254, iss-255, iss-257). Full tier (the cut is additive by iss-257). docs-currency: two findings — the README ladder sentence over-quantified to every hook (fixed in the receipts commit: "every other hook") and the removed contributor-guidance pointer (maintainer-directed, no change). Crosscheck: 25 discrepancies, substantially the iss-250 corpus re-confirmed between two same-day cuts, dispositioned against that open issue rather than re-filed. Rejected: re-filing the drift as a new issue (iss-250 already carries the corpus and stays the single tracking home), and holding an additive cut on record drift the brief's own aspirational posture (adr-5) anticipates.

  • dcn-26081600000000072026-08-16

    2026-08-16 — itd-76 planned at the live interview (spc-31 minted, intent ready exit 0). The itd-84 hand-run rendered SPLIT, confirmed: itd-76 narrows to the personal core (source add / ledger / sync-banlist / cite-check + guards); team share/ingest files as itd-126 and paper reconstruction as itd-127 (both refines itd-76, seeded criteria marked unconfirmed); the trust rule extracts to adr-41 (proposed) + brief invariant 9 — documents and ledgers never leave the user tier, a public citation requires both gates — which the intents cite rather than declare; the stance files as the consult-freely-cite-deliberately principle. Interview rulings: the share surface is the existing .abcd/development/research/references.csl.json research store, not a second .abcd/work/references.json exchange file (one committed bibliography — resolves the store clash the sources-plan adversarial review flagged); the draft's "Dogfood (already running)" claim was stale and is rewritten as target (no corpus on the development machine); multi-machine ledger ownership explicitly deferred until a second machine exists; persona Maya corrected to Alice. Seven Given-When-Then criteria authored and accepted in full. Rejected: planning the monolith (both remaining open questions gated only the share/ingest part), and holding for itd-77 (the corpus default path works without relocation). Hand-run graded into the decomposition-calibration note.

  • dcn-26081600000000062026-08-16

    2026-08-16 — academic references baseline adopted: the References & sources section of ACKNOWLEDGEMENTS.md carries a curated set of primary sources (end-user programming, AI-assisted development in practice, security of AI-generated code, human judgement and method, records and specification) as one ACM-style numbered list ordered alphabetically by first author, with canonical metadata in .abcd/development/research/references.csl.json. CSL-JSON extends the 2026-07-08 bibliography ruling to the repo level — one canonical format, .bib derived on demand (pandoc one-liner in _references.md) and gitignored. Admission criteria (primary sources only, verified citations only, curated not exhaustive) and the per-group rationale live in research/notes/2026-08-16-academic-references-baseline.md; store↔markdown sync is the documented protocol in _references.md per script-first-mvp, with a references_sync lint captured as iss-248, the possible next rung. A root CITATION.cff (CFF 1.2.0) answers the reverse direction — citing abcd itself. Rejected: .bib as the source of truth (a second canonical bibliography format beside the recorded CSL-JSON ruling), and generating the markdown section from the store (inverts markdown-as-source-of-truth). Consequence of the numbered list, from the independent adversarial review of the sources plan: ACKNOWLEDGEMENTS.md leaves the iss-118 merge=union set — an alphabetical insertion renumbers subsequent entries, so a union merge of two concurrent additions would silently interleave both renumberings; a loud conflict is correct there.

  • dcn-26081600000000052026-08-16

    2026-08-16 — adr-40 §5 REVERSED at the process-planning interview (amendment recorded in-place in adr-40): disembark oracle renames to disembark review (itd-125, breaking) instead of keeping the verb and fixing prose. The investigation finding that turned it: the binary verb never invokes the oracle seam — it is a compute-or-ingest verdict endpoint (deterministic manifest+coverage mapping, or validate-and-ingest of a host-produced verdict), so the seam name claims transport the verb does not touch and collides with the /abcd:oracle ask design target, the seam's real surface. The sweep carries the artefact (audit/oracle-<manifest12>.* → review/review-<manifest12>.*, clean-replacement across the rename so one manifest never holds two verdicts) and the agent (lifeboat-oracle → lifeboat-reviewer). Naming convention ruled in the same session: assessment agents are target-grain + role (intent-auditor, lifeboat-reviewer). adr-25 and the seam name oracle stand unchanged. Rejected: prose-only fix (leaves the artefact contradicting the vocabulary), renaming the seam itself (adr-25 is correct), a superseding mini-ADR (same-day clause amendment suffices).

  • dcn-26081600000000042026-08-16

    2026-08-16 — the v0.5.0 release gate ruled PROMOTE ×2 (the first cut the armed public-repo receipt gate will verify). The passes executed against content tree d1afd2c; the merge-currency ruleset forced a re-cut, so the receipts are keyed to its cherry-pick 2235cda, which differs only by five interleaved record-only files outside both detectors’ pinned scope. docs-currency: one finding — the terminology.md release-artefact parenthetical that escaped the iss-183 sweep — fixed in the receipts commit, the disposition the receipt records. Crosscheck (full tier per the pinned manifest, 22 checkers, 28 unique discrepancies): all design-record drift (the vintage/staleness surfaces, the citation-baseline gate, the banlist renders and the agents/ registry row landed ahead of their brief rows), captured whole as iss-250 for the next cycle — the iss-192 treatment at v0.4.2, now precedent. Rejected: holding the cut on brief drift (the brief is aspirational by design, adr-5, and no user-facing doc is affected), and fixing the 28 findings inside the release branch (the two-commit shape is the gate's own contract; drift repair is next-cycle work with its own detector already armed).

  • dcn-26081600000000032026-08-16

    2026-08-16 — the assessment vocabulary settled at a maintainer grill and filed as adr-40 (proposed): four buckets — lint / review / audit / gate — separated by what each compares, not by determinism, not by trigger. The rule was already half-recorded (05-internals/01-agents.md rules the two verdict families disjoint: "reviews assess a change, criterion verdicts assess a promise vs reality") and three shipped surfaces contradict it — intent review emits family 2 so it is an audit, abcd audit is deterministic rule-checking so it is a lint (and it consumed the /abcd:audit name 02-constraints/04-naming.md reserves for itd-16), and disembark oracle emits family 1 while the brief calls its output an audit. Grill rulings: one surface performs exactly one act (multi-act surfaces split at design time — cheap, because every multi-act surface abcd has is unbuilt, so they are specified rather than refactored); the buckets are a closed list extended by PR, not a criterion (an autonomous run given a criterion interprets it; a table lookup matches or fails); intent ready survives as the fourth bucket gate because it names a decision rather than a comparison, preserving itd-94's exit-code contract; determinism is orthogonal (itd-16's hash-chain check is a deterministic audit; itd-85's conformance check is a lint however built); automatic-vs-manual never enters a verb name (the trigger is the facilitator's, per itd-97); the oracle is the model-access seam beneath review and audit, never a bucket. Clean break, no aliases — pre-1.0.0, --impact breaking drives version derivation (iss-171 precedent), users re-download; an alias would additionally collide with the documentation discipline's ban on change-narration, leaving an undocumented silent forward. The role mapping is the operational reason the split earns its cost: product thinker reads audit and essentially nothing else, which makes itd-99's "never hand a product thinker a technical decision" mechanically checkable. Same grill corrected a wrong finding: iss-246 was filed claiming abcd's record documents a surface far larger than the binary with no gate catching it; false — the Status column in 04-surfaces/README.md is machine-checked by surface_coverage (iss-35), the brief carries ~100 inline design target markers, and adr-5 makes the brief aspirational by design. The real defect is narrower: surface_coverage is blind inside a row, so six of twenty rows read shipped then qualify themselves in prose, and documents outside the registry cite those sub-verbs as live (all three citing predecessor-store spec ids spc-29/spc-30, whose prose survived the migration to the native store). Fix per adr-40 §6: sub-verb tables carrying two facts per verb — bucket and existence — with surface_coverage extended to registered cobra sub-commands, one table serving both disciplines. Also established: the twelve-step record walk completes at ten steps; step 2 (capture promote) has no verb and step 12 (capture resolve) cannot write resolved_by, so walkability is sequenced before coherence — renaming ~90 files across a process nobody can walk is polish before function. Plan at plans/2026-08-16-process-coherence-and-walkability.md; six intents to plan, none plannable unattended. Rejected: one polymorphic review <id> verb (merges the disjoint families, erases the role signal), classifying acts rather than surfaces (makes the bucket a statement of intent rather than a guarantee, and hands product thinkers lint findings), three buckets without gate (forces intent ready to become intent lint), and adding verify/validate (itd-109's verification suite is a packaging of lints and audits, not a fifth kind).

  • dcn-26081600000000022026-08-16

    2026-08-16 — CI inert-path skip gate (iss-234): the inert allowlist is docs/**, .abcd/development/**, .abcd/work/**, plus exactly README.md, CHANGELOG.md, CONTRIBUTING.md, SECURITY.md, ACKNOWLEDGEMENTS.md, LICENSE, LICENSE.md; everything else — notably the harness routers (AGENTS.md/CLAUDE.md/GEMINI.md), commands/, agents/, hooks/, .abcd/*.json, .github/**, evals/, scripts/, Makefile, Go source — is non-inert, and every unknown or degraded outcome (non-PR event, empty diff, unreadable base, aborted or failed classifier) runs the full matrix, fail closed and loudly. Deviation from the capture's skippable list, maintainer-confirmed 2026-08-16: the ubuntu unit lane ALWAYS runs — lifeboat brief-coverage, glossary-index and README-grounding tests assert against the live tree inside the allowlist (reproduced: a prose-only brief edit turns TestEveryBriefSectionHasARow red while record-lint and docs-lint stay green), so skipping go test ./... on an inert change is fail-open; what stands down is the macOS leg's heavy steps, the race lane, smoke, and zizmor. The skipped-conclusion-satisfies-ruleset behaviour is unverified until the rehearsal PR passes; nothing arms auto-merge on it before that. Rejected: a fromJSON dynamic matrix (a never-reporting check (macos-latest) wedges every PR) and a marketplace paths-filter action (plain git suffices, no new pinned dependency).

  • dcn-26081600000000012026-08-16

    2026-08-16 — the multi-harness routing ADOPTED at maintainer confirmation (itd-84 hand-run graded into the decomposition-calibration note, entry 3): adr-39 filed — the host-tier policy (MCP front door as the universal floor; the current plugin host's integration as the reference implementation, the assumed SOTA surface for the time being; the shipping default ultimately an open-source harness, flipping only on the parity suite plus a deliberate maintainer act; adaptor ladder most-native-first; per-host adoption one intent each at an explicit decision, nameless until adopted). itd-22 renamed harness-portability (id unchanged) and reworked to carry the shared machinery only — host profile seam, ladder semantics, parity conformance suite — with a retire-the-name ban (retired-itd-22-slug) on the old slug. itd-113 minted: the MCP front door intent (the floor is the first build). The never-double-write stance routed into adr-39 rather than a new principle — it restates one-canonical-primitive at the host boundary.

  • dcn-26081500000000052026-08-15

    2026-08-15 — Multi-harness support is IN SCOPE, reversing (reverses) the "obsolete under no-hard-deps" annotation the 06-delivery out-of-scope index carried on itd-22; the intent stays in drafts/ as the lineage carrier pending rework. The commitment: every supported harness drives the same abcd CLI functionality — behaviour lives once in the transport-agnostic core (adr-23) and is never double-written for one host. Per-harness delivery follows an adaptor ladder, most-native first: (1) the host's own plugin/packaging format, (2) any other native seam (lifecycle/hook wiring, config), (3) an MCP server as the universal fallback floor every MCP-capable host gets when rungs 1–2 are unavailable. Where a host exposes a native work-plane (goal/work-item tracking, a canonical wiki or knowledge base, trajectory judging), abcd's concepts (intents, brief, reviews, capture, lifeboat) map onto those native concepts rather than running as a parallel artefact set; hosts without such concepts get the adaptor rungs without the mapping. Candidate harnesses exist but commitment records name no external tool before per-host adoption is decided (2026-07-30 convention); each host adoption files as its own intent per the itd-22 lineage's own rule. Rejected: the reversed annotation's claim that a second harness is "just another host over the same core" needing no record — the core stays single, but hook/payload portability, packaging, and concept mapping are real per-host work the record must carry. The itd-84 decomposition hand-run routing this into intent/principle/brief rows precedes any filing.

  • dcn-26081500000000042026-08-15

    2026-08-15 — iss-200 (env -S guard bypass) fix attempt 2 BLOCKED by two independent reviewers (correctness + security), round stopped per the plugin-user-safety plan's first-attempt-BLOCK STOP. The splice-and-restart approach (commandOf re-tokenizes the -S value and re-walks) is REJECTED, not to be re-patched: it introduced a quadratic cost regression (O(n^2), ~5 min at the 1 MiB stdin cap — a DoS on the very hook meant to gate the command) AND still let all three in-scope spellings through (env quote-removal, the \_ separator, and a leading env option in the value all desync a strings.Fields split and a command-position restart). Branch bugfix/iss-200-env-split-string-guard-bypass-v2 left unpushed. iss-200 enriched with the complete env -S spelling set the next attempt must cover and the design question it now turns on: faithfully modelling env's parser (bounded/quote-aware/option-aware) is more than the "no nested re-tokenizing" the remediation assumed, while the tokenize.go "sh -c unparseable => documented non-match" precedent is a FAIL-OPEN for a denylist guard, so it does not transfer. This is the iss-189/190 pattern — repeated local-patch BLOCKs on one root cause mean the next move is an agreed design, not another patch. Rejected here: hot-patching the reviewers' suggested fixes and re-reviewing in-session (pushing through the STOP on a security-critical guard).

  • dcn-26081500000000032026-08-15

    2026-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-26081500000000022026-08-15

    2026-08-15 — itd-84 (intent decomposition) ADOPTED at the MVP rung, per its own staged promotion ladder: the decompose-before-filing principle is filed, the hand-run four-piece protocol lives in the /abcd:intent surface page (capture and the planning interview both run it, loud-staged as not-yet-automated), a DECOMPOSITION rules domain injects the rule at recall time, and every hand-run is graded into .abcd/development/research/notes/2026-08-15-decomposition-calibration.md (the 2026-07-13 auto-merge SPLIT case seeds the corpus retrospectively). The deterministic Go pre-pass is admitted to the predictable-development plan's queue (front-door design open: decompose subverb vs a check in intent ready; collision with iss-210 noted). The capture-time agent rung stays DEFERRED until ~50 graded captures exist (itd-81 calibration); building or running it earlier is a recorded STOP. Rejected: overriding the bundled INTENTS rules domain to carry the new rule (a per-field override replaces the whole array and would withhold future bundled upgrades — iss-174's exact failure mode), hence the additive custom domain instead.

  • dcn-26081500000000012026-08-15

    2026-08-15 — three forward plans adopted at a maintainer grill, absorbing the existing queue rather than adding to it: 2026-08-15-plugin-user-safety.md (execution priority 1; owns install-experience Cut B pick-up and the v0.5.0 security remainder; fix queue opens iss-200 then iss-195), 2026-08-15-predictable-development.md (priority 2; itd-109 promotion is the headline; absorbs the v0.5.0 consistency remainder), 2026-08-15-facilitator-experience.md (continuous, rides along; supersedes the explainability plan's pick-up role). The plan 1/3 boundary is touch-vs-machinery: what a facilitator directly invokes or reads versus automation that guarantees behaviour without human action. Each plan admits items by a stated admission test with the ledger remaining the backlog of record. Same grill: iss-189/190 retired by SUPERSESSION, not wontfix — the defects are real, the local-patch avenue is exhausted (three BLOCKed rounds), so both resolve into the new iss-229 (the recorded 2026-08-08 galloping-probe/trueMatchEnd structural design) with their repros as its acceptance corpus; and itd-111's one-tap micro-prompt open question graduated to its own capture iss-230, homed in the facilitator plan. Rejected: wontfixing 189/190 (asserts the defects don't matter), a full 104-issue triage into the plans (stale mirror of the ledger), and executing the plans in the listed 1-2-3 order (the safety floor and the compounding accelerators come first).

  • dcn-26081100000000012026-08-11

    2026-08-11 — Pull-request lifecycle automation for autonomous rounds settled five points, recorded against the existing records rather than a new intent (one-canonical-primitive: iss-172, iss-178 and itd-107 already hold this ground; capture promote would have minted a sixth). (1) AUTO-MERGE ELIGIBILITY splits on additive-versus-editing, not documentation-versus-code: a new record file plus an append to this log, insertions only, record gate green, single commit. The evidence is this repo's own correction history — the post-merge correction commits in the recent window each fix a FALSE CLAIM about the system ("describe the real fix", "state what is true", the packaging and exclusion claims), which no deterministic gate catches, and all of them sit in changes that REWRITE existing prose; the purely additive captures needed none. (2) The eligible set is an ALLOWLIST of inert paths, never a denylist of source extensions: the plugin command pages, the rules file, the lint configuration and the agent-instruction router are markdown or JSON that change behaviour, so a "no source touched" test fails open on all of them. (3) Intent DRAFTS count as additive — the lifecycle already gates at promotion (adoption is a maintainer decision; implementing an unready intent is a STOP), so a second gate at merge is redundant. (4) The strict status-check policy is NOT relaxed to smooth the stalled-behind-base condition: it is the only thing that gates a concurrently-minted duplicate record id, because the mint lock is a filesystem lock that does not span checkouts and each branch passes in isolation; the stall is cleared by updating the branch instead. (5) Delivery is rung 1 first — protocol in the rendered routine, host credentials — per script-first-mvp, with the binary acquiring no platform CLI dependency. Deferred to the itd-107 grill: the rung-2 credential question, a declared merge style, peer-session concurrency policy, and attribution-footer defence depth.

  • dcn-26080800000000022026-08-08

    2026-08-08 — bug-hunt loop round 9 (state issue #197): a multi-angle sweep (5 blind hunt angles plus independent adversarial verification) surfaced a complete, silent bypass of every guard blocker via env -S/--split-string (GNU env re-splits and runs that value as the command; the guard's wrapper table treated it as the wrapper's own value and stepped past it). A fix attempt (branch bugfix/env-split-string-guard-bypass, closing the separate-token spelling env -S git push ...) was BLOCKed at pre-PR review by two independent reviewers (correctness and security), who each independently found the fix incomplete: the glued spellings env -Sgit ... and env --split-string=git ... execute identically to the closed form and remained a live bypass. Per protocol this is a first-attempt BLOCK, not a repeat of the unrelated iss-189/190 scanner root cause, so it stops here rather than escalating — nothing from that branch was pushed. The complete bug (all three spellings, plus the reviewers' converging suggested repair — handle env's -S<value>/--split-string=<value> forms alongside the separate-token form in commandOf/skipWrapperArgs, no nested re-tokenizing needed) is captured fresh as iss-200, since iss-196 (the narrower, incomplete framing) only ever existed on the abandoned, unpushed branch and was never merged; treat iss-196 as superseded by iss-200 the way iss-191 was re-scoped into iss-195.

    The same sweep also confirmed three further bugs, captured here record-only (no behaviour changes in this commit): iss-201 (abcd guard hook's stdin read has no overflow check, so a payload padded past the 1 MiB cap silently truncates, fails JSON parsing, and fail-opens with a diagnostic that misleadingly blames the host instead of reporting the cap overflow — major, not critical, since the practical exploitation cost is a single tool_input exceeding roughly 1 MiB of model-generated content, and the fail-open is loud, never silent); iss-202 (scanner.New reads .abcd/config/pii.json with a bare, unguarded os.ReadFile — no symlink guard, no size cap — unlike every sibling trust-boundary config reader in this codebase; a FIFO hangs it forever and a git-committable symlink to a device file grows it toward OOM, both reachable automatically via the SessionEnd hook, and the hang also wedges history.repoLock's unbounded flock, permanently disabling transcript capture for that repo — the same bug class already fixed once under iss-97, which this instance escaped); and iss-203 (abcd audit's privacy rule guards on scanner.New's error return expecting a fallback to the built-in pattern set, but scanner.New never returns a non-nil error, so the guard is always true, the documented fallback is dead code, and a broken pii.json override silently drops a repo's raised severities and downgrades the audit exit code from 2 to 1 with no diagnostic).

    Also reconfirmed this round (captured round 7 as iss-195, previously flagged as needing adversarial verification before fix-eligibility): the scanner's rigid/open-ended heuristic false-positive hard_fail-flags RFC 3849 reserved documentation addresses and silently corrupts them via Redact, on top of the previously-known cost regression (up to ~54x on colon-hex content, worse than the ledger's original 1.9x-27x table) — worse than its minor label suggests. Its own fix is out of scope for this round, but iss-195 is a distinct bug in the scanner's rigid/open-ended heuristic, not part of the shelved scanner adjacency-recovery mechanism (iss-189/190/191, shelved per the maintainer's 2026-08-07 ruling); iss-195 itself remains fix-eligible, not shelved. No ledger or code change made for iss-195 this round beyond this reconfirmation note.

  • dcn-26080800000000012026-08-08

    2026-08-08 — iss-189/iss-190 shared root cause identified, fix designed but not implemented: bug-hunt loop rounds 6-8 (state issue #197) each attempted a local patch to scanAllPatterns/probeAt's 512-byte adjacency window (internal/adapter/scanner/scanner.go) and each was BLOCKed on review for the same underlying reason — a truncated, possibly-ambiguous window-edge view was driving a discard/skip decision that reached further than the ambiguity itself (round 6: discarding a window-edge match lost the forward-chaining offset; round 7: discarding lost a genuine shorter match, and its boundary classifier mis-fired on multi-alternation patterns; round 8: an uncertain match end wrongly suppressed stolenJunctions, a backward search that never depended on that offset being exact). Recommended structural fix: replace the fixed-window single-shot probe with a galloping/exponential-doubling probe (trueMatchEnd) that grows the window only while a match keeps running into its edge, and stops the moment the match ends short of the edge or the window reaches the real end of line — so m.end is always the true end, never an artifact of truncation. This removes iss-189's boundary-ambiguity question outright (no more guessing whether \b is real, so no classifier to get wrong) and iss-190's "clipped, so skip chaining" special case (nothing is ever clipped), without reintroducing round 6's cost regression — it only grows for matches that are genuinely still growing, at the same amortized cost class the top-level unbounded match in the same function already pays. Not yet implemented or reviewed; captured here so the next attempt (an autonomous ROOT-CAUSE ESCALATION round, or a human) starts from this direction instead of re-deriving it from the same three round post-mortems.

  • dcn-26080700000000022026-08-07

    2026-08-07 — iss-191 re-scoped by maintainer ruling: the round-3 merge-gate review's cost finding is a different mechanism from the compile-fallback iss-191 actually describes, so the two are split. iss-191 keeps its narrow, still-accurate scope (junctionProbe's (?s). fallback; verified not to trigger on the bundled set, whose combined alternation compiles cleanly). The reachable half is captured as iss-195: the rigid/open-ended heuristic classifies net_ipv4/net_ipv6 as open-ended, so every address match in ordinary content enters stolenJunctions' backward search — benchmarked at 1.9x–27x versus the pre-iss-188 tree on identical reserved-documentation content (full table in iss-195's ledger entry; scratch benchmark artefacts are local-tier and ephemeral, so the entry carries the numbers). Capture is record-only; no behaviour changes.

  • dcn-26080700000000012026-08-07

    2026-08-07 — release retention: the newest-per-line prune (brief § 3, itd-70) is computed and previewable but has never run, so v0.4.0 and v0.4.1 survive against the policy. They stay: pruning them by hand would spend the only live fixture itd-70 has to prove itself against, and the first real prune should be the shipped mechanism's. The doc-currency half — prose that describes the policy as operating — is captured as iss-194.

  • dcn-26080600000000052026-08-06

    2026-08-06 — attribution epoch: the full git history (main, all release tags, and the open work branch) is rewritten to normalise commit attribution — AI-tool author/committer identities and two misconfigured machine-local identities all map to the maintainer's account, AI co-author trailers are removed, and every commit that had AI involvement carries an Assisted-by trailer (the disclosure convention; added where missing). Every rewritten commit's tree is byte-identical to its predecessor — content is untouched; only hashes and attribution change. Consequence for the record: any commit SHA cited in records, receipts, or issue threads dated before 2026-08-06 refers to the pre-rewrite history and no longer resolves from a current checkout; treat those citations as historical, keyed to the old epoch.

  • dcn-26080600000000042026-08-06

    2026-08-06 — iss-183: of the two fix directions the issue offered, REWORD is taken and wiring is not. The descriptive instances now carry the channel-truthful phrasing iss-43 established in the README — .abcd/** is present in every repository checkout, marketplace installs and release source archives included, and never in the released binaries — with the launch bundler named as the implemented structural namespace deny that no cut release has yet run, rather than as an operating packaging filter. Wiring the launch publish path so the deny actually runs on a real release stays open feature work with its own design questions (the marketplace manifest schema has no per-path exclusion, and release.yml uploads the binaries without invoking the verb), and is deliberately not assumed by this wording. Two candidate sites are classified exempt on genre rather than reworded: 01-press-release.md, which states the intended product in press-release voice throughout, and 04-surfaces/04-launch.md, whose mention sits inside its explicit "full-cut design" framing and is already truthful. One instance the issue body's list missed surfaced only under a case-insensitive re-enumeration — AGENTS.md's working-tree-layout line, capitalised "Excluded from the release artifact" — which is why the closing sweep runs the three phrases with -i.

  • dcn-26080600000000032026-08-06

    2026-08-06 — iss-187 (bug-hunt loop, round 1): rules.Merge (internal/core/rules/rules.go) assigned override domain keys straight into out.Domains without ever allocating that map, because its cloneRuleSet helper deliberately preserves a nil Domains (it only allocates when the source map is non-nil). A base such as RuleSet{SchemaVersion: 1} — which Validate accepts — therefore panicked with "assignment to entry in nil map" the moment the overlay carried a domain, contradicting Merge's own doc comment ("New domain keys are added"), which states no such precondition. Not reachable in production today: the sole call site, RuleSet.Load, always passes Merge(Defaults(), over) and Defaults() always has a populated map — so this was a latent defect in an exported API contract that would go live for the first caller merging onto a non-Defaults() base (a future multi-tier overlay starting from an empty set). Fixed at the Merge call site by allocating out.Domains when it is nil and the overlay has at least one key, matching the idiom the sibling loader guard.Merge (internal/core/guard/config.go) already uses for out.Entries; cloneRuleSet keeps its nil-preserving semantics, so no other caller's behaviour moves. Repro: internal/core/rules/rules_test.go, TestMergeNilBaseDomainsAddsNewKeys, watched failing on pre-fix code for the claimed reason (panic: assignment to entry in nil map) and passing after.

  • dcn-26080600000000022026-08-06

    2026-08-06 — v0.4.2 release cut: content commit 3377980 (changelog roll; eight [0.4.1]-duplicate Unreleased entries removed first), semantic gates both PROMOTE at full tier. Docs-currency: zero findings. Brief↔surface crosscheck: 26 discrepancies, all design-record drift, dispositioned per the iss-152 precedent — captured as iss-192, release not blocked. Version derived v0.4.2 (additive, pre-1.0 → patch bump per plan §3/adr-37; the run plan's "v0.5.0" was a prediction the derivation corrects). Crosscheck ran via direct harness subagents after the workflow runner failed on a session permission-handler fault (22/22 vacuous errors — discarded, never treated as a pass); pinned prompts unchanged.

  • dcn-26080600000000012026-08-06

    2026-08-06 — iss-186 (bug-hunt loop, round 4): commitTransition (internal/core/capture/workflow.go) wrote the destination file before removing the source, so a non-ENOENT os.Remove(src) failure (EPERM/EROFS/EIO — e.g. an immutable source status dir, or a read-only remount) returned an error after dst had already landed, with no rollback. The issue id was then present in both status dirs at once, and findIssue rejects any id present in more than one file as ErrDuplicateIssueID — so the stranded copy could never again be resolved or wontfixed without a human manually deleting one file; List/Status also double-counted it, since scanLedger does not dedupe. Fixed by rolling the destination back (best-effort os.Remove(dst)) whenever the source remove fails for a reason other than "already gone", restoring the pre-call state so a retry is all that is needed once the underlying failure clears; a failed rollback itself is surfaced in the returned error rather than swallowed. A non-ENOENT remove failure has no portable, cross-platform way to trigger deterministically in a test (immutable attributes and read-only remounts are Linux/ext4- and permission-model-specific, and this repo's CI runs macOS and Linux), so a test-only seam (removeSourceHook, nil in production) was added, mirroring the existing beforeOrphanRemoveHook pattern in alloc.go. Repro: internal/core/capture/workflow_test.go, TestTransitionRemoveFailureDoesNotStrandIssueInTwoDirs, watched failing on pre-fix code for the claimed reason (destination not rolled back) and passing after.

  • dcn-26080500000000112026-08-05

    2026-08-05 — iss-188 follow-up (two independent adversarial reviews of the fix above, both landing on the same defect): the bounded backward search in internal/adapter/scanner/scanner.go (stolenJunctions) could step OVER the junction it was looking for. junctionProbe is unanchored, so one of its hits can SPAN a real junction — begin before it and end after it — without beginning at it; the loop nevertheless resumed at that hit's END (off += loc[1]) even when the hit's own offset had just been REJECTED by wholeMatch, skipping every byte in between, the true junction among them. Nothing revisits a skipped range, so the search returned fewer cuts than it should and iss-188's own failure mode reopened through a narrower trigger: "ghp_"+32×a+"AIza"+4×b+"ghp_"+36×c reported one finding and left the second token's tail raw, and "ghp_"+10×a+"AIza"+22×z+"sk-proj-"+40×i — where the skipped-over decoy is itself a syntactically valid secret — left 48 raw bytes of an OpenAI project key through Redact with the fail-closed residual re-scan reporting the output clean. Fixed by always resuming at cut + 1, dropping the jump-to-hit-end fast path entirely: a rejected candidate can hide a real junction one byte later, and an accepted one is not worth a special case. This stays bounded for the reason the whole feature exists: the loop is capped at maxAdjacencyBacktrack (512) iterations per match regardless of how long the match is, and each iteration's search is capped at maxAdjacencyBacktrack + maxAdjacencyProbeWindow bytes by RE2's linear guarantee — so the per-match cost is a constant factor independent of the REST of the line, and the whole scan stays linear in line length rather than quadratic. Measured: doubling and quadrupling an adversarial 247KB line doubled and quadrupled the time (2.3s / 4.6s / 9.2s), which is the property that matters. Repro: internal/adapter/scanner/adjacency_test.go, TestStolenJunctionSearchDoesNotSkipPastRejectedCandidate and TestStolenJunctionSearchSkipsPastValidDecoySecret, both watched failing on pre-fix code for the claimed reason; cost guard TestJunctionBacktrackIsBounded, extended with dense_rejected_candidates_in_backtrack_window — every match's window packed with candidates that all fail validation, the worst case for advancing one byte at a time. Two further gaps the same reviews found were CAPTURED, not folded in: iss-190 (a recovered match longer than maxAdjacencyProbeWindow is truncated, and the misaligned artificial end breaks the chain that would recover a THIRD abutting token — the pre-existing iss-185 window trade-off reached through a new path, whose real fix is an adaptive window that risks reintroducing the unbounded per-match cost) and iss-191 (junctionProbe's (?s). compile fallback would validate once per byte instead of once per candidate, unreachable with the bundled pattern set). Two comment claims were also corrected as inaccurate: cost is bounded independently of the rest of the line but IS proportional to the match's own length, since wholeMatch re-runs the probe over the prefix; and a window-exceeding recovery can miss a token ENTIRELY, not merely truncate it, when the pattern's required structural markers (jwt_shaped's two . separators) both fall outside the window.

  • dcn-26080500000000102026-08-05

    2026-08-05 — iss-188 (bug-hunt loop, follow-on to iss-185): a secret pattern whose quantifier is open-ended (\bghp_[A-Za-z0-9]{36,} and the seven other {n,} families) greedily consumes a following token's own leading bytes when those fall inside its trailing character class, so the true junction sits BEFORE the match's reported end and iss-185's forward adjacency probe — which only ever looks at that end — never runs where the second token actually starts. "ghp_"+36×a+"ghp_"+36×b reported one finding covering ghp_aaa…aaaghp and left _bbb…bbb raw through Redact, with history's fail-closed residual re-scan reporting the output clean: the same live-secret-reaches-disk violation iss-185 closed for the fixed-length family. Fixed in internal/adapter/scanner/scanner.go:465 (stolenJunctions): before a match's reported end is accepted as final, a bounded backward search walks candidate cuts and reports each one where the shortened prefix is STILL a whole match for its own pattern AND a token can begin, and scanAllPatterns probes those cuts exactly as it probes the forward end. Open-ended is detected from the compiled regexp — a match that cannot still match one byte shorter has a rigid length and is skipped after one test — not from hand-annotated metadata, so a pattern added later inherits the classification. Three things keep the cost per match rather than per match LENGTH, which the ledger entry named as the trap (an unbounded backward scan would trade the leak for a resource-exhaustion cliff on exactly the huge single-line input a scanner must handle): that one-test early-out, maxAdjacencyBacktrack (512, mirroring maxAdjacencyProbeWindow), and a single combined junctionProbe alternation over the whole pattern set that generates candidate cuts in one linear pass instead of one pass per pattern — measured 40s unbounded against 0.3s bounded on a 200KB line. The over-long match is deliberately left untrimmed: it only over-reports the first token's span, and sealLine already forces every overlap byte to *. Repro: internal/adapter/scanner/adjacency_test.go, TestConcatenatedOpenEndedSecretsBothDetected (the ledger entry's literal reproducer) and TestOpenEndedSecretSwallowingDifferentFamilyBothDetected (a whole AKIA key swallowed by an alnum class run), both watched failing on pre-fix code for the claimed reason; cost guard TestJunctionBacktrackIsBounded.

  • dcn-26080500000000092026-08-05

    2026-08-05 — iss-185 (bug-hunt loop, round 3): ScanText's leading-\b-anchored secret patterns could never detect a second fixed-length token immediately abutting a first with no separator — the byte before the second token is itself a word character (the first token's own last byte), a word/word transition where \b never holds, so FindAllStringIndex silently returns only the first match. Redact then left the second token's whole body raw, and history's stage-two fail-closed residual re-scan reported the redacted text clean anyway, so a concatenated pair of secrets reached disk with one still live. Landed after three rounds of pre-PR/pre-merge adversarial review, each catching a real problem in the pass before it: (1) the first pass's own-pattern-only probe missed a mixed pair of different fixed-length patterns, and double-counted a google_api_key match whose dash-terminated 35th char already satisfied \b on its own; (2) the fix for that, an unanchored FindStringIndex probe, cost O(matches × patterns × remaining line length) — measured at 14–49s on large single-line input; (3) anchoring the probe with \A fixed the restart-at-every-offset cost but not the cost of one attempt against two patterns (net_lan_hostname, net_device_hostname) that carry their own unbounded internal quantifier, still quadratic on many back-to-back fixed-length tokens. The landed shape: adjacencyProbe compiles an \A-anchored, \b-stripped (past any inline flag group) variant of each pattern; scanAllPatterns probes every pattern's variant, within a small fixed window (maxAdjacencyProbeWindow, 512 bytes) so one attempt can never cost more than a constant regardless of what follows, at the byte offset immediately after each already-found match, deduplicated against matches already found. A pattern with an open-ended quantifier can still greedily consume into a following token before this recovery ever runs — a separate, broader gap, captured as iss-188 rather than folded in here. Repro: internal/adapter/scanner/adjacency_test.go, TestConcatenatedSecretsBothDetected (the original bug), TestConcatenatedDifferentFixedLengthSecretsBothDetected and TestGoogleAPIKeyDashJunctionNotDoubleCounted (review round 1), TestAdjacencyProbeStaysLinearOnLongLines and TestAdjacencyProbeWindowIsBounded (review rounds 2 and 3).

  • dcn-26080500000000082026-08-05

    2026-08-05 — iss-118: DECISIONS.md and ACKNOWLEDGEMENTS.md gain merge=union in .gitattributes, the same remedy already in place for CHANGELOG.md. Both are the identical shape — append-only ledgers of anonymous, dated, order-independent entries that never need identity — so a concurrent-append conflict has nothing to actually disagree on; the union driver keeps both sides instead of stopping the merge. Prompted directly by the bug-hunt loop's bugfix/iss-184-… branch hitting exactly this conflict against .abcd/work/DECISIONS.md on PR #199, which iss-118 had already diagnosed (filed after an earlier merge hit the same conflict) but left unresolved pending this design call. Full atomicisation (per-decision records, a new id family, an armed uniqueness detector) was the other option iss-118 named; not pursued here as disproportionate to a minor, low-traffic hotspot. Impact recorded as internal, no CHANGELOG entry — matching the iss-80 precedent for a process/tooling change with no user-facing behaviour.

  • dcn-26080500000000072026-08-05

    2026-08-05 — iss-43, CORRECTION to the entry immediately above, from a merge-gate record-accuracy review on PR #196. That entry stands unedited; four of its claims are corrected here rather than in place, because it is merged history. (1) It opens "the three-claim corpus is closed as OVERTAKEN rather than fixed", and the corpus does not close as a unit: claims 1 and 2 — the Phase 0 status claim and the native-capability surface list — close as overtaken via 73428b6, while claim 3's surviving half, the Layout line, is FIXED by that same PR. The entry knows this later in its own text and in the issue's resolution: field, so the opening verdict was a second over-claim of the same shape as the attribution it goes on to retract: a single verdict asserted over a corpus whose members had different fates. (2) "a SHALLOW clone whose truncation window opened well after 2026-07-17" over-claims. The evidence bounds the boundary to the interval after 2026-07-17 and no later than the oldest visible substantive README rewrite; "well after" asserts a distance nothing measured. Read it as "after 2026-07-17". (3) "writing the doc to describe a packaging mechanism that does not exist" is refuted by the entry's own closing paragraph. The clause scopes to the all-channel curated publish path, which genuinely does not exist and which no release has ever taken; the namespace deny itself exists and is tested. (4) The call edge is wrong in the closing paragraph: "reachable from the wired abcd launch ship; it is unwired, because Ship stops at WouldPublish" reads as one chain, implying the verb runs through launch.Ship. It does not. launch.Ship has NO production caller — the only calls are three in dryrun_test.go — while the wired verb exercises the deny through launch.PrecheckPayload and launch.RenderPayload, which resolve the bundle at internal/core/launch/render.go:192, reached from internal/surface/cli/ship.go. release.yml invokes neither. Both facts stand; the edge joining them did not. The lesson generalises past this entry: a summary sentence written before the detail paragraphs are finished tends to keep the verdict the round started with, and a call chain assembled from two true sentences about neighbouring functions is not evidence that either calls the other — grep for the callers.

  • dcn-26080500000000062026-08-05

    2026-08-05 — bug-hunt loop round 1: iss-184 (critical, guard tokenizer heredoc misparse) fixed at root cause, in two passes after a pre-PR adversarial security review caught the first pass narrowing the hole rather than closing it. internal/core/guard/tokenize.go's << handling already special-cased the literal-digit arithmetic-shift form ($((1<<20)) is not a heredoc), but isDelimStart accepts any identifier-shaped word, so $((1<<shift)) — an identifier operand — still read as a heredoc delimiter, and skipHeredocBodies then silently consumed every remaining line of the command looking for a "shift" terminator line that never comes, dropping later commands (a force-push, an rm -rf, anything) from ever reaching command position — a silent allow, not the loud fail-open the hook's own doc comment promises for anything the tokenizer cannot answer confidently. The first pass made skipHeredocBodies report whether it actually found each pending heredoc's terminator, turning a miss into ErrUnparsableCommand. The security review then constructed the exploit this missed: an attacker supplying a later line that happens to equal the misread "delimiter" (e.g. appending a bare shift) still finds a match, so the swallow still succeeds silently — the fix only closed the unterminated half of the class, not the coincidentally-terminated half, which is the one an attacker actually controls. The real fix is classification, not detection-of-failure: a heredoc delimiter word immediately followed by a bare ( or ) with no separator is never a real heredoc — its body and terminator line have to come first, so nothing legitimate places a paren directly against the delimiter word, and $((expr<<ident)) produces exactly that shape. << in that position is now read as the arithmetic operator at tokenize time, same as the literal-digit case, so the guarded line is reached and matched normally regardless of what any later line contains. The unterminated-body-to-error fix from the first pass is kept as defense in depth for genuinely malformed heredocs (cat <<EOF with no closing EOF line), a distinct, narrower gap the same swallow also covered — an existing test that pinned that silent-swallow as intended behaviour is updated to assert the corrected ErrUnparsableCommand contract. Detectors: TestArithmeticShiftByIdentifierIsNotAHeredoc, TestArithmeticShiftCoincidentalDelimiterStillBlocks (the adversarial payload the security review demonstrated), and TestTokenizeRejectsUnterminatedHeredoc — each watched failing on pre-fix code for the claimed reason and passing after. Three more bugs surfaced by the same round's multi-angle sweep and independently verified with failing tests are captured but not fixed here — iss-185 (critical, scanner leaves a second back-to-back secret token undetected and unredacted, defeating history's fail-closed residual re-scan), iss-186 (minor, a failed source-unlink in a capture ledger transition can permanently strand an issue id across two status directories), iss-187 (minor, rules.Merge panics on a nil-Domains base — currently unreachable through any live caller, so a latent exported-API contract defect) — left open for a future round, highest severity first.

  • dcn-26080500000000052026-08-05

    2026-08-05 — iss-43 (v0.5.0 item D): the three-claim corpus is closed as OVERTAKEN rather than fixed — the Status section and the surface list were removed by 73428b6 (2026-07-17, "manual: Revise README with new badges and project details"), a manual revision predating the v0.5.0 plan, so the Phase 0 claim and the native review oracle / spec-task engine / autonomous run claims no longer exist to correct, and re-deriving a corpus against a rewritten document would be inventing findings to justify a ticket. That attribution is itself a correction worth recording: the round first credited the iss-143 tagline commit 48a3524, which touches ONE README line (the strapline), because it read a SHALLOW clone whose truncation window opened well after 2026-07-17 and therefore could not see the real commit — a truncated history answers a git log question confidently and wrongly, and the cheap guard is git log -S over the file for the exact removed string, unshallowed first. Two corollaries earned the same way: the corpus's third claim was never 73428b6's at all (git log -S "never shipped" puts that line in the scaffold commit and in this branch alone), so "all three overtaken" was a second wrong attribution riding on the first; and a whole-phrase probe can miss a claim that was line-wrapped in the original, which is why "spec/task" reproduces where "spec/task engine" returns nothing. One instance survives, and it is half true rather than false, which is why it needed splitting instead of deleting: the Layout line called .abcd/ "never shipped", which holds for the released binaries alone (release.yml uploads the four of them and checksums.txt, nothing else) and fails everywhere else — .claude-plugin/marketplace.json declares source: "./", so a marketplace install takes the whole repository, and GitHub attaches auto-generated source archives to each release, which carry the directory too because .gitattributes declares no export-ignore. The line now divides on the boundary that is real: every repository checkout against the released binaries, rather than a per-channel split that would have been wrong about the release page. Doc-side deliberately: the marketplace manifest schema has no per-path exclusion, so making "never shipped" true everywhere means building a curated publish path — feature work with its own design questions, not doc repair, and writing the doc to describe a packaging mechanism that does not exist is the phantom-claim failure this item belongs to. The proposed detector (README capability and status claims resolve to wired verbs and to the roadmap) is DROPPED here and re-pointed at iss-181 as a candidate extension of the gate cross-check detector's scope, recorded as a candidate rather than a commitment because it shares that detector's two unsettled scoping questions and a second half-specified scanner would answer neither. The same claim survives across the record — CONTEXT.md's sharp-edges list, AGENTS.md, both .abcd/ READMEs, 02-constraints/01-platform.md, 05-internals/03-configuration.md and phase-1-ahoy.md, with adr-0028, the dated plans and the planned/shipped intent bodies exempt as decision and historical records — and it is recorded as iss-183 rather than fixed here, since the disposition scoped this item to one README line. That issue also corrects a claim this round made twice: the exclusion is NOT unimplemented. internal/core/launch/bundle.go denies the .abcd namespace structurally, with tests, reachable from the wired abcd launch ship; it is unwired, because Ship stops at WouldPublish with no network call and release.yml uploads the binaries without ever invoking the verb. "No mechanism exists" and "the mechanism never runs" ask for different fixes, and only the second is true.

  • dcn-26080500000000042026-08-05

    2026-08-05 — CORRECTION to the entry immediately above, from a merge-gate record-accuracy review on PR #195. That entry, and iss-80's own resolution: field, said the branch-local id-collision class "was closed" by iss-115/iss-120. It was not: internal/core/recordid/recordid.go's own package doc documents an ACCEPTED, undocumented-in-that-entry residual window — two branches that BOTH mint before either commits still collide — left to the already-armed record-lint uniqueness detectors (issue_id_unique, intent_lifecycle, spec_id_unique) as backstop, the same trade-off iss-120's own resolution names verbatim ("the armed record-lint detectors as the residual-window backstop"). iss-80's body asked for a fully collision-free minting scheme (forge-minted / random-suffix / timestamp / reserve-registry); that was never built, that trade-off was made when iss-115/iss-120 landed rather than here, and no open item currently tracks the residual window separately. Both iss-80's resolution: field and this log now say "already addressed, not closed to zero" and name the trade-off explicitly, rather than implying the class was eliminated. The test-coverage work in the entry above (the two new refunion tests) is unaffected and stands as described.

  • dcn-26080500000000032026-08-05

    2026-08-05 — iss-80 (v0.5.0): resolved as already-fixed, with the residual verification gap closed rather than the defect re-fixed. The branch-local id-collision class this item tracked — itd-N/spc-N/iss-N allocators scanning only the working tree, so two agents on branches cut from one base each mint the same id and collide at merge — was already closed by iss-115 and iss-120, which introduced recordid.MaxAcrossRefs (scan every git ref for the family's highest committed id) and folded it into all three minting paths: internal/core/spec/store.go, internal/core/intent/create.go, and internal/core/capture/workflow.go. What survived was uneven evidence, not an uneven fix: only the spc-N family had an end-to-end regression test standing up a real two-branch history (internal/core/spec/refunion_test.go), while none of capture's or intent's existing tests stood up a real two-branch history through Capture/CreateFromText and so never drove the ref scan through their public entry points at all — MaxAcrossRefs was exercised only as a primitive in its own package test, never as wiring. That is the shape in which a fix silently un-wires: a refactor that dropped the MaxAcrossRefs call from Capture or CreateFromText would have left every existing test in both packages green. So this round adds internal/core/capture/refunion_test.go (TestCaptureMintsPastACommittedBranch) and internal/core/intent/refunion_test.go (TestCreateFromTextMintsPastACommittedBranch), each mirroring the spec test's exact fixture via internal/gittest.NewRepo — branch A mints and commits record 1, branch B is cut from before that commit so its working tree carries no record, and B must mint record 2. Both were mutation-checked before being trusted: with MaxAcrossRefs stubbed to return an empty RefScan, each fails with precisely the collision it names (iss-1/itd-1 re-minted on branch B), and all three families fail together — so the tests are pinned to the ref-union behaviour rather than passing incidentally. No production code was touched, which is the point: the minting paths were verified correct by reading before the coverage was written, and the change is test-and-record only. Impact recorded as internal and no CHANGELOG entry, matching the iss-34 precedent for a test-only closure with no user-facing behaviour change.

  • dcn-26080500000000022026-08-05

    2026-08-05 — iss-44 + iss-160 + iss-161 + iss-162 (v0.5.0 item D, one work item): the plugin surface is reconciled with every document describing it, and the reconciliation is a MOVE rather than a rename, because the harness's namespace rule leaves no other answer. Verb files under commands/abcd/ registered as /abcd:abcd:<verb> — a commands/ subdirectory IS a namespace segment, and this one was named after the plugin, so the prefix appeared twice and every documented /abcd:<verb> was an unknown command (iss-161). Flattening into commands/ is what makes the printed guidance runnable, which is why iss-162 needed no rewrite at all: all eighteen verb files already spelled /abcd:<verb> in their self- and cross-references — verified by grep across every one rather than assumed — so the guidance was correct prose about a name nothing registered. On iss-160 the fix direction was settled by evidence, not preference: the loader registers every markdown file under commands/, requiring no frontmatter and exempting no name (this repo's own iss-110 records agents/README.md registering as an agent; the published plugin reference describes commands purely as flat .md files with no ignore list), so NO in-place form keeps a readme unregistered and the only reliable home is outside the auto-discovery root. It goes to the brief's surface registry, which already enumerates the same surface and is already machine-checked against it — folding the doc into the gate that guards it rather than leaving a second enumeration to drift. The cost is one repointed link in a 2026-07-12 plan, paid because links_resolve is a blocker and a dangling pointer is not history. iss-44's three instances close with them: ahoy gains a section per sub-verb (with identity-check carrying an explicit CLI-only note, because its exit code is the point of wiring it into a hook — an absence recorded as a decision is not a gap), every make build remedy is replaced by the go run ./cmd/abcd … fallback the same paragraphs already carried, and memory's renders stop naming a front door from internal/core, which is transport-agnostic by boundary rule: the heading a plain-CLI reader sees must not claim they invoked a plugin command they may not have installed. Detectors first, both watched failing: a surface-parity test over the real command tree and the real directory (flat-and-commands-only, every sub-verb reachable or scoped, no unrunnable remedy), and a string-literal check over internal/core/memory — literals, not comments, because prose explaining a surface may name it. surface_coverage gains a bare_command field so the flat directory's top-level board file is excluded the way README already is, rather than demanding a registry row that cannot exist; hardcoding the name would have been wrong in a lint engine that ships to repos whose plugin is not called abcd. Left alone deliberately: the historical citations of commands/abcd/ across decisions, shipped intents, closed specs, research and resolved issues — they describe the tree as it was, and rewriting them would trade a true record for a tidy one. Not fixed here, and reported instead: the release-gate manifest's promptHash pins prompt text this change edits, by an algorithm nothing in the tree computes or verifies, so it is left untouched rather than guessed at.

  • dcn-26080500000000012026-08-05

    2026-08-05 — iss-37 (v0.5.0 item D): re-scoped in place per the 2026-08-03 maintainer disposition, from five instances to the three doc claims that describe the gate suite wrongly, and the fix direction is doc-side throughout because the issue's class is claims-must-match-reality and the disposition frames all three as doc claims — the Makefile and every gate's behaviour are untouched. AGENTS.md names the three lint gates make preflight runs (lint-reviews, record-lint, docs-lint) ahead of build/vet/test/race, and its definition of done keeps gofmt -l . as a requirement while attributing it to CI's own format step rather than to preflight, which does not run gofmt. The ci.yml record-lint comment claimed the step was "visible but non-blocking for now"; the step has no continue-on-error and record-lint exits non-zero on a blocker, so the comment described an intention the workflow had already outgrown — it now states the gate blocks and that warns surface in the log only (comment-only; no step structure touched). README.md and CONTRIBUTING.md describe the real suite, and CONTRIBUTING stops claiming preflight and CI run "the same checks" where they do not. Instance 1 of the original five (the docs/reference/cli/README.md freshness claim) was verified accurate in round 13 and carries no work. The brief's 06-lint.md section-1 catalogue — a predecessor project's Python-era IL001–RC007 families and class names — plus the gate cross-check detector are re-filed as iss-181 rather than reworked here, because the disposition on them is substantive (remove the catalogue, never archive it; do NOT mint a Go-equivalent numbered scheme, which is taxonomy design and would ship already-stale against this cycle's own rules; rework section 1 generically over the live armed rules and internal/core/lint, with any literal enumeration generated and gated) and the detector's scoping — scan root, and what "a live definition" means for a prose-named gate — is unsettled and recorded as two open questions in that issue's body. iss-37 is resolved against the re-scoped body.

  • dcn-26080300000000022026-08-03

    2026-08-03 — iss-42, CORRECTION to the entry immediately above and three fixes from a fresh adversarial correctness review. (1) That entry claimed two banned_tokens entries made both stalenesses "non-silent on reintroduction". The phantom-research-spikes half did not: its pattern was the literal string research/spikes, which never occurs in the prose it was meant to catch — the record map spells the row as two separate backtick spans (notes/ ... spikes/), so restoring the exact original stale line left record-lint at zero blockers. The claim was written from reading the pattern instead of reproducing the defect, which is the failure the detector-first rule exists to prevent, and the lesson is that a ban's acceptance test is the original line, not the pattern's plausibility. The fix is not a wider regex: ADR-30 and the dated go-rebuild plan carry the same prose shape legitimately, and no pattern separates the living index from the two historical records without an escape they must not be edited to carry. So the row is GATED instead, per iss-38's "delete or gate, never correct and leave hand-kept" — an index_drift region over the row holds it to research/'s actual subdirectories, which catches every spelling of a phantom child AND a real child the row omits, and fails closed if the region is deleted. (2) abcd ideate record wrote its dated verdict record to research/ root, making the shipped binary the standing producer of the very convention violation this item cleared out of that directory by hand; ResearchRelDir now points at research/notes/. spc-18's rationale ("killed ideas are research outcomes, and the research directory is where a future session looks") argues for the research area, not its root, and a verdict record is by spc-18's own words a dated research note — so notes/ is where the record's convention already put it. The CLI surface test asserted the path through the constant, so it would have followed the constant anywhere; it now asserts the literal directory. (3) The rewritten trust caveat over-claimed surface_coverage: the rule reads commands_dir and skills_dir only, while the crosscheck manifest's Direction B enumerates five surface kinds, so the agent, hook, and CLI-verb surfaces are periodic-pass-only. A caveat whose entire job is saying how much is machine-enforced must not overstate it — the same phantom-enforcement class iss-40 flagged — and the wording now names the two surfaces the structural check actually covers.

  • dcn-26080300000000012026-08-03

    2026-08-03 — iss-42 (v0.5.0 item D): CONTEXT.md's sharp-edges list gains a detector rather than only a correction, because the correction alone would have been the third one. The stale trust caveat (still calling iss-35's brief-vs-surface reconciliation "the open cross-check" months after surface_coverage shipped and iss-122 pinned the Direction-A crosscheck) is an instance of a class: the orientation doc grounds a live claim in a record, the record reaches a terminal state, and nothing in the workflow asks anyone to go back. context_citation_currency is that missing requirement made mechanical — it resolves every iss-N/itd-N/spc-N/adr-N handle in the "Live constraints / sharp edges" section against its store and blocks a citation to a terminal bucket (or, for the flat ADR store, a declared supersession or retired status). Deliberately narrow on two axes: ONE section of ONE document, because a terminal-state citation is legitimate in an evidence trail, a supersession chain, and a dated plan — history is supposed to name closed records; and terminal-state only, because a dangling handle is record_schema's question and a second weaker implementation of an answered check is worse than none. Rejected: a git-diff-shaped handoff rule ("a change to a cited record must touch CONTEXT.md in the same commit"), which the ledger entry's wording suggests but which gates the wrong thing — it fires on commits that need no orientation change and stays silent on the case that actually bit us, a record moved in one branch and the caveat left standing in another. The state-based check has no such blind spot: whenever the citation is stale, the gate is red, regardless of which commit made it so. Alongside: research/ stops contradicting its own README (five dated notes move into notes/, where ~25 peers already sit, with every citation followed — the itd-88 fidelity evidence trail, two DECISIONS.md evidence paths, .abcd/rules.json, and a plan link), the development record map's routing row names research/'s real children (notes/ + prompting/, not the phantom spikes/), and two banned_tokens entries make both stalenesses non-silent on reintroduction. The dated plan and the ratified ADR that also mention spikes/ are left untouched: they are chronological snapshots and a ratified decision, not living indexes, and rewriting them to match today would falsify the record — development/README.md alone is corrected because it alone claims to be current.

  • dcn-26080200000000092026-08-02

    2026-08-02 — iss-41 (v0.5.0 item D): the interim delivery-state rule is stated as the one the lifecycle already implies — delivered capability is represented by the intent leaving drafts/, and nothing else says it — because the alternative on offer (a new tier, or a per-intent "partly shipped" field) invents lifecycle vocabulary to describe a citation problem. The ledger's premise that shipped/ is empty has aged out: thirteen intents live there now, so the mechanism exists and what was missing was the gate holding the changelog to it. delivery_state reads each version entry's delivery sections (Added, Changed; a repo's configured list is unioned with those, never substituted for them) and blocks an itd-N citation whose intent is still in drafts/. Scoping by section rather than by whole entry is what keeps it precise: the ids under Fixed in this corpus are provenance for a defect — which draft two branches minted at once — and blocking them would force either a falsehood or a deletion of real information. It fails closed three ways: no changelog, no intents store, and a store holding no lifecycle bucket — the last being a root pointed one level too deep, which resolves every citation to nothing and reads exactly like a clean corpus. The corpus had TWO instances, not the one filed: itd-60, whose deterministic layer shipped as abcd docs lint while its semantic layer is still five open questions, and itd-85, which shipped WHOLE as abcd audit and was simply never promoted. They get different treatments because they are different facts. itd-60 stays in drafts/ and loses the citation — an intent is delivered whole or not at all (split-the-intent doctrine), so citing a partial delivery reads as a promotion that never happened, and splitting itd-60 to make the citation true is editorial work this issue does not carry. itd-85 loses the citation too, but under protest: the honest fix is promotion, and promotion is blocked on the shipped/ schema wanting a non-null spec_id the audit verb has never had. Filed as iss-180 rather than papered over or forced — writing a retroactive spec to satisfy a lint is the failure mode this repo keeps naming. The out-of-scope half is a REUSE, not a new rule: index_drift gained one field, dir_entry, the mirror of entry on the directory side, which reduces a filename stem to the id a document actually enumerates. Without it a hand-written listing can only agree with a directory by transcribing whole slugs, which is a listing nobody writes, and the alternative was a second rule shaped exactly like the first. The list itself had drifted nineteen entries while claiming in its own prose to be derived and "not hand-counted": itd-47, itd-73 and itd-74 had left drafts/ for three different buckets, and sixteen captures were missing. Regenerated, wrapped in the marked region, and the sentence promising hand-kept lockstep is replaced by the gate that enforces it. The four later-phase items that never had an intent id move OUT of the derived list — a derivation cannot produce them, so their presence was what made the claim false in the first place.

  • dcn-26080200000000082026-08-02

    2026-08-02 — iss-40: one canonical glossary, chosen as a ROUTING rule rather than a migration. .abcd/development/brief/glossary/ keeps the name "glossary" and 04-naming.md stops claiming it; what stays behind in 04-naming.md is its ~60-row Reserved-vocabulary table, unchanged, because those rows are closed enums and spec-pinned reserved names (dormant, task_classes members, index.json field names) and the glossary schema's aliases/forbidden_synonyms fields mean nothing for an enum value. Folding them into term files would have invented scope and misused the schema; the defect was the false self-identification, and only that is retired. VR001 keeps its reserved status and its two registration targets — the word "glossary" is removed from its descriptions across the brief and itd-37 so the term resolves to one place, but nothing about what the reserved lint would check is changed, since no Go code implements it. The index is made derived on the brief↔lifeboat-mapping pattern (internal/core/glossary renders, a test in the same package gates the committed README against it) rather than by a new schema-validation engine, which the README had been promising through a JSON-schema file and a abcd lint terminology verb that do not exist. Three limits are recorded rather than papered over: the drift gate checks the index against the term files, NOT each term file against the field tables, so the frontmatter shape stays a review responsibility; the banlist entry names/record/glossary-self-identification reaches only the docs-lint roots (docs/, root README.md), so it guards the published surface, not the brief where the retired phrase lived — adding .abcd/development/brief as a lint root surfaces 75 pre-existing blockers and is its own piece of work; and 05-internals/06-lint.md's TM003–TM011/H1 rows still claim terminology.schema.json-backed schema validation "Delivered" that no Go code implements — the same phantom-enforcement-claim class this change retires for the glossary README's validation section, but for TM003+ it sits outside iss-40's self-identification scope and inside iss-37 (phantom-enforcement-claims), stopped at round 13 pending maintainer disposition; left untouched here rather than pre-empting that disposition.

  • dcn-26080200000000072026-08-02

    2026-08-02 — iss-39 (merge-gate round 3): the exemption-scope enumeration is made exhaustive, and the block-sequence parse stops truncating. scanIntentTree lost its contentExempt filter, and that one scan feeds TWO rules — intent_lifecycle and intent_impact_valid — but the CHANGELOG, the ExemptPaths doc, the per-file walk comment, and contentExempt's own doc each named only the first while reading as an exhaustive partition. A reader arming intent_impact_valid with exempt_paths would therefore conclude it was unchanged and be surprised on upgrade by a new blocker over an exempt record's illegal impact: value, so the changelog now states that consequence outright. record_schema is dropped from that partition and stated separately: it is cross-store and never consulted the exemption, so describing it as having "stopped" honouring one was wrong in a way that would mislead anyone trying to reason about which rules the exemption still governs. Separately, blockSequenceAt broke on a blank or comment line inside a sequence rather than skipping past it. YAML reads - a, blank, # note, - b as one two-item list; stopping at the interruption dropped the tail, and a dropped supersedes handle is not a quiet under-read — it made the bidirectional check assert that another file omits a link that file plainly carries, which is the same false-claim failure the block parse was added to prevent. The corpus has no interrupted sequence today (every .md scanned), so this closed a latent hole rather than a live one. The closing --- is neither blank nor a comment, so the scan still ends at the frontmatter boundary — covered by its own test, because a skip that ran past the delimiter would read a body list as the key's value.

  • dcn-26080200000000062026-08-02

    2026-08-02 — iss-39 (merge-gate pass): four more record_schema corrections, all of the same family as the previous round — a check that was right for one shape and absent for its sibling. (1) The undeclared-directory finding was implemented for store ROOTS only; a directory inside a declared bucket (intents/shipped/archive/) was skipped with no finding at all, so the previous round's flat-store fix closed the escape for one store of four. Both cases are now reported from the one place that reads a directory of records, because a flat store and a declared bucket hold records the same way and a directory in either is a lifecycle nobody declared. (2) spc was missing from the handle pattern although the spec store is indexed and armed: a bidirectional spec supersession tripped a false blocker whose message named the very prefixes it omitted, while the reverse direction parsed to zero handles and was never checked. The alternation now covers every store the rule indexes, and the message is composed from one constant so it cannot drift from the pattern again. (3) superseded_by: [] was a false blocker: the empty flow sequence is this record's house spelling for an empty list (related_rfcs: [] across six ADRs), so it means absence. Fixed with a local isAbsentValue rather than by widening the shared isNull, which also judges scalar fields (kind, impact, slug) where a list literal is a wrong value rather than an unset one. (4) The filename/id check compared strings, so id: adr-0012 in 0012-*.md was reported as a mismatch — contradicting the rule's own stated design that the padded and bare spellings are one handle; it now parses both sides and compares numerically, as every other comparison in the rule already did. Record-side: iss-179 now cites the recoverable evidence for what adr-6 was (.abcd/work/reviews/2026-07-06-plan-consistency/05-link-structure.md lines 47-49 name the original file, 03-cross-corpus-consistency.md line 42 records it as voided by DECISIONS.md lines 8-9 together with adr-8 and adr-17 — the only other two ADRs that decision voids, both since pruned by a successor that names them (adr-25, adr-22), which is what leaves adr-6 alone — and observes that the unused deprecated status is the state it fits) so the disposition is a decision with evidence rather than an open question; the two brief re-pointings drop a reflexive attribution that had adr-29 reusing a model from itself; and adr-22, adr-26, and adr-32 gain one body clause each naming what their newly-declared supersedes handles retire, so the frontmatter and the prose say the same thing.

  • dcn-26080200000000052026-08-02

    2026-08-02 — iss-39 (review pass): four correctness repairs to record_schema, each found by mutating the rule rather than reading it. (1) The "no lifecycle state escapes" invariant was implemented for bucketed stores only — a FLAT store (the ADRs) declares no buckets, so the walk read its files and never looked at its directories, and a whole adrs/archive/ of records with mismatched ids and phantom successors was invisible to every check in the rule. A flat store declares zero buckets, so any subdirectory of it is undeclared by definition, and now says so. (2) The retirement escape hatch was self-attesting: retired was built from every record's supersedes before the resolution loop ran, so one record naming adr-9999 there made that id resolve in every other record's related_adrs — reopening the exact phantom-reference class the rule exists to close. It is now bounded by the store's allocation high-water mark (an id above it was never issued, so nothing can have pruned it) and the declaration itself is reported; supersedes also leaves recordRefFields, where it could never fail its own check and read as coverage it did not provide. (3) The shared frontmatter scanner is a same-line scanner, so a block sequence (supersedes: then indented - adr-12) read as empty — and an empty read here did not merely under-report, it made the bidirectional check assert that ANOTHER file omitted a link that file plainly carried. Other rules degrade to "field missing on this file"; this one degraded to a confident false claim about a different file, which is worse, so the block spelling is folded in at the one place the rule parses handles. Local to record_schema rather than in the shared scanner: the canonical scanner has many consumers whose keys are scalars, and widening it for one rule's list fields would change what every other rule reads. (4) A dot-directory (.obsidian, .vscode) tripped a blocker as an undeclared bucket; tooling state is not a lifecycle the record authored. Also disclosed rather than fixed: widening superseded_by to ^(itd|adr)- makes intent_lifecycle looser ALONE — it reads only the intent tree and cannot resolve an adr- target — so the CHANGELOG and the pattern's own comment now say the two rules are armed together and record_schema is what resolves a cross-store target. The surviving adr-6 prose citations are captured as iss-179 rather than papered over: adr-29 states in its own body that adr-6's decision stands and that adr-29 does not supersede it, so the supersession vocabulary cannot record it.

  • dcn-26080200000000042026-08-02

    2026-08-02 — iss-39: record-lint gains record_schema, the first rule that reasons ACROSS the record's stores (ADRs, intents, specs, the issue ledger) rather than inside one, and the superseded/ exemption narrows for the intent tree: both rules that read it (intent_lifecycle, intent_impact_valid) now run there too, while the spec-store rules (spec_lifecycle, spec_id_unique) still honour it as before and the cross-store record_schema never consulted it at all. Four invariants, one scan: a cross-reference field names a record the corpus has; a supersession is declared from BOTH sides; a filename and the id inside it agree; and every lifecycle directory is enumerated, so an undeclared bucket is a finding rather than a state no rule reads. Scope is deliberate on two axes. (1) Cross-references are checked in the machine-readable frontmatter fields (supersedes, related_adrs, related_intents, builds_on, blocked_by), not in bare prose: a frontmatter handle is a claim that the record exists and is a live input, whereas prose legitimately narrates ids that do not resolve ("itd-38's id was released, not reserved"; a test fixture's itd-9999; adr-29's account of what ADR-6 settled) — arming prose would have cost ten false positives against one true one, the same false-positive budget that scopes GL002. (2) A handle resolves either to a file or to a supersedes: declaration elsewhere, because the ADR lifecycle PRUNES a superseded record and keeps the trace in its successor — that is what distinguishes adr-4/adr-8/adr-14..18 (pruned, accounted for) from adr-6 (cited, never accounted for). The exemption narrowing is the root cause of the corpus defect it exposes: intent_lifecycle is a schema rule, but the superseded/ bucket exempted its own records from the one rule that checks a supersession is recorded, so itd-47 and itd-49 sat there for months with a prose blockquote and no superseded_by field. Being historical excuses a record from how it is WRITTEN, never from being well-formed. superseded_by also widens from ^itd-\d+ to ^(itd|adr)-\d+: an ADR that redecides the question an intent rested on retires that intent as surely as a successor intent does, and refusing to spell that forced those two records to say nothing at all. Corpus repairs in the same change: adr-6 is dropped from the two related_adrs lists and the two brief pages that cited it re-point at adr-29 (which records the two-stage redaction model and states in its own body that adr-6's decision stands — adr-29 does not supersede it, so claiming it does would have written a falsehood to clear a finding); adr-12 and adr-32 gain the bidirectional pair the ledger-location redecision always implied, adr-12's status moving to superseded and the index row with it; itd-47/itd-49 gain superseded_by: adr-22/adr-26 with kind_at_supersession, and those ADRs name them back; and the pre-existing one-way links itd-32→itd-31 and itd-31→itd-48 gain their reverse halves. CHANGELOG impact additive, matching iss-38's disposition on the same axis: the rule ships in the lint engine abcd docs lint runs, and any abcd-managed repo gains it by declaring its own record_stores.

  • dcn-26080200000000032026-08-02

    2026-08-02 — iss-38 (v0.5.0 item D): hand-maintained indexes are either DELETED or GATED, never corrected and left hand-kept, because a corrected list drifts again on the next commit and nobody notices the second time either (adr-5, derive don't store). The ledger named four stale indexes; three were real and one does not hold. (1) intents/README.md transcribed four lifecycle directories as ASCII trees and had fallen sixteen drafts, one promotion (itd-73, listed as a draft while living in planned/), two disciplines and two superseded intents behind, with a shipped/ section still calling the directory empty over thirteen shipped intents — deleted, because the enumeration carried nothing the directory does not carry better, and what a filesystem cannot state (the kind taxonomy, the lifecycle contract, the bundle history) stays. (2) commands/README.md (fourteen verbs named, eighteen files present) and (3) internal/README.md (core described as "identity/version and the read-only status snapshot" while its own later bullets described twenty packages, and adapter/scanner filed under planned seams although it ships with its own pattern set, redactor and tests) keep short, high-value enumerations — so those ship WITH the detector rather than as a promise to remember. The new index_drift rule holds a marked region (<!-- index: <id> -->) to the directory it enumerates in one of two modes: exact, where listing and directory must agree both ways, and absent, where every listed path must still be missing — the planned-seams shape, whose drift is a seam that shipped. Scoping is an explicit marker plus a configured entry pattern rather than a markdown-list parser: one generic rule, no bespoke parser per README, and unrelated prose beside a list cannot fire it. It fails closed three ways (region gone while the config entry remains; region parsing to zero entries; malformed spec), so half-deleting an index is a finding rather than a silent disarm. (4) The fourth instance — "the repo README Layout omits skills/ from the plugin surface" — was investigated and does NOT hold: there is no skills/ directory, abcd ships zero skills deliberately (the three workflows once shaped as skills became commands, closing iss-61; brief/05-internals/08-skills.md states it), so the Layout section is correct by omission and was left untouched. Inventing a skills/ reference to satisfy a finding would have written a falsehood into the record to close a ticket — the same disposition iss-37 reached on its one non-holding instance. CHANGELOG: an entry, unlike iss-34's test-only pass, and impact additive rather than internal — the rule lives in the shipped lint engine that abcd docs lint runs, so any abcd-managed repo gains it by declaring its own pairs in .abcd/docs-lint.json.

  • dcn-26080200000000022026-08-02

    2026-08-02 — iss-170: resolvePluginRoot now canonicalises the executable path with resolvePath (EvalSymlinks, falling back to filepath.Abs, then the original path, on error) before the ancestor walk, because os.Executable reports the path abcd was INVOKED through and ahoy install itself pins a PATH symlink at /usr/local/bin/abcd -> <plugin-root>/abcd — so the walk climbed the symlink's ancestors (/usr/local/bin, /usr/local, /usr — the loop's own guard excludes /, so it was never actually a candidate) and never saw hooks/, a permanent "plugin root not resolvable" gap on exactly the layout the installer writes, in a normal shell where neither ABCD_PLUGIN_ROOT nor CLAUDE_PLUGIN_ROOT is set (CLAUDE_PLUGIN_ROOT is set by the harness inside hook invocations, which is why every env-driven test — each of which sets it directly via t.Setenv — passed over the defect; this codebase has no independent evidence for whether any other context also sets it). The gap is platform-specific: os.Executable resolves through /proc/self/exe on Linux, already symlink-free, so the defect and this fix both bite only where the OS returns the invoked (unresolved) path — macOS's execve-argument implementation, per Go's os/executable_darwin.go. Reusing the existing resolvePath rather than calling filepath.EvalSymlinks inline keeps the fallback chain shared with the symlink-classification path; the Abs middle step is CWD-dependent in principle, but os.Executable returns an absolute path whenever it reports no error on both shipped platforms, so that step never fires here and no case that worked before can regress. Testing it required a seam: os.Executable is not overridable, so a package-level var osExecutable = os.Executable was added and the detector substitutes a fake returning the symlink path, with both env candidates blanked via t.Setenv so ONLY the fallback runs — watched fail (no plugin root) with the seam in place but the walk unresolved, and pass after.

  • dcn-26080200000000012026-08-02

    2026-08-02 — iss-34 (v0.5.0 item C8): the five untested refusal guards now carry detectors, and the audit that opened the round is worth keeping because the ledger's "zero coverage" claim was true for only three of the five. ML001's single-source branch was ALREADY covered by TestLintRejectsMalformed/external_missing_licence — forbidden page, blocker code, exit contract — so nothing was added there; padding a satisfied guard with a second test buys no detection and costs a reader's trust in the corpus. The symlink-dereference guard was covered on its REJECT half only (escape, denied target), which is the interesting general point: a guard whose job is to refuse SOME inputs and safely dereference the rest is only half-pinned by refusal tests, because dropping the dereference silently ships nothing rather than shipping something forbidden — a regression that reads as "stricter" and never trips a deny assertion. Both halves are now pinned, and the cycle guard turns out not to mislabel a rejection when removed but to hang the resolve outright. The three genuinely uncovered guards — the scripts runtime closure, the MQ001 quotation budget, and the ask --file-back write path — each gained the full shape the convention asks for: forbidden input presented literally, the specific reason code or error type asserted (not merely "an error"), and absence of side effects proved, which for file-back means a byte-level snapshot of the whole store taken before and after each refusal rather than a spot check on one filename. Two design choices are reusable: the scripts test drives the shipped ClosureFn seam and adds a no-closure polarity control, so the exclusions are demonstrably the gate's doing rather than an unrelated default-deny; and each case was verified by disabling its guard and watching the test fail, which for already-shipped guards is the only available form of "watched fail before". No guard was found broken, so the increment is test-only, go.mod is untouched, and there is no CHANGELOG entry — the repo's definition of done ties an entry to a user-facing change, and coverage alone is not one. The entry's promotion path — a pairing lint between declared invariants and named tests — is deliberately NOT built here; it is a convention increment, not part of the coverage corpus this item scoped.

  • dcn-26080100000000152026-08-01

    2026-08-01 — iss-30 (v0.5.0 item C7), CORRECTION to the entry immediately above, and two production fixes: that entry closed the item as "test-only" and stated that "no production behaviour was found to diverge from its own documentation, which is why this increment adds no fix". That claim was false and is retracted here. Two independent fresh pre-PR reviews (correctness and security) each reproduced a real defect in internal/core/memory/yaml.go, both now fixed detector-first on the same branch. (1) collectBlockScalar set the block's indent from the first non-blank line WITHOUT requiring it to exceed the indent of the key: | line that opened the block. Since the function is only ever reached for a top-level key (parseYAMLLines refuses any other indent), a | with no indented body took the next COLUMN-0 line as content and went on consuming every line after it: the remaining keys — domain, slug, source — were absorbed into the value and no error was raised. An unindented first line now ends an EMPTY block and is left unconsumed for the top-level parse. (2) dumpString triggered its quoting on \n and \t but not \r, so a bare carriage return was emitted RAW into the YAML region, while parseFrontmatter normalises \r to \n before splitting lines — the writer and the reader disagreed about what a line is. A value carrying \r--- therefore re-read as an early frontmatter terminator and every key below it fell into the page body; a distiller-supplied recall string was enough to make Ingest report success while writing a page that reads back with an EMPTY source block and no source hashes, which is exactly the state the reconcile/repair path treats as an orphan. \r now joins the quote trigger; doubleQuote already escaped it correctly, so only the trigger was missing. The lesson worth keeping is about detector siting rather than either bug: the earlier increment's \r cases DID pass, because they round-tripped through parseScalar/parseFlowMap directly and never crossed the dumpFrontmatter → joinFileFrontmatter → parseFrontmatter boundary where the invariant is actually stated (yaml.go:11-16) and where the defect lived. A round-trip test that does not use the real entry points tests the parser's internals, not the invariant; the new cases go through the file boundary and, for the CR case, through Ingest itself. Both detectors were watched fail before the fix and pass after. Consequently the increment is no longer test-only and DOES carry a CHANGELOG entry under Fixed — the second judgement call in the entry above ("no CHANGELOG entry: nothing user-facing changed") lapses with the claim it rested on.

  • dcn-26080100000000142026-08-01

    2026-08-01 — iss-30 (v0.5.0 item C7), FINAL increment, test-only: the memory-ingest boundary's last four acceptance instances were absences, not defects, and are now drained behind detectors in internal/core/memory/ingest_boundary_test.go and internal/core/memory/yaml_boundary_test.go. The no-new-dep STOP the entry flagged for PDF extraction never fired, and the reason is the design rather than luck: PDFExtractor is a plain func([]byte) (string, error) the caller supplies, so a fake extractor covers the nil / error / empty-text / success matrix on the fetched path and both local sniffs (.pdf extension, %PDF- magic) without a parser ever entering go.mod — the nil case (no parser installed) is itself one of the behaviours under test. Likewise Fetcher carries the whole URL-ingest success path with no network: the fetcher is asked for the REQUESTED url, the FINAL url after redirects is what reaches the citation and the registry origin, the response headers reach licence detection (an HTTP License: header has no local-path equivalent), and --keep-original takes its extension from the final url's PATH, so a query string or fragment cannot leak into it. Two judgement calls worth recording. (1) On the parser's block-scalar limit: only the literal | opens a block — >, |- and |+ are read as ordinary scalars — and rather than treat that as a defect to fix, the increment pins the property that makes it safe, which is that an unsupported indicator fails LOUDLY (the indented lines beneath it are refused as top-level content) rather than silently swallowing or dropping them. Widening the parser was rejected as scope the memory store has no shape asking for; the dumper never emits a block scalar at all. (2) No CHANGELOG entry: nothing user-facing changed, and the repo's own definition of done ties an entry to a user-facing change — the precedent is the behaviour-preserving internal/urlguard extraction, which carried none either. Every case was mutation-checked (sixteen targeted reversions of shipped behaviour, each turning at least one new case red), and no production behaviour was found to diverge from its own documentation, which is why this increment adds no fix.

  • dcn-26080100000000132026-08-01

    2026-08-01 — itd-105 / spc-21, MERGE-GATE fix (sixth round, test-hardening only): a fresh merge-gate security reviewer reproduced a TWO-HOP bypass of the same fetch-origin allowlist test, and this entry also corrects the claim two entries above. That entry said the allowlist "taints any name whose own assignment line references itself", which is exactly what it did — and exactly why it closed only the ONE-hop case, not "the self-referential bypass class" the fix commit's message implied. Two names that reference each OTHER (repo_url="${GH_MIRROR:-$gh_default}" then GH_MIRROR="$repo_url") leave neither line self-referential, so the per-line check passed the planted script green while GH_MIRROR=https://attacker.invalid/x genuinely redirected the fetch — the reviewer verified that against the real script logic with a curl-argv-recording shim. TestBootstrapFetchOriginsAreConstants's allowlist is now computed by bootstrapSafeNames, which propagates taint to a FIXPOINT over the assignment graph instead of scanning each line once: a name is script-local only if every assignment of it draws on constants, on CLAUDE_PLUGIN_ROOT, or on names already safe AT THAT POINT in the file, and the pass repeats until no name is newly tainted. What that closes is chains of self- and mutual reference of ANY length — one hop, the reviewer's two, and the three-hop laundering variant are all detector cases now, alongside the reproduction spliced into the committed script's own bytes. What it does NOT claim is completeness: it is a fixpoint over $NAME/${NAME} references in name= assignments, not a shell parser, so a value laundered through a construct that scan does not model (an eval, an eval-time expansion, a name assembled at runtime) is outside what it proves. The reference scan deliberately stays order-INSENSITIVE on the usage side, because a shell function body runs long after the line defining it and "used before assigned" is not a defect there. Second finding in the same pass: the curl scan filtered lines on the substring curl -, so any invocation whose first argument is not a flag (curl "$url" -o /dev/null) was skipped ENTIRELY — it could be missing -q or the transport pin and never be looked at, while the call count stayed consistent with itself because the scan was its own counter. curl is matched as a command WORD now (line head, after a shell operator, command substitution, path prefix, or keyword), with mentions — command -v curl, the refusal message's prose, .curlrc — held out as non-invocations by their own detector cases. Detector-first on both, each pre-fix behaviour restored in place and watched to fail: the two-hop, three-hop and planted-script cases reported nothing under the old taint rule, and five curl shapes (flags after the URL, no flags at all, an absolute path, after if, downstream of a pipe) were invisible to the old substring filter. hooks/bootstrap.sh is UNCHANGED — the reviewer's finding is that the regression guard was weaker than its own comment claimed, not that the shipped bytes have a live seam. Left alone deliberately, out of scope for this pass and unfixed: SSLKEYLOGFILE/QLOGDIR are not scrubbed, the lock and temp mkdirs take the ambient umask, and every tool the script runs is PATH-resolved (an actor who can write the PATH can replace curl outright, which no shell script closes).

  • dcn-26080100000000122026-08-01

    2026-08-01 — itd-105 / spc-21, coordination note: two independently-running instances of the v0.5.0 loop each reviewed PR #184 at its merge gate concurrently, found different real findings (a self-referential allowlist bypass; a curl config-surface bypass), and pushed both fix commits to v050/itd-105 minutes apart — rebased together here rather than either overwriting the other. Same collision class the state issue's round-9 comment already disclosed for v050/iss-159; recorded again per that precedent, no new action taken beyond the rebase.

  • dcn-26080100000000112026-08-01

    2026-08-01 — itd-105 / spc-21, FIFTH round (concurrent session B, landed alongside the entry above): a fresh security review returned BLOCK on a bypass it reproduced, and a fresh correctness review returned MERGE with minor findings; both are closed here on the same branch. (1) BLOCKER — none of hooks/bootstrap.sh's four curl calls passed -q, so curl loaded its own configuration surface: $CURL_HOME/.curlrc (curl >= 7.73, falling back to $HOME/.curlrc), where a single connect-to or resolve line re-points the connection while the URL on the command line still literally reads https://github.com/…. The transport pin --proto '=https' --proto-redir '=https' therefore still HELD and proved nothing, and because the binary and the checksums.txt that verifies it travel the same route, the SHA-256 check was vacuous — the poisoned config supplied both. Reproduced end to end before the fix: a .curlrc carrying connect-to plus its own cacert diverted all five requests to a second local server and installed the forged binary at the guard path, where it would run unattended as the Bash shell guard on every tool call. Fixed by passing -q as the FIRST argument of every call (curl honours it in no other position) and by removing, before any fetch, the other names curl reads without being told to: HTTPS_PROXY https_proxy HTTP_PROXY http_proxy ALL_PROXY all_proxy CURL_HOME and CURL_CA_BUNDLE SSL_CERT_FILE SSL_CERT_DIR. ACCEPTED COST, deliberately: a machine that can only reach the network through a proxy no longer bootstraps automatically — refuse() already names the manual-install and build-from-source ways out, and a proxy plus an attacker-chosen CA is precisely the pairing that makes the redirection succeed on TLS, so the seam is not worth keeping for the convenience. (2) MAJOR — the suite could not have caught (1): it only exercised the removed ABCD_BOOTSTRAP_* script variables, never curl's own config surface. TestBootstrapIgnoresCurlsOwnConfigSurface now runs the fixture-pointed copy with a poisoned .curlrc under both CURL_HOME and HOME, and asserts the published bytes are installed and the forger is contacted zero times; it was watched failing against the pre-fix script in exactly the shape described above. TestBootstrapFetchOriginsAreConstants gained the structural half — every curl - line must carry curl -q as well as the literal transport pin, and both scrub lines must be present exactly once — verified by deleting a -q and shortening the scrub list and watching it fail. The one test-side concession is that bootstrapFixtureScript neutralises the CA-scrub line in its throwaway COPY, because CURL_CA_BUNDLE is the only way a real curl trusts the self-signed local fixture; that widens what curl will ACCEPT and can never name a different server, the CURL_HOME/proxy scrub stays intact in the copy (which is what makes the poisoned-config case meaningful), and the shipped bytes are held by the structural test. (3) MINOR — the .binary-meta install had no regular-file guard, so a directory at that path swallowed the record as .binary-meta/binary-meta (the same mv -f hazard $binary already refuses) while the success notice claimed provenance had been recorded. The install itself is genuine there, so this REPORTS rather than refuses: the notice now says the path exists and is not a regular file, and TestBootstrapReportsAnObstructedBinaryMeta proves the record is never moved into the obstruction. NOT FIXED, deliberately: the stale-lock double-break race (already disclosed and accepted above), the "120 bytes" comment wording and the checksums.txt text-vs-binary-mode parsing convention (cosmetic, not worth the churn at a merge gate), and the hook-ordering assumption (already disclosed, no code change).

  • dcn-26080100000000102026-08-01

    2026-08-01 — itd-105 / spc-21, MERGE-GATE fix (concurrent session A): a fresh merge-gate security reviewer found a real gap in that same allowlist test, not in the shipped script. TestBootstrapFetchOriginsAreConstants subtracted any name the script "assigns to itself" before checking it against the allowlist, so a SELF-referential seam (mirror="${mirror:-}", then [ -n "$mirror" ] && repo_url="$mirror") read as script-local and the test passed green while a curl shim recorded a fetch to an attacker-named host. Reproduced by planting exactly that shape against the committed script before fixing. The allowlist now taints any name whose own assignment line references itself, on every line where it is assigned, so neither the self-reference nor any later use of the name reads as safe — verified this catches the planted bypass and still passes on the real script. One more merge-gate MINOR landed in the same pass: mkdir -p "$tmp" (the temp-download directory) succeeds on a directory that reappears, symlinked, in the window since the preceding rm -rf; plain mkdir (no -p) turns that same-name race into a refusal instead of a curl write through a planted symlink. Both merge-gate reviews (fresh, independent, full-PR-diff) had already returned MERGE before these were found — landed anyway per the merge gate's "fix everything raised" step rather than waiting for a fifth review round, since both are narrow, each has a watched-fail-then-pass test, and neither changes the shipped script's externally observable behaviour except the second (a same-name TOCTOU race becoming a loud refusal, strictly safer).

  • dcn-26080100000000092026-08-01

    2026-08-01 — itd-105 / spc-21, FOURTH round: two fresh independent reviews of the seam-removal fix pass above (one security, one correctness) both returned MERGE, each naming a short list of cheap items rather than a blocker — three rounds of BLOCK was not treated as licence to manufacture a fourth by inflating what these were. All were landed on this branch directly rather than deferred, since none needed a fresh review cycle to verify. (1) The structural regression test guarding the seam removal, TestBootstrapFetchOriginsAreConstants, was a DENYLIST — it scanned for ${, $ABCD, $HTTP, $CURL — so a bypass renamed to any other variable ($GH_MIRROR was the reviewer's example) would satisfy it while still redirecting a fetch; reproduced by planting exactly that shape against the committed script and watching the old test pass regardless. Replaced with an ALLOWLIST: every $NAME/${NAME} reference in the script, after subtracting names the script assigns to itself, must be CLAUDE_PLUGIN_ROOT and nothing else — verified this catches the planted $GH_MIRROR bypass and passes on the real script. (2) safe()'s tr -d range stripped ESC and other C0 controls but not CR (\015) or DEL (\177); a bare CR overprints from column zero, the exact attack class internal/termsafe's own doc comment names, and DEL is the same family. Range widened to \000-\010\013-\037\177 (keeps only tab and newline, as before); the existing control-character test now plants CR and DEL alongside ESC in the same specimen and watches both survive the pre-fix range before the widened one strips them. (3) mv -f onto an existing DIRECTORY at $binary moves the downloaded file INTO the directory rather than replacing it — reproduced: the script reported success, exited 2, wrote a truthful-looking .binary-meta, and the binary landed at $binary/abcd-<os>-<arch> while the hooks stayed broken forever, since the fast path's [ -f ] check never becomes true. A guard now refuses before any download when $binary exists and is not a regular file; the existing directory-fast-path test was tightened to assert the actual refusal (it had previously accepted a substring of the SUCCESS message as if it proved a refusal happened, which is why the bug had a green test). (4) plugin_root_basename's control-character stripping and 120-byte cap (added in the prior round) had no detector: deleting the sanitisation left the full suite green, and a directory literally named aa\nrelease_sha=<40 hex> forged a second release_sha line that skew.go's last-wins map parsing would have preferred over the genuine one. Two new cases prove the fix is load-bearing: an embedded-newline specimen asserting .binary-meta holds exactly its six declared lines and the genuine value survives, and an oversized-basename specimen asserting the recorded value is exactly 120 bytes. Noted, not landed: the structural allowlist test is still a snapshot of the shape the script must hold, not a guarantee against every conceivable future evasion of that shape — it is the cheapest check that catches the two concrete bypasses two independent reviewers actually constructed, not a formal proof.

  • dcn-26080100000000082026-08-01

    2026-08-01 — itd-105 / spc-21, THIRD-round fix pass: the environment-driven URL seam in hooks/bootstrap.sh is REMOVED rather than patched a third time. Two independent adversarial reviews had already returned BLOCK on two successive allowlist attempts at the same defect — first a bare ${VAR:-default} read, then a case http://127.0.0.1:*|http://localhost:* glob — and both were defeated empirically by fresh reviewers: URL userinfo (http://127.0.0.1:1@attacker.example, where everything before the @ is a username and the real host is the attacker's) walked straight through the glob, and the override path also cleared the --proto '=https' --proto-redir '=https' pin, so a redirect could downgrade the transport on top. The pattern was the finding, not the instances: an allowlist over URL syntax is a parser-differential surface, and the thing it guards is a code-execution primitive — the binary AND the checksums.txt that verifies it come from the same origin, so whoever names the origin supplies both the payload and the manifest that "verifies" it, and what is installed then runs unattended as the Bash shell guard on every tool call. So ABCD_BOOTSTRAP_BASE_URL and ABCD_BOOTSTRAP_API_URL are gone; grep ABCD_BOOTSTRAP hooks/bootstrap.sh now returns nothing, the script's only environment read at all is ${CLAUDE_PLUGIN_ROOT:-} (a filesystem destination, never a fetch origin), and the two transport flags are literal on all four curl calls with no variable to clear. This supersedes claim (1) of the fix-pass entry above and the ABCD_BOOTSTRAP_BASE_URL mention in spc-21's Testing section, which named a seam that no longer exists. THE TEST SEAM MOVED TO THE TEST SIDE. internal/surface/cli/bootstrap_test.go reads the committed script's bytes, replaces the two quoted origin literals with an httptest base, writes the result to a temp file, chmod +xes it and execs THAT — the shipped bytes are what runs on a user's machine, with no test-only branch anywhere in them. Three properties make the copy trustworthy rather than a fixture that hides the bug (a failure this item already shipped once, when a friendlier fixture concealed that the release tag was always unknown in production): the match is the QUOTED, complete assignment value, so a longer origin cannot be prefix-rewritten into a mangled URL; each literal must appear exactly once before and zero times after, or the helper t.Fatals naming the drift; and the happy path additionally asserts the fixture served at least one request, so a substitution that silently missed cannot pass by testing the real GitHub. The fixture speaks TLS (httptest.NewTLSServer) because the pin is unconditional, and trust is supplied through CURL_CA_BUNDLE/SSL_CERT_FILE — curl's own variables, which only ever ADD an issuer curl will accept and can never name a different server, so they are not the class of seam that was removed. Reviewer-facing residue, stated rather than implied: an actor who already controls the hook process's environment can still influence curl through curl's OWN variables (a proxy setting, a CA bundle), which is true of every curl invocation on the machine and is not something a shell script can close — such an actor can also replace curl on PATH; what is closed is the seam this script itself honoured. Detector-first throughout, each fix reverted in place and watched to fail: the reverted script reproduces the round-2 bypass verbatim (recorded fetch to http://127.0.0.1:1@abcd-bootstrap.invalid/releases/latest, no HTTPS pin), and against a live attacker-controlled release server on loopback the pre-fix script took four requests from it and installed its payload while the fixed script took zero and installed the genuine ELF release. Four smaller items in the same pass. (1) plugin_sha's forty-hex gate rests on itd-105's unverified warrant that the harness names each plugin cache directory for its source commit; if that stops holding, every install records unknown, the skew notice goes silent permanently, and nothing anywhere says why — so the RAW basename is now recorded as plugin_root_basename beside the gated field, never compared and never rendered, purely so the failure is diagnosable from the file rather than only from a comment. Control characters are stripped from it and it is capped at 120 characters, since a directory name may contain a newline (forging a key=value line) or enough bytes to push .binary-meta past the guarded read and silence the notice by a second route. (2) mkdir "$lock" failing was indistinguishable from losing the race and took the same silent exit 0; it now refuses loudly when no lock DIRECTORY exists afterwards, because that case is permanent and repeats every session while the race case is transient and correctly quiet. (3) Both message sinks strip control characters from the values they echo, and the skew notice sanitises release_tag through termsafe like every other untrusted rendered string in this repo — the tag is read out of an HTTP redirect and is the one value in that line with no shape check. (4) binary_sha256 is recorded and re-checked by nothing; the comment now says so plainly instead of implying an automatic check, because the fast path's whole contract is one file test and adding a SHA-256 recomputation to every session start would trade the AC away for a check nothing yet consumes. Two known asymmetries re-confirmed as disclosed rather than accidental: only the two binary-backed SessionStart entries carry the inline existence wrapper — UserPromptSubmit, PreCompact and SessionEnd still invoke the binary bare, which is itd-105's "every hook reports, for now" testing posture and not an oversight; and the unsupported-platform notice's move to exit 2 means it now repeats EVERY session for as long as the platform is unsupported, which is the accepted cost of that same posture (the one-notice-per-session aspiration is iss-168's). Not fixed, noted: the orphan sweep could still delete a live racer's temp directory in the already-accepted >10-minute stale-lock race, and the transcript scanner's local_username hard-fails on this script are the same pre-existing false-positive class already firing on main for README.md.

  • dcn-26080100000000072026-08-01

    2026-08-01 — itd-105 / spc-21, hook-ordering assumption DISCLOSED and defensively mitigated rather than verified. spc-21's Approach asserts "ordering within one event's hook list is preserved by the harness, so the binary-backed session hooks run after the bootstrap in the same event". That is an assumption about the harness, and nothing in this repository verifies it; if it is false, a fresh install's first session runs abcd hook prompt-router-reset and abcd hook session-start before any binary exists, and the intent's AC ("never a raw shell 'No such file or directory'") is missed by the two commands the bootstrap is supposed to protect. A PATH fallback is forbidden by the intent's Decisions and is NOT added. Instead both commands gain an inline existence check in hooks/hooks.json — the same shape as the PreToolUse guard entry's existing inline wrapper, which turns a bad exit code into a clean message — so if the assumption turns out to be false the failure is at least a plain-language message and a non-blocking exit 2 rather than a raw shell error, with no fallback binary resolution anywhere. This mitigates the SYMPTOM; the assumption itself still wants verifying against the real harness, and the maintainer should treat it as open. In the same file the bootstrap entry gains "timeout": 240 (seconds): the three curl budgets plus the tag resolution total 180s worst case, which the harness's 60s default would have killed mid-run — which is precisely how the trap bug above and an orphaned temp dir would both have been reached in production. Deferred, deliberately, and bounded: two racers can both proceed when one breaks the other's ten-minute-stale lock, which last-write-wins resolves into a verified binary either way; and the trap is installed just after the lock is taken, leaving a signal window bounded by that same stale-lock recovery. Both are cheaper to state than to fix, and neither can install an unverified binary.

  • dcn-26080100000000062026-08-01

    2026-08-01 — itd-105 / spc-21, FIX pass after two fresh adversarial pre-PR reviews (one security, one correctness) that converged independently on the same top items. Detector-first throughout; each behavioural fix has a test watched failing before it and passing after. Four claims of the entry above are superseded. (1) ABCD_BOOTSTRAP_BASE_URL / ABCD_BOOTSTRAP_API_URL were bare ${VAR:-default} reads, which made them a code-execution primitive rather than a test seam: the binary AND the checksums.txt that verifies it are fetched from the same base, so whoever set the variable supplied both the payload and the manifest that "verified" it — verification became vacuous — and the installed binary is then run unattended as the Bash shell guard on every tool call. Both are now honoured for http://127.0.0.1:* / http://localhost:* only and REFUSED otherwise (refusing beats ignoring: a silently dropped override reads as a passing test), and the production calls pin --proto =https --proto-redir =https so no redirect can downgrade the transport or point at file://. (2) release_tag was scraped from %{url_effective} after -L on the asset download, which was verified against the real repository to land on release-assets.githubusercontent.com/<numbers>?<signed query> — no /releases/download/<tag>/ segment exists there, so in production the tag was ALWAYS unknown, release_sha was always unknown behind it, and the entire version-skew notice (an intent AC) could never fire. The tag is now resolved BEFORE any download, from %{redirect_url} on an unfollowed request to /releases/latest (302 -> /releases/tag/<tag>), and both the asset and checksums.txt are then fetched from the TAG-PINNED path — which also closes the narrower hole that a release cut between the two downloads would have checked a new manifest against an old binary. The fixture was the reason this passed review-blind: it redirected to a conveniently tag-shaped URL, so it now mimics the real CDN shape and serves checksums.txt only from the pinned path. Consequence accepted: an unresolvable tag is now a refusal rather than a silent unknown, because the alternative is an unpinned pair the checksum step cannot honestly verify. (3) The bootstrap's two messages for a person — the unsupported-platform statement and the one-time abcd ahoy install suggestion — went to stdout with exit 0, which on SessionStart means model context and nothing the human ever sees; both now go to stderr with exit 2, matching cli.go's existing "non-zero so SessionStart shows it; SessionStart never blocks" convention. This deviates from spc-21's Approach step 2, which specified exit 0 for the unsupported platform: the spec's reason (a reported condition, not a hook fault to retry) is preserved — nothing is changed, nothing is retried — but exit 0 also meant the statement was unreadable by its only audience. (4) trap cleanup EXIT HUP INT TERM where cleanup returns does not terminate on a signal; POSIX RESUMES the script, verified empirically here, so a SIGTERM mid-run deleted the temp dir and then carried on to report a checksum mismatch that never happened. Now trap cleanup EXIT plus trap 'cleanup; exit 1' HUP INT TERM, cleanup being idempotent. Smaller, same pass: .binary-meta is written through the temp dir and renamed in (a crash mid-write otherwise left a truncated release_sha that still parsed) and carries the verified binary_sha256 so a later check can tell the binary that was verified from one that replaced it; resolvedSHA now requires forty lowercase hex rather than merely "not the literal unknown"; the skew notice is non-directional, since comparing two commits establishes that they differ and never which is ahead; the fast path requires a regular file, [ -x ] alone being true of a directory too; a run holding the lock sweeps .bootstrap.tmp.* orphaned by a SIGKILL (which runs no trap); hooks/*.sh is pinned eol=lf, a CRLF checkout of this one breaking the script that repairs the hooks rather than merely a hook.

  • dcn-26080100000000052026-08-01

    2026-08-01 — itd-105 / spc-21 implementation: the plugin provisions its own binary from a committed POSIX-sh hooks/bootstrap.sh wired as the FIRST SessionStart hook, per spc-21's Decisions (fast path on an executable binary, darwin/linux × amd64/arm64 gate, atomic mkdir lock with a 10-minute stale break, same-origin SHA-256 against the release checksums.txt, atomic rename install, .binary-meta provenance). Three judgment calls a reviewer should see. (1) The script's TEST-ONLY overrides are TWO env vars, not one: ABCD_BOOTSTRAP_BASE_URL (download base, as spc-21 names) plus ABCD_BOOTSTRAP_API_URL (release-commit lookup base) — the release-sha resolution hits a different URL shape than the asset download, and folding both behind one variable would have made the fixture server lie about which endpoint was called. Both mirror ABCD_BIN_TARGET's pattern. (2) release_sha is read from the commits API (/commits/<tag>), NOT the releases API's target_commitish: this repo tags annotated (git tag -a) and creates the release from an existing tag, so target_commitish is the default branch name rather than a commit — a value that would have made the skew notice compare a branch name against a SHA. A value that is not 40 hex is recorded as unknown and renders nothing. (3) spc-21's CI-smoke line ("the existing smoke job additionally runs sh hooks/bootstrap.sh against a fixture server on both OS runners") is satisfied WITHOUT touching workflow YAML: the script-driving test lives in internal/surface/cli/bootstrap_test.go, which go test ./... already runs on both legs of ci.yml's ubuntu+macos check matrix, and it shells out to the committed script against an httptest fixture exactly as the AC describes. A bespoke workflow step would have duplicated that coverage while adding background-process management to CI. Rejected: a PATH fallback in the hook commands (spc-21 forbids it); signature verification (out of scope, same-origin checksums are the accepted bar); guessing plugin_sha from git rev-parse when the plugin root is not a commit-stamped cache directory (the meta file never guesses).

  • dcn-26080100000000042026-08-01

    2026-08-01 — guard batch (iss-159/144/148), REVERT of the backtick sub-part after a THIRD adversarial round; the other three sub-parts stand. Following backtick command substitution went in, then grew a frame/stack mechanism intended to hold two properties at once — a substitution's content checked as its OWN segment (so a hazard hidden inside one is matched) while the ENCLOSING command's tokens, chain index and command position survived the boundary. Three rounds, three fresh independent reviewers, three BLOCKER findings, all in that mechanism rather than in one instance of it: (1) a substitution before trailing flags truncated the enclosing segment, so rm + substitution + -rf * went block to allow; (2) the frame fix for (1) renumbered the enclosing command's chain when a newline fell inside a substitution, defeating every after_cd entry (cd scratch && rm -rf $(\nfind . -name x\n)); and (3), the one that decided it, a substitution in LEADING command position left a bare $ as the enclosing command's argv[0], so commandOf returned "$" and NO entry could match — that is not a hole in rm-rf-after-cd-chain, it is a hole in the registry, reachable by prefixing any hazard with $(true). Two more in the same round: a bare ( nested inside $( … ) mis-popped the frame and re-opened (1) in a narrower shape, and an unterminated backtick failed OPEN. DECISION: revert rather than patch a fourth time inside one round. A mechanism that has produced a security-relevant regression on every attempt is not converging, and each fix has been strictly worse than the last in blast radius — the third defeats the entire registry. internal/core/guard/tokenize.go is restored byte-for-byte to main: no backtick handling at all (literal text), $( … ) exactly as it was, and the four guard.json fixtures the frame mechanism added removed with it. The two claims of the entry above are therefore WITHDRAWN, not superseded: backtick substitution does NOT reach command position, and the enclosing command does NOT survive a substitution. The literal ledger ask ("a backtick command substitution is not followed, while the dollar-paren form is") asked for PARITY with $( … ) as it behaves today, and parity is what leaving both forms untouched delivers — the gap is disclosed again as a stated v1 limit on all four coverage surfaces (brief, plugin command, CLI long help + generated reference, package map), which is the honest form of it. Recorded rather than quietly carried: $( … ) on main already loses the flags written AFTER a substitution — rm $(true) -rf * does not read as a recursive force delete — a pre-existing gap this round's review process surfaced and did not introduce, undisclosed before it and undisclosed still, because closing it is the same design problem as following a backtick and the two should land together or not at all. iss-148 is re-scoped IN PLACE back to open on that one sub-part (the iss-96 precedent: a capture resolve would have to state a resolution for scope that is not settled), with the three shipped sub-parts and their commits named in the entry; iss-144 and iss-159 are untouched and stay resolved, neither being implicated in any review finding. Deferred as its own future work, and explicitly NOT a patch to the reverted code: a substitution model that follows the payload AND preserves the enclosing command across the boundary, which needs the tokenizer to carry a command-position stack rather than a segment flush — the reason three attempts to bolt it onto the flush all leaked.

  • dcn-26080100000000032026-08-01

    2026-08-01 — guard batch (iss-159/144/148), FIX pass after two fresh adversarial reviews returned BLOCK (security) and FIX FIRST (correctness). Detector-first throughout: each fix has a test watched failing before it and passing after. Two claims in the entry above are superseded by it. First, "backtick substitution reaches command position through the same segment flush the grouping parens already gave $( … ) by accident" — the flush was the bug, not the mechanism. flushSegment permanently ENDS the enclosing command's segment, so every flag and operand written after a substitution closed started a new, unrelated command: cd scratch && rm + a backticked substitution + -rf * went from block on main to allow on this branch, a regression this branch introduced, and the identical hole already existed for $( … ) on main (rm $(true) -rf *). Both are fixed together rather than one fixed and one documented, because the mechanism to fix them is the same: a substitution pushes a FRAME that parks the enclosing tokens, accumulates its own content, flushes that as its own segments (a hazard inside a substitution is still matched — the point of the original fix), and restores the enclosing tokens so the segment resumes. Segments come back in SOURCE order rather than at the close boundary, which is what keeps precededByCD reading a cd written before a substitution as preceding it. A bare ( deliberately keeps the old flush: it is a subshell group, not a substitution inside a command, and it genuinely ends the token run before it — f() { rm -rf *; } would otherwise glue the body onto the function's name and lose the rm from command position. Imbalance degrades rather than errors (a close with no open falls back to the plain flush; an unterminated span is unwound at end of input rather than dropped, since a hazard inside it still executes), consistent with the file's existing philosophy that only an unterminated quote or heredoc — which changes what the REST of the input means — is ErrUnparsableCommand; a real shell rejects unbalanced parens itself, and this guard's job is to refuse to misparse into an allow, not to validate shell grammar. Second, "an api path written as a fully-qualified URL is NOT matched (a stated limit)" — it is matched now. gh passes an absolute URL through to the API unchanged, so the URL form was a real bypass of a real repository deletion, and documenting it was the wrong end: an operand is normalised to its path (scheme/host, query, fragment dropped) before the depth check, which only ever shortens, so the depth limit that keeps deeper work allowed is untouched. The host is deliberately NOT inspected — deciding which hostnames are the real API is a lookalike-domain problem this guard cannot settle, and normalising every authority away can only make the check see a path it would otherwise have missed. What is left is narrower and now disclosed in all four surfaces rather than in a Go comment and a test: a host that MOUNTS the API under a prefix (GitHub Enterprise Server's /api/v3/) is not seen, because matching a root segment wherever it appeared would falsely refuse DELETE /teams/{id}/repos/{owner}/{repo}, which removes a repository from a team and destroys nothing. Third item, no supersession: Validate rejected a dashed subcommand/subcommand2 but not the two operand fields this branch added, so "arg_prefixes": ["-f"] and an arg_paths root carrying a slash both loaded clean and could never fire — the "looks armed, never fires" class the validator exists to catch. Both are load-time rejections now, with the well-formed shapes pinned as accepted so the checks cannot quietly take the fields out of use.

  • dcn-26080100000000022026-08-01

    2026-08-01 — guard round (iss-148, iss-159, iss-144): the matcher's wrapper walk now steps over a wrapper's OWN arguments rather than its name alone, off two explicit tables — the flags each wrapper documents as taking a value, and the mandatory operand no flag stepping can reach (timeout [OPTIONS] DURATION COMMAND..., where timeout 30 rm -rf / read as a command called 30). That was the sharpest of the three items and the reason to take it first: sudo -u bob <hazard> read -u as the command name, so one extra token turned an entry the registry DOES describe into an allow, and a guard that has stopped refusing looks identical to one with nothing to refuse. The complementary miss is deliberate and now stated rather than implied — a value flag the table does not name (a bundled sudo -Hu bob) is not stepped over, and a miss is a non-match, never a false block. xargs, timeout and exec joined the wrapper set. Backtick substitution reaches command position through the same segment flush the grouping parens already gave $( … ) by accident, scoped to parity with today's behaviour (unquoted only) rather than POSIX completeness, so the two spellings of one substitution stop disagreeing. Registry content took four additive Pattern fields, each optional and per-repo overridable like the rest: subcommand2 for a two-level grammar (gh repo list and gh repo delete share their first level and only one is a hazard), flag_values for a flag's SETTING rather than its presence (presence alone would force a choice between missing -X DELETE and refusing -X GET; the value is compared without regard to case, since a constraint a change of case walks past is not one), arg_paths for a root segment AND an exact depth (the depth is the entry's scope: repos/{owner}/{repo} IS the repository, while DELETE on a branch ref under it stays ordinary work), and arg_prefixes for a hazard carried by an operand with no flag to look at (git push origin +main:main). The empty form of each is a load-time rejection, because an empty flag group defangs and an empty prefix over-blocks, and both are invisible in the file. Two behaviours are pinned as tests rather than left to be rediscovered: an api path written as a fully-qualified URL is NOT matched (a stated limit, the family of the payload gap), and --help is not an exemption anywhere in this registry — exempting it would mean teaching every entry which of its flags mean 'do nothing', and a guard that reasons about intent can be argued out of refusing. iss-144 needed no code at all: its incident shape was already known-bad fixture #1 and the incident capture already known-good #1, so the only change was adding the three-step form it actually occurred in (mkdir → cd → rm -rf *) to the corpus, making the resolve verifiable rather than asserted. Residual and deliberately not acted on: a cd in one tool call and an rm -rf * in the next is still an allow, since the tokenizer never sees two invocations as one candidate — a harness-level concern, not a registry one.

  • dcn-26080100000000012026-08-01

    2026-08-01 — iss-96 (item A6), a VERIFICATION milestone rather than an implementation: the transcript scanner's tracked coverage gaps re-checked against the network-identifier set A2 folded into DefaultPatterns, and the residue re-scoped in place. Two findings, both empirical rather than inspected. (1) A2 DID reach this path — every scanner consumer inherits the network set, so a non-reserved address or a LAN/device hostname in a captured transcript is now a finding (all five kinds — net:ipv4, net:ipv6, net:mac, net:lan_hostname, net:device_hostname — exercised on the transcript path itself in the same corpus, not inferred from their presence in the pattern set, and a flagged private address asserted REDACTED in the stored record at the store boundary); that class is therefore newly covered on this path since iss-96 was captured — it was never part of the entry's residue, which names unanchored secrets and home paths only, so this is coverage the re-check ESTABLISHES rather than a gap it closes. (2) The classes iss-96 actually names — a 40-character secret-key value with no prefix, a bare password, a prefix-less API token, and now a genuinely high-entropy 40-character value — still produce ZERO findings at the transcript path's own entry point, with or without a password:, api_key = or Authorization: Bearer key name beside them, because the TOKEN patterns are prefix-anchored APART FROM rp_session_key, which keys on the literal JSON field name "sessionKey" rather than on a generic key-name class, and no pattern measures entropy. The set as a WHOLE is not uniformly prefix-anchored and must not be described as such: the network kinds are an allowlist inversion, the identity kinds key on the probed identity, token:pem_private_key is a literal header, and Pattern.SkipAt already lets a pattern accept or reject a match by what SURROUNDS it — none of which reaches an unlabelled value, which is why the residue stands, and two of which (rp_session_key, SkipAt) are the shipped precedent remediation option (b) would generalise rather than introduce. Disposition: iss-96 stays OPEN with a dated verification section appended in place (the iss-24 precedent; a capture resolve would have had to state an action nobody took, and the ledger's resolution field is exactly that claim), re-scoped from "coverage may have moved" to a single unresolved DECISION between an entropy/charset detector with a length floor, key-name context matching, and the opt-in external-scanner adapter over this path only — three options that differ in REACH, not merely in false-positive cost, and saying otherwise would misdescribe them: (a) reads the value, so it is the only one that reaches an UNLABELLED value; (b) covers labelled values only and is structurally incapable of this entry's own first-named case, a bare secret-key value with no key name, because there is no key to match; (c) has whatever reach its ruleset delivers, and the measurement recorded in the entry corrects an earlier one that was wrong in both fixture and conclusion — re-run 2026-08-01 with pinned, sha256-verified gitleaks 8.24.3 default rules (gitleaks dir, no repo config) over a NAMED fixture, one specimen per line, comprising every case of TestTranscriptPathMissesUnanchoredEntropy's table, every line of the transcript TestCaptureStoresUnanchoredEntropyVerbatim captures, and delimiter probes on the same values: 21 lines, 6 findings, all generic-api-key, whose condition is keyword + =/: DELIMITER + entropy at or above 3.5 bits per character, so password: <passphrase>, --password=<passphrase>, api_key = <high-entropy> (the branch's own corpus case), session_token = <high-entropy> and session_token: <high-entropy> are all CAUGHT, while bare values with no key name, key names separated from their value by prose rather than a delimiter (the store fixture's hand-built session_token <high-entropy> line, which the earlier measurement mis-read as a key-name failure when the cause is the absent delimiter), and every sub-floor repetitive specimen whatever key name precedes it, all pass — so (c) as shipped reaches LABELLED high-entropy values, subsuming much of (b) and adding an entropy floor on top of it rather than being the narrowest option, and (a) remains the only one that reaches an UNLABELLED value; the anchored ghp_ control passing is a fixture artefact (36 repeated characters fall under gitleaks' own entropy filter — a realistic-entropy ghp_ token in the same run IS caught by github-pat), not a coverage claim. False-positive cost is the SECOND axis and lands hardest on (a) — a redaction false positive corrupts the record redaction exists to preserve — so reach and cost together are the open question and the bar is the maintainer's to set: grill-then-implement, not autonomous. The verification is PINNED in the tree rather than asserted in prose: TestTranscriptPathMissesUnanchoredEntropy at the pattern-set boundary and TestCaptureStoresUnanchoredEntropyVerbatim at the store boundary (each specimen present verbatim in the written record, the anchored token absent AND its fingerprintSpan fingerprint present — the byte-level mirror of maskSecret that sealLine actually applies on the Capture path, not maskSecret itself — since absence alone would also be satisfied by a store that dropped the line). THE PINS' REACH IS THE PATTERN SET, and the earlier claim that they "fail by design, never a silent pass" was too broad on two counts, both now fixed: the original specimens all REPEAT and measure 3.12, 2.16 and 2.75 bits per character, below the ~3.5-bit floor an entropy detector conventionally uses, so an entropy detector could have landed with every pin green — a 5.32-bit specimen assembled at run time from a fixed-seed shuffle, with its entropy asserted in-test at or above 4.5 bits per character AND its exact value asserted against a golden constant on both sides (entropy alone cannot see the two duplicated generators diverging, since a changed stream would still measure ~5.32 bits; the golden also pins determinism, and is gitleaks-clean as a literal because a bare 40-character alnum run carries no keyword and no delimiter), now closes that hole; and option (c) never consults DefaultPatterns at all, so NO ScanText-level pin can alarm for it by construction, which is stated in the entry so a stale close cannot lean on the pins alone. Within the pattern set they do fail by design — a charset/length floor, key-name matching or any new DefaultPatterns entry THAT REACHES THESE SHAPES trips them (the qualification is the test file's own, and it matters: an entry reaching nothing in the corpus rightly leaves both pins green) — and that failure is the signal to re-point them and close the entry. Never close on assumption: the anchored controls in the same corpus are caught, and one of them sits INSIDE the negative test, which is what proves the specimens reached a working detector rather than a mis-wired or emptied one; the negative assertion is scoped to the token/secret kind family, so an unrelated widened pattern fails it under a DIFFERENT message rather than being credited as entropy coverage — and that message now names BOTH readings, because a secret or entropy detector shipping under a namespace the family list does not know (secret:entropy, say) arrives down the same branch, where telling the reader to adjust the specimen would hide the very coverage growth the pin exists to notice. Every credential-shaped specimen is assembled at run time — the discipline network_test.go already states for flagged network identifiers — so, beyond the one golden constant this entry discloses as measured clean, no literal of that shape enters this repo's history for a full-history secret scan to fire on.

2026-07136

  • dcn-26073000000000072026-07-30

    2026-07-30 — a cross-agent transcript-capture source is the current default SOTA upgrade for the history corpus, triggered when compatibility beyond Claude Code becomes a concern; adopted import-only: its output enters through the pre-declared specstory-import seam over the native store, so the fail-closed redaction applies to imported material, and the native floor stays the default with capture degrading to it when the tool is absent. The candidate tool, target harness, and provider-coverage caveats live in research/notes/2026-07-30-session-recording-sota.md (§6 addendum) — commitment records name no external tool before adoption is decided. The SOTA verdict is re-verified at the adopting intent; a move from optional to required tool is a sota-per-intent path-1 hard stop (new-dependency approval). Rejected: adopting the tool's in-repo history directory as a store (adr-29 already rejected external stores; transcripts stay out of the repo) and bespoke per-host parsers (a permanent maintenance burden the external tool already carries). See iss-217. (Recorded 2026-08-15; decided 2026-07-30, parked across the attribution epoch.)

  • dcn-26073000000000062026-07-30

    2026-07-30 — itd-74 (round 7), increment 2: the scaffolding and honest-reach halves (AC5, AC7), closing spc-20's mapping. ahoy install writes three artefacts, all create-if-absent: the committed guard hook at .githooks/pre-commit, a .abcd/docs-lint.json carrying an EMPTY public banned-names family, and the documented private stub in the gitignored local tier. Three decisions worth the record. (1) THE SCAFFOLDED HOOK IS A GENERALISATION, NOT A COPY. It drops this repo's iss-62 identity gate and the itd-76 dogfood refresh and keeps the name guard alone, so a byte-equality drift test between the two files would be wrong; the template is proved BEHAVIOURALLY instead — the scaffold test installs it into a real temp repo and drives three commits through it (loud warning and exit 0 with no entries, refusal naming the key alone with the pattern absent from all output, refusal to stage the store itself), which is the only evidence that distinguishes a guard that works from one that merely parses. Rejected: a symlink from .githooks/pre-commit to the embedded default (zero duplication, but breaks a Windows checkout and would have rewired increment 1's own test harness), and copying this repo's hook verbatim (it would scaffold repo-specific gates into every managed repo). (2) THE PUBLIC FAMILY IS SEEDED EMPTY. abcd cannot know which names a repo may not publish, and a ban nobody declared would fail a build over a word the maintainer never chose; the array's PRESENCE is what makes banlist add --public usable, which is all AC5 asks for. A docs-lint config that exists but carries no usable array is a NON-resolvable diagnostic gap: the config gates CI and a contributor owns it, so abcd reports the fault and never rewrites a file it cannot read. (3) THE STUB'S GAP IS RESOLVABLE ONLY ONCE THE FENCE COVERS IT. Writing the store into a repo git would track is the exact hazard the layer exists to prevent, so the stub write runs after the visibility step and is gated on the canonical .gitignore block being on disk; advertising it as resolvable regardless would leave a repo permanently "partial" on a fix apply refuses to make (the markerSymlink precedent). No new gitignore entry was needed — iss-169's fence already covers .abcd/.work.local/ under private and /.abcd/ under public — so AC5's gitignore clause is pinned by a new test against real git check-ignore, keyed to banlist.PrivateRelPath rather than to a spelling of the tier, and it passed on first run. AC7: the reach sentence lives once as banlist.PrivateReachNote and travels INSIDE the reported state (BanlistHealth.Reach), not as renderer prose — a machine consumer reading "hook installed" beside a present store would otherwise draw exactly the wrong conclusion, and the JSON envelope is a report surface too. The health pass reads no entry and spawns no subprocess: the store's content is the secret, and a status board is the surface that must not hold it. Stub examples are all commented out (a fresh scaffold parses to zero entries, so the guard warns loudly rather than looking like protection) and every illustrative value is a reserved documentation value or a persona-derived fixture host, judged by the repo's own network-identifier detector — with a control value asserted flagged first, so the assertion cannot pass vacuously. Residual, recorded not fixed: abcd does not set core.hooksPath, so a clone arms the hook by hand (the record scopes AC5 to the hook being committed, and silently repointing a repo's hooks path is a git-config change no acceptance criterion asked for); and the scaffolded template and this repo's prototype now share ~250 lines that no mechanism holds in sync. FIX PASS after two fresh adversarial reviews returned BLOCK on this increment's own code; detector-first throughout, each behaviour change watched failing first. (A) THE FENCE IS GIT'S DECISION, NOT A TEXT COMPARISON. Both the stub write and the gap's resolvability were derived from gitignoreBlockDrifts — a set comparison of the abcd-managed .gitignore block — which answers a different question from the one that matters. A repo can carry a byte-perfect block and still track the store (a negation after it, a tracked tier), a fully-configured repo never reaches the visibility step at all, and stepConfigValues returns nil whenever ANY unrelated config value is missing under a declined ConfigChange, which silently disabled the write while localTierIgnored reported the gap as resolvable — a permanent partial. Both now call gitutil.IsIgnored, the same primitive increment 1's requireIgnoredStore uses, evaluated on disk after the visibility step, and skipped outside a git repo for the same stated reason (a check cannot demand proof no one can supply). Health carries the verdict and a present store git would track is called out on every surface. (B) CONTAINMENT. The three writes used os.MkdirAll plus an atomic rename, and a repo that commits a symlink at .githooks — which a checkout materialises before abcd runs — took the 0755 hooks OUTSIDE the repo while every surface reported the in-repo path; watched, and confirmed by the reverted code writing pre-commit into the link target. They now go through fsutil.CreateExclusiveIn under an os.Root opened at the repo, which is both guarantees at once (no clobber, no check-then-write window) and refuses symlink traversal at every level. The local-tier case was already contained by increment 1's os.OpenRoot read path, which reports such a store as unreadable rather than absent. (C) BOM FAIL-OPEN, IN BOTH READERS. A leading UTF-8 BOM made the first line differ from the format declaration, so a KEYED store read as LEGACY: every keyed entry became a whole-line pattern matching nothing a commit contains, while entries stayed >=1 so the zero-entry warning never fired — a store that looked healthy and checked nothing, reproduced as a real commit going through. Fixed in the Go parser, the scaffolded template, and this repo's own prototype; and a first line that is not the declaration but WOULD be after stripping leading blanks is now a DAMAGED declaration that fails closed, because reading it as legacy is the same downgrade by another route. (D) MERGE-COMMIT BYPASS. git runs no pre-commit hook for a merge, so a banned name entered history the moment a branch carrying it was merged; a pre-merge-commit half now runs the same guard through one implementation (a shim, not a copy) in both the template and this repo. The reach sentence widened with it: PrivateReachNote now names what a hook cannot see — a rebase, git am, a cherry-pick, --no-verify — because "machines that have opted in" is necessary and not sufficient, and the shorter sentence let a reader believe an opted-in machine was covered. (E) TWO CLAIMS WITHDRAWN. A foreign pre-commit hook was reported as the abcd guard: presence is not identity, so each template carries # abcd-name-guard: v1, a hook without it is a non-resolvable diagnostic abcd never replaces, and "installed" became "committed" with the arming instruction beside it (git runs the hook the clone's hooks path selects, which abcd neither sets nor fully observes). And under visibility: public the fence ignores the anchored /.abcd/, so the "committed, CI-enforced" public family is untracked exactly where public exposure is the risk — detection now reports banlist.public_family_ignored and the board reads NOT ENFORCEABLE. The placement question is NOT resolved here (moving the file amends the iss-169 record; carving an exception gives up its one-switch property) and is captured as iss-176 for the maintainer, with three candidate reconciliations. Minors in the same pass: the private layer's shape comes from a new banlist.SummarisePrivate — the shared parser without the per-entry grep, so a status pass costs no subprocess per line — the public family's four faults report apart (an unreadable file is not an absent array), the local tier's 0700 is asserted rather than assumed from the creating call, the staged-path refusal is case-folded, the format is announced before the parse loop, and stale scratch files are swept. Residuals the reviews verified as accepted: the scaffolded template and this repo's prototype share ~250 lines that no mechanism holds in sync (byte-equality would be wrong — the template drops the identity gate and the dogfood refresh — and the template is proved behaviourally instead); --no-verify, rebase and server-side pushes remain uncoverable by construction; GNU/BSD grep divergence stands as increment 1 recorded it; commit messages, tag names and branch names are outside the guard's scope (it reads staged blobs and paths); a scaffolded repo gets no CI wiring for the public family; abcd still does not set core.hooksPath; and a.note() renders absolute paths across every apply step, pre-existing and repo-wide, captured as iss-177 rather than half-fixed here. FIX PASS 2 after a second pair of independent BLOCK reviews, both on the fix pass's own code. (F) THE MERGE SHIM NEVER STANDS IN. It was written whenever its own gap was present — including beside a FOREIGN pre-commit hook — so abcd's marker landed in the shim, the board read "pre-merge-commit hook committed", and merges stayed unchecked; worse, the maintainer's hook silently began running on merge commits, which git never did, so apply was taking over exactly the wiring the foreign-hook gap disclaims owning. The shim is now written only beside abcd's own guard (including one the same step just wrote — keyed on the artefact's STATE, not on a gap a fresh repo deliberately does not raise), and banlist.merge_hook_inert reports the alternative. The wrong assertion in the increment's own test — which asserted the buggy behaviour — was flipped and watched fail. (G) A COPY OF THE STORE IS A MISTAKE-NET, NOT AN ADVERSARY-NET. The staged-path refusal matched only the local tier, so cp of the banlist to notes.txt, or a git mv out of the tier, committed every pattern in clear while the guard announced a clean check — the entries cannot catch their own text, because they are escaped regular expressions and carol-server\.example\.net does not match itself. Three tests now: the tier path (not escapable, and applied to a rename's SOURCE path too — the loop had been overwriting it with the destination and discarding the one field that identified the file), a staged blob whose FIRST LINE is the format declaration, and a staged path whose basename is the store's filename. Their reach is stated rather than implied, here and in the brief and the spec: a copy with the declaration stripped, altered by a byte or displaced below a preamble passes the first-line test; a LEGACY store declares no format at all and passes it always, and passes the basename test the moment it is renamed; and the rename-source test only fires for a store git already tracks. What they catch is the accident that happens — a cp, a .bak, a stray duplicate — and they are NOT widened further on purpose: matching a store's key list or scanning deeper into every staged blob would route the secret through more code paths to catch fewer accidents. Round 3 also found the other direction: the first-line test blocked this repo's OWN committed corpus fixtures, and --no-verify is an off switch for the whole guard rather than a per-file escape, so the refusals now honour a published second-line # abcd-banlist-example marker — exempting a blob from the COPY tests and from nothing else, its content still scanned against every entry — and the two keyed corpora carry it. The tests also moved OUT from behind the absent-store early exit (whether this machine has a store says nothing about whether a commit is carrying one, and that exit was itself how the rename escaped), and the guard no longer creates its local tier in a repo that never opted in: with no store it scratches in a 0700 temp directory instead of leaving an unfenced abcd directory behind on every commit. (H) THE DECLARATION IS LINE 1 OR NOWHERE, in all three readers and for BOTH formats. A blank line or a comment above it, a duplicate below it, or any prefix bytes before it (a UTF-16 byte-order mark, an editor artefact — caught by a suffix test rather than a byte-class check no portable shell has), is a damaged declaration that fails closed. Round 3 found the header scan gated on the store not already being keyed, so a keyed store with the declaration repeated on line 2 read as healthy to Go — "present, keyed, 1 entry" on the status board — while the shell blocked every commit; a store one reader calls healthy and the other refuses is worse than either verdict alone, and a fourth shared corpus now drives both readers over exactly that file. (I) THE ENVIRONMENT IS PINNED FIRST, in all four hooks: xtrace off, IFS, LC_ALL and PATH as the FIRST statements, before anything is read or run — the pin had been landing after rev-parse/cd, and the merge shim had none at all while resolving its delegate through an external dirname (now ${0%/*}, pure parameter expansion). The pin NARROWS the substitution class and does not close it: two of the pinned directories are user-writable on a typical developer machine, and #!/usr/bin/env bash resolves the interpreter through the inherited PATH before any of it runs — the earlier "root-owned" wording in this line was wrong and is corrected here. Every external tool the hooks call is probed after the pin so a missing one blocks loudly instead of surfacing as a mute exit 127, and a nonstandard prefix extends the pin through git config --local abcd.guardPath — read through the already-pinned git, and deliberately NOT an environment variable, since a repo-scoped direnv sets the environment and would reopen the exact hole. Minors in the same pass: scaffolded modes are chmod'd explicitly because CreateExclusiveIn and MkdirAll are umask-masked and a stripped exec bit turns the shim's fail-closed branch into a permanent merge block; the marker is matched by PREFIX so a v2 template cannot reclassify every v1 hook as foreign; storePathIsSafe distinguishes "not a repository" (skip, as before) from "repo-shaped and git will not answer" (fail closed) — InRepo is false for git-absent-from-PATH too, which the old comment's justification did not cover; hooksPathArmed resolves both sides before comparing, so an absolute core.hooksPath is no longer read as unarmed and told to downgrade itself; the absent-public-family gap is non-resolvable where git would ignore the path and abcd declines to write a config it would immediately call unenforceable; the detection envelope omits the banlist object for an unmanaged folder rather than serialising undeclared zero states; detection reads now resolve through the same containment root the writes use; the reach note is explicitly non-exhaustive and names git revert and a reapplied stash; and abcd ahoy scaffolds the .githooks/* text eol=lf attribute into managed repos (append-if-missing, never a rewrite) rather than leaving them the CRLF-shebang failure this branch fixed for abcd itself. CORRECTION to this line's earlier claim that the health pass "spawns no subprocess": it always did — it now spawns four (one rev-parse, one batched check-ignore for both paths, one config --local, and one check-attr for the hooks' EOL), down from six or seven, and ahoy.Detect is on the session-hook path, so that count is a cost paid per prompt. One earlier test was vacuous and is fixed rather than deleted: the local-tier half of the symlink containment test passed with containment reverted, because the escaping store is classified unreadable before any write is attempted, so it now asserts that protecting state by name. FIX PASS 3 (converge). MARKER IDENTITY: classifyGuardHook matched the marker as a substring of the whole blob, so a foreign hook that merely MENTIONED it — a comment, a grep for it — classified as abcd's own, the board claimed coverage, and the merge shim was written beside it; identity is now a whole LINE matching ^# abcd-name-guard: v<digits>$, with the version a group so a v2 template cannot reclassify v1 hooks. The same line-wise fix went to the .gitattributes pin, where a commented-out attribute had read as pinned. REACH ACCURACY: a fast-forward git pull creates no commit and so runs no hook — the commonest uncovered path of all, now named — and the stash claim was probed FALSE (git stash pop then commit runs pre-commit normally) and removed: a bypass list naming a covered path teaches a reader to distrust the rest of it. Minors: the merge-inert gap no longer asserts a delegating shim that may not exist; createContained pinned modes on directories it did NOT create, widening a maintainer's deliberate 0700 to 0755, and now pins only what it made; repoShaped walked no ancestors, so in a repo SUBDIRECTORY with git unavailable the stub would have been written into a tracked tree; the stale-scratch sweep and the tier creation are conditional on the tier being the scratch home; and the foreign-hook gap's Required: false is documented as deliberate (a required gap nothing can resolve is a repo permanently reported incomplete for a state its maintainer chose). Also re-classified: stepBanlist now asks disk what occupies the hook paths rather than trusting the detection snapshot taken before the earlier steps ran. FIX PASS 4 (prose currency plus one-liners). The two CHANGELOG bullets, internal/README.md, and both brief surfaces described THREE scaffolded artefacts and a stale reach; there are FIVE (both guard hooks, the .gitattributes LF pin, the public family, the stub), and the reach now names a fast-forward git pull — the commonest uncovered path of all — and no longer names a reapplied stash, which probing showed IS covered and which reach_test.go now pins out. Security minors: an inherited shell FUNCTION shadowing grep defeated the PATH pin entirely (probed — the guard reported a clean check under BASH_FUNC_grep%%=() { return 1; }), so all four hooks now unset -f the commands they run as their first statement after the xtrace guard; abcd.guardPath refuses a value with an empty PATH element, which every consumer reads as the current directory; the scratch-directory trap is installed before the three inner mktemps that could exit past it; and mktemp -d takes an explicit portable template. The .gitattributes classification stops pattern-matching abcd's own line and asks git check-attr eol instead — git is already this package's authority for the ignore question, and a later * text eol=crlf overrides a line a regex still calls pinned; the line-anchored regex survives only to keep an append from duplicating. The marker regex tolerates a trailing CR, so a CRLF-mangled abcd hook classifies as OURS-but-unpinned and install can heal it rather than reporting a foreign hook for ever. Three residuals are widened rather than fixed, in the brief and the spec: the environment pin narrows common accidental and repo-scoped routes and closes nothing (anyone controlling the committer's environment wins); the example escape keeps content scanning so it cannot smuggle a plaintext banned name, but it protects no copy of a STORE — escaped patterns never match their own text — and a live store carrying the marker exempts every copy of itself; and the marker asserts identity, never integrity, so any file quoting it is treated as abcd's guard. Lifecycle: itd-74 sits in shipped/ with its fidelity review OWED (receipt rcp-3ceed52bdb99). That is the designed follow-up, not an omission — abcd spec close stamps the receipt and the review is a separate verb (abcd intent review), which record-lint and audit accept; no record file was hand-edited to produce or to clear it.

  • dcn-26073000000000052026-07-30

    2026-07-30 — itd-74 (round 6), SECOND fix pass after two fresh adversarial reviews returned BLOCK on the first fix pass's OWN code. Detector-first throughout, each fix reverted in place and watched to fail before it passed. The guard's staged-content read was the cluster: it now reads each staged blob stage-explicitly (git show ":0:$path", closing the 0:README.md rev-magic bypass), derives staged modes from git diff --cached --raw -z so a gitlink (mode 160000, no blob here) is SKIPPED rather than fail-closing every commit forever, scans the staged PATH strings alongside content so a banned name in a filename is refused by key, refuses any staged path under the local tier (the private store must never be committed, and the guard cannot catch its own source), and announces the format and entry count it actually read before the scan so a stripped # abcd-banlist: keyed line cannot silently downgrade every keyed entry to a non-matching whole-line pattern. The verbs: add now proves the composed KEY<space>PATTERN line round-trips (a whitespace-only pattern wedged the store as key ; leading/trailing whitespace was silently trimmed so the enforced pattern differed from the validated one) and rejects a NUL the two readers disagree on; the stdin path reads all of stdin and refuses trailing data rather than storing the first of a multi-line pattern silently; the verb resolves the git working-tree toplevel — the exact root the guard enforces at — so a repo nested under a parent holding a .abcd/ no longer writes its store into the parent where the guard never reads it; no cobra path echoes an unknown token (a would-be private value); the inert verdict is driven by the grep probe, not a static screen that falsely called \b/\w/\s "matches nothing" (GNU grep implements them); remove --private deletes ALL lines for a key (a duplicate no longer survives under a key the report calls gone) and remove --public no longer lets a bare hand-curated key shadow the managed names/<key> target it owns; the read path reports a store git does not ignore; and a mutation's entry count excludes unparseable lines so it agrees with list. Records corrected: the brief and this ledger had the RE2-vs-ERE divergence backwards — Go ACCEPTS [a-z-.] while grep -E refuses it (exit 2), the opposite of the earlier wording; engine.go was already right. Residual, recorded not fixed: the fsutil lock files are 0644 and never unlinked (a shared primitive; the banlist lock lives in the 0700 gitignored tier and the file is empty), a public-only add still creates the gitignored local-ephemeral tier to place its lock (nothing leaks; relocating hits the atomic-rename-inode problem), the .abcd-symlink asymmetry and a hand-written store's 0644 mode; and the out-of-repo sync-banlist trust and the empty-$toplevel branch carry over from the first pass. RemovePrivate surfaces the not-ignored condition only via the shared read path (list/bare), since PrivateResult carries no health field.

  • dcn-26073000000000042026-07-30

    2026-07-30 — itd-74 (round 6), fix pass after two adversarial reviews (correctness + security) both returned BLOCK. Five decisions, each replacing a mechanism rather than patching an instance. (1) THE STORE DECLARES ITS FORMAT. The private banlist's first line — # abcd-banlist: keyed — decides the whole file: keyed means every line must parse as KEY<space-or-tab>PATTERN, no declaration means every line is one whole-line pattern under entry-<line-number>, and no line is ever split. The previous per-line heuristic ("is the first field key-shaped?") was wrong in two independent ways at once: it printed part of a legacy line as a key, and on this layer a pattern IS the secret, so the guard leaked what it existed to withhold; and it narrowed an old whole-line pattern to the remainder after its first field, so protection did NOT "never weaken because the format grew a column" — the earlier record line and the brief both claimed otherwise and were wrong. A declaration costs the user one line and makes both classes unrepresentable; add/remove refuse a non-empty legacy store rather than migrate it, because writing a keyed line in would silently reinterpret every other line. Both readers now strip ASCII space and tab only: strings.TrimSpace and bash [[:space:]] are different sets, so a U+00A0-indented line was keyed by one reader and dead to the other, and a U+000B-separated line the reverse. (2) VALIDATE AGAINST THE ENGINE THAT ENFORCES, not a convenient third one. A private pattern is screened for the constructs POSIX ERE does not implement (a backslash before an alphanumeric, (?) and then handed to grep ITSELF on stdin to accept or refuse; RE2 is the fallback only when grep cannot be run, and the refusal says so. Checking under RE2 accepted \d and (?i) as healthy (grep reads them as something else — inert protection reported live) and accepted [a-z-.], which grep refuses (its fail-safe branch then blocks every commit). The public layer's engine is Go's regexp because abcd docs lint enforces it, so a public add compiles the EXACT string it stores through the linter's own compile path, and stores it with the (?i) prefix all sixteen hand-curated entries carry — without it a verb-written entry was case-sensitive while the docs promised otherwise. list --private reports unusable and inert lines APART: the first stops every commit, the second stops nothing, and one message for both misdirects an incident. (3) THE GUARD READS STAGED BLOBS, not diff text, and fails closed. Four shapes staged a banned name that no diff-text reading could see: a content line beginning ++ becomes +++ and is dropped with the headers, a NUL-bearing blob has no textual diff at all, a committed .gitattributes with -diff disables the reading repo-wide in one line, and a rename is status R which the ACM filter excluded (as it excluded T). git show :<path> over --name-only -z --diff-filter=ACMRT asks the question the guard is actually asking and has no shape to route around. Every git step is checked, replacing a || true that turned any failure into a clean pass: a check that could not run must never be indistinguishable from one that passed. (4) CONTAINMENT IS THE WRITE PATH'S JOB. Reads and writes resolve through os.Root, so a symlinked .abcd/.work.local cannot land the private patterns outside the repo while the verb reports the in-repo path; the verbs resolve the repo root as the rules loader does rather than trusting cwd, which had created a second nested store that the root-anchored gitignore does not match and the guard does not read; add --private refuses when git does not ignore the store path, because the layer's whole safety is that the file is untracked and the guard cannot catch its own source; and both stores hold the shared flock across load-modify-write. (5) A PATTERN NEVER TRAVELS IN ARGV. The hook passes it to grep via -f - on stdin, the verb accepts - to read one line from stdin (the documented form), and a flag-parse failure withholds the offending token instead of quoting it. Accepted trade on that last point: SetInterspersed(false) was rejected because the documented add --private KEY "PATTERN" --json puts a persistent flag after the positionals; a flag-error surface closes the leak without breaking it, and a test pins the trailing flag. Residual, stated rather than fixed: the guard still trusts an out-of-repo sync-banlist executable it neither verifies nor sandboxes, and a garbling refresh is only partly caught (the zero-entry warning); and the empty-$toplevel branch is guarded but not test-covered, because git resolves the repo before invoking a hook.

  • dcn-26073000000000032026-07-30

    2026-07-30 — itd-74 (round 6), increment 1: the private guard layer end to end plus the maintenance verbs on both layers (AC1–AC4, AC6). Private entry format is KEY<whitespace>PATTERN with the key charset [A-Za-z0-9][A-Za-z0-9._/-]* — deliberately free of every regex metacharacter, which is what makes legacy compatibility safe rather than best-effort: a line whose first field is really the head of a regex cannot pass for a key, so it falls back to the whole-line reading under the synthetic key entry-<line-number>, and even where a split does apply to an old two-word pattern the resulting match is a superset of the old one (over-blocking, never under-blocking). Refusal names the key alone; the matched text and the pattern never reach any output, and a malformed line is a refusal naming its line number, because a banlist that cannot be read must not look like a banlist that found nothing. Two hook-internal fixes fell out of writing the proof: the candidate text moves from a pipe into grep to a temp file (under pipefail, a matching grep -q exits early and the writer left holding a closed pipe reports 141, which the pipeline surfaces instead of grep's verdict — a staged diff larger than the pipe buffer could silently defeat the guard), and grep's own stderr is discarded so an engine error message can never echo a pattern. Public layer: entries are managed IN the existing banned_tokens family of .abcd/docs-lint.json under a names/ id prefix, and the prefix is the ownership boundary — list renders the whole family (hand-curated harness/present_tense entries included, marked as such), remove refuses anything outside the namespace. Config edits are byte surgery on the array located through the standard decoder's input offsets, never a re-marshal: an add is one inserted line plus a separating comma, a remove is one deleted line, and add-then-remove is byte-identical to the original — asserted against this repo's own docs-lint.json rather than a synthetic fixture, because a surgical editor proven only on a two-entry toy is not proven. Redaction is structural, not conventional: the exported private entry type has no pattern field at all, so no future rendering can leak the value, and pattern-validation errors discard the engine's message because Go's regexp errors quote the expression. One format, two readers, one fixture: testdata/parse-corpus.txt and one shared probe table drive both the Go parser and the committed shell hook, so their agreement is checked rather than assumed. Residual: the two engines are RE2 and the platform's POSIX ERE, so a pattern valid in one and not the other is possible — the shared corpus is restricted to constructs both accept, and the malformed-line path fails safe on either side. Deferred to later increments: ahoy scaffolding of the guard artefacts and the seeded stub (AC5), the honest-reach line on the status/report surfaces (AC7; abcd banlist itself states it), and the intent/spec lifecycle moves.

  • dcn-26073000000000022026-07-30

    2026-07-30 — iss-169: the visibility-driven .gitignore block now carries the brief's §1 table verbatim — private ignores .abcd/.work.local/ only, public ignores the anchored /.abcd/ plus the legacy root-level /memory/ (the leading slash pins each public entry to the repo root; an unanchored pattern matches at any depth and would also ignore nested paths such as an internal/memory/ source package) — replacing a phantom root-level .work/ that appeared under both visibilities. The brief was checked first and is current: the tier table directly above §1 commits .abcd/development/ and .abcd/work/ and gitignores the local tier, so the code alone had drifted, and the issue's hedge that the public set "needs rethinking" resolves to a path fix, not a policy question. Under public no separate .abcd/.work.local/ entry is needed because .abcd/ subsumes it — visibility stays one switch with no per-subdirectory exceptions. Upgrade needs no migration verb: gitignoreBlockDrifts compares set-wise so an old block reads as drift, and applyVisibilityBlock already strips every block before writing the canonical one; the test pins that shape for both visibilities. This closes an installer-versus-auditor contradiction — three-tier-layout asserts the local tier is gitignored, which the installer's own output guaranteed it was not.

  • dcn-26073000000000012026-07-30

    2026-07-30 — iss-156: the PII rules domain gains the network/infra recall vocabulary the leak incident needed (ip, ips, ipv4, ipv6, vpn, tailscale, tailnet, wireguard, firewall, network, reachability, reachable, dns, ssh, subnet, plus the mac address alias) and one new rule line forbidding committed hostnames, IP/MAC addresses, and other live network identifiers: redact or omit, and use a reserved documentation value (RFC 5737/3849/2606/7042, the same citation set as the scanner and the audit privacy-hygiene rule) only where an illustrative example is needed — the rule does not tell an agent to substitute a plausible fake identifier into a factual write-up. Data-only: recall matching is already word-bounded (the prompt is normalised to space-separated tokens and a single-token term must match a whole token), so the bare ip keyword is safe and no matcher change was needed — a substring matcher would have forced a phrase form like ip address. Placement is dictated by the matcher, not by word count (aliases also holds single words such as pr and diataxis): a term goes in recall when it should hit as a standalone token, and in aliases when only the multi-word phrase is safe — mac alone would recall on an Apple Mac, so mac address is a phrase alias and matches via the stemmed-phrase path. The stemmer's own limits force the explicit variants: a three-character floor keeps ips from stemming to ip, and -ability is not bridged to -able, so reachable is its own entry. Accepted trade: broad tokens like network over-fire on prompts with no privacy stake, which is benign here — the injection is four short rule lines, deduped once per session. The never-commit-identifiers rule previously existed only in a parent CLAUDE.md privacy section, so the loader could never inject it; the 2026-07-29 reserved-identifier principle now has a rule-text home the hook actually emits.

  • dcn-26072900000000062026-07-29

    2026-07-29 — server-side merge backstop for the autonomous loops: "main protection" rulesets in the predecessor CLI's established shape (PR required with 0 approvals, required status checks, strict up-to-date, force-push/deletion blocked, no bypass actors) added to abcd-cli, Bauhaus, Testimony; itemdeck.app got the PR/force-push/deletion rules only because it has no CI yet (adding CI, then the checks rule, is the follow-up). The three private repos cannot carry rulesets on the current GitHub plan, so their loops rely on the prompt-side merge gate alone. Consequence accepted: direct commits to main are now rejected on the gated repos — trivial changes ride a docs:/chore: PR with auto-merge armed. (Recorded 2026-08-15; the line was parked uncommitted across the attribution epoch.)

  • dcn-26072900000000052026-07-29

    2026-07-29 — iss-155: three-tier-layout gains the placement half of the tier convention — local-tier artefacts (NEXT.md, scratch/, logs/) found directly in a committed tier are now errors, each finding carrying a move-to-.abcd/.work.local/ fix. The rule verified tier presence and the .work.local gitignore but never that local ephemera were ABSENT from .abcd/work/ and .abcd/development/, which is exactly how a handover file carrying host infrastructure detail reached a public repo unflagged. Presence is checked on the filesystem, matching the tier checks themselves: an untracked NEXT.md in a committed tier is one git add -A from history. The existing rule extends rather than minting a sibling ID — one convention, one rule.

  • dcn-26072900000000042026-07-29

    2026-07-29 — the A2 network-identifier detector lands as one atomic change (iss-154+157+125+153): an allowlist inversion built once in the scanner's canonical pattern set, folded into DefaultPatterns so Stage-1 redaction and the launch/lifeboat scan inherit it, and consulted directly by the audit privacy-hygiene rule so the two surfaces cannot disagree about what a leak is. Maintainer disposition on the first repo-wide run (28 findings, plan STOP 2): the exempt set is "values that name no individual host" rather than the reserved documentation ranges alone — loopback, unspecified, netmasks, masked CIDR prefixes, and the IANA special-use ranges (IPv4 link-local, multicast, benchmarking, protocol assignments; IPv6 link-local, multicast, NAT64 well-known prefix, benchmarking). What identifies private topology stays flagged, which is the incident class: RFC 1918, CGNAT/tailnet, IPv6 unique-local, and 6to4 (it embeds a routable address, so it names a host) — consistency of the rationale wins over convenience of the residue. Twelve deliberately illustrative lines take the sanctioned per-line waiver; the repo audits clean on privacy-hygiene. The plan's STOP threshold is clarified to count findings, not distinct identifiers. Also here: /Users/Shared and /Users/Guest stop reading as usernames (iss-153), in both the audit rule and the scanner's identity matcher.

  • dcn-26072900000000032026-07-29

    2026-07-29 — v0.5.0 cycle runs as a scheduled cloud loop (one item per 5-hour round, plan order): auto-merge authorised through the strict gate only (CI green + two adversarial MERGE verdicts; security lens mandatory on workstream A/B diffs); itd-74 is in autonomous scope, multi-round via PR resume, bounded by spc-20 and STOP condition 1. Rejected: human-merges-everything (stalls the ordered pipeline at merge cadence) and auto-merge-C/D-only (slows exactly the security half the release is for).

  • dcn-26072900000000022026-07-29

    2026-07-29 — v0.5.0 scoped as "security & consistency" (plan: plans/2026-07-29-v0.5.0-security-and-consistency.md): the security half closes the NEXT.md leak class end-to-end (itd-74/spc-20; the atomic iss-154+157+125+153 detector item; iss-155/156; guard batch iss-159+144+148; boundary fixes iss-30/34), the consistency half retires the record-currency majors (iss-37..44, iss-80) — maintainer added the latter rather than deferring them. Version is derived by launch ship, not declared; 0.5.0 is the prediction given itd-74 additive. Deferred majors listed explicitly in the plan (largest: iss-124); the 2026-07-24 queue's pick-up role is superseded.

  • dcn-26072900000000012026-07-29

    2026-07-29 — privacy-leak follow-up: illustrative machine identifiers in anything committed or published always come from reserved documentation ranges (RFC 5737 IPv4, RFC 3849 IPv6, RFC 2606 domains, RFC 7042 MACs; hostnames derived from the persona registry, e.g. alice-laptop) — the itd-79 persona rule applied to infrastructure. Recorded as principle examples-use-reserved-identifiers; enforcement is the iss-154 allowlist-inversion lint (flag any identifier OUTSIDE the reserved ranges), whose shipping promotes the principle to a discipline. No new intent: real private identifiers are itd-74's banlist territory — the incident evidence extends itd-74's scope to machine identifiers (iss-158) rather than founding a second primitive. Incident issue text deliberately names no repo and no values (shape only), so the ledger itself cannot re-leak.

  • dcn-26072800000000082026-07-28

    2026-07-28 — itd-102: no scaffold entry point existed in ahoy/prepare for a repo record block, so the verb family gained a minimal identity init (write path: block + pointer, atomic, adopts an existing block, refuses to repoint an adopted registry). abcd launch scaffold is release-machinery-specific and ahoy install writes only abcd's own plumbing; extending either would have widened its remit.

  • dcn-26072800000000072026-07-28

    2026-07-28 — itd-102: surface comparison is normalised CONTAINMENT of each required block field (markup, dashes, wrapping, case folded; trailing sentence punctuation trimmed from the needle), not line equality. Equality would flag abcd's own three conforming surfaces, each of which carries the tagline in a different rendering (inside <p>, concatenated with the pitch in the manifest, bolded mid-sentence and line-wrapped in AGENTS.md); containment catches all three iss-143 variants while accepting all three current ones. Consequence: identity render fires only on drift, and its template render is a proposal to adopt by hand, not a byte-exact reproduction of conforming prose.

  • dcn-26072800000000062026-07-28

    2026-07-28 — itd-102 implementation: repo positioning lives in a NEW internal/core/positioning package, not internal/core/identity — that package is the git commit-author gate (.abcd/config/identity.json pin, pre-commit hook) and shares nothing with repo self-description but the English word; folding them would put two unrelated concerns behind one name. The user-facing verb stays abcd identity (spc-19). For the same collision the registry is .abcd/positioning.json at the .abcd/ top level (beside docs-lint.json / record-lint.json / rules.json), NOT .abcd/config/identity.json. Rejected: extending the commit-identity package; naming the verb abcd positioning (spc-19 fixes the verb).

  • dcn-26072800000000052026-07-28

    2026-07-28: itd-102 spec minted as spc-16 (fourth live iss-80 instance this run); renumbered to spc-19 by hand.

  • dcn-26072800000000042026-07-28

    2026-07-28: itd-104 spec minted as spc-16 (third live iss-80 instance this run: 16 collided with #156, 17 with the itd-101 branch); renumbered to spc-18 by hand.

  • dcn-26072800000000032026-07-28

    2026-07-28 — itd-101 part (b) closed two robustness notes from the approving security review, and flagged two it left. (1) A page read is now BOUNDED and regular-file-checked (fsutil.ReadGuarded, 8 MiB), because containment answers "does this path land inside the repo" and says nothing about how big what it lands on is — and this collector's output is fetched over the network. It opens the RESOLVED path rather than the literal one: O_NOFOLLOW on the literal path refuses every symlink leaf, which would break the legitimate in-repo bridge (CLAUDE.md -> AGENTS.md) that containment has just approved. So containedRealPath returns the resolved path alongside its verdict, and the reader reads exactly the thing containment judged. (2) StatusOK and StatusBlocked now ENTAIL an answer in the wholesale-failure guard: a 2xx cannot exist without a host replying, and "blocked" is defined by a status code, so only StatusBroken is genuinely ambiguous. That is what those statuses MEAN, not inference from a proxy, and it removes a footgun where a third-party adapter omitting Answered would refuse a run in which every check succeeded. The Checker seam's doc comment now states both obligations an implementer owes. NOT DONE, deliberately: (a) urlguard.BlockedIP still omits CGNAT 100.64.0.0/10 and benchmark 198.18.0.0/15 — adding them would change memory ingest behaviour, and that extraction was landed as a behaviour-preserving port, so it belongs in its own change; (b) a narrow availability path remains where a repo whose entire baseline is current-manual plus one PR-added citation to an unroutable host refuses the whole refresh with a misleading "check connectivity" — the reviewer could not make it bite on a realistic corpus, and the guard's limits are already recorded above.

  • dcn-26072800000000022026-07-28

    2026-07-28 — itd-101 part (b) third review round closed the other half of the roots containment and recorded one accepted narrowing. (1) Containing the configured ROOT string is NOT enough: WalkDir yields a symlinked .md as an ordinary file and os.ReadFile follows it, so a committed docs/leak.md -> ../private/notes.md sits inside a perfectly contained root and still drags an outside file's citations into the live fetch and then into the committed, pushed baseline. Every collected FILE is now resolved-contained, not just its root; an in-repo symlink (the CLAUDE.md -> AGENTS.md bridge shape) still resolves, because containment is about where a path LANDS. RULE affirmed: a containment check on a directory says nothing about the files found under it. (2) ACCEPTED NARROWING in the refresh's wholesale-failure guard: keying it on answered (a host returned any status line) rather than on success means an intercepting proxy or DNS sinkhole that answers EVERY request with a non-2xx outside the blocked set — 503, 407, or a default-vhost 404 — no longer trips it, and a whole corpus would be rewritten broken. That is strictly narrower than the condition it replaced, but the replaced one was wrong in two commoner ways (any repo that had ever run confirm lost the protection entirely, and a sole genuine 404 could never be recorded). It ships because refresh is operator-initiated and its transcript prints the broken: count before anything is pushed; the guard covers failures that produce no status line at all, and nothing more. (3) A CHANGELOG entry must describe the tree AT ITS COMMIT, never the state it will reach once a human acts: rewording the citation bullet to the post-confirmation state asserted "every URL carries a receipt" while the repo's own gate printed the counter-evidence. Reverted to the true count.

  • dcn-26072800000000012026-07-28

    2026-07-28 — itd-101 part (b) second review round closed three holes the first round's fixes left open, all reproduced end-to-end by the reviewers. (1) The baseline-path containment check was purely LEXICAL, so a committed symlinked directory (.abcd/evil -> /outside) plus a lexically-innocent "baseline": ".abcd/evil/x.json" reopened the very arbitrary-file-write primitive the first fix claimed to close — WriteFileAtomic MkdirAll's through the link. Containment now also RESOLVES: EvalSymlinks on the deepest existing ancestor of the target (it usually does not exist yet on a first run), compared against an EvalSymlinks'd repo root, reusing the shape internal/core/launch/bundle.go already uses for symlinked bundle entries rather than adding a third copy. CitationPolicy now takes the repo root and returns a CitationPolicySet carrying both the repo-relative form (for messages, so no absolute path is ever rendered) and the absolute form (for I/O). (2) cfg.Roots had NO containment, and while reading outside the repo was inert for a reporting lint, this intent made the collector feed a live fetcher whose results are persisted into a baseline the workflow expects to be committed and pushed — "roots": ["../private"] therefore fetched and PUBLISHED every URL in a sibling directory. The collector (not the pre-existing lint walk) now refuses an escaping or symlinked root. (3) The wholesale-failure guard consulted res.Preserved == 0, but a preserved receipt was never fetched and so is no evidence the network worked: any repo that had ever run confirm — the designed steady state for robot-refusing sources — silently lost the protection entirely. The guard now reads a new CheckOutcome.Answered bit that the CHECKER sets when a host returned any status line at all. That is the bit StatusBroken was destroying (a DNS failure, a refused connection and a genuine 404 all landed there), and recovering it from a proxy was wrong in both directions — the old condition also made a sole genuine 404 permanently unrecordable, refusing forever with a false "check connectivity". RULE affirmed: when a guard needs a fact, carry the fact, never infer it downstream from something correlated.

  • dcn-26072700000000132026-07-27

    2026-07-27: itd-103 guard wiring — the fail-open-loud shim is a shell wrapper in the plugin's hooks/hooks.json PreToolUse entry (pass through only the binary's own 0/2; everything else warns UNGUARDED and allows), not Go code. The failure it guards against is the Go binary not running at all, so it cannot live in Go. Tested by executing the committed manifest string under /bin/sh against a fake plugin root.

  • dcn-26072700000000122026-07-27

    2026-07-27: itd-103 guard wiring — the two front doors disagree on ONE case by design. A guard that cannot be evaluated (unparsable command, registry that will not load) is a FAULT for guard check (exit 2: a script must never read silence as clearance) and fail-OPEN for guard hook (exit 0 + loud stderr: a broken guard must never stop a session). Rejected: one shared behaviour, which would either brick sessions or teach scripts that silence means safe.

  • dcn-26072700000000112026-07-27

    2026-07-27: itd-103 guard wiring — abcd guard hook is a sub-verb of the USER-facing guard verb, not a fifth entrypoint under the hidden hook subtree. Reason: guard health has to be legible (AC 1), and a hidden adapter documents nothing; the other hook entrypoints are injection transport with no user-facing counterpart, this one is the same decision the user can also ask for by hand. Consequence: it appears in the generated CLI reference and must stay host-agnostic in its prose.

  • dcn-26072700000000102026-07-27

    2026-07-27: itd-103 guard overrides live in dedicated committed .abcd/guard.json, not a rules.json domain — structured entry schema, and the rules kill switch must not silently disable a safety guard (spc-16).

  • dcn-26072700000000092026-07-27

    2026-07-27 — itd-101 part (b) review round settled five more. (1) The committed citation_baseline.baseline config value is CONTAINED at one choke point (lint.CitationPolicy, which now returns an error): a ../../.. or absolute path is REFUSED, never silently normalised, because SaveBaseline MkdirAll's its parent and a contributor controls that file — this was a real arbitrary-file-write primitive found by the security review, reproduced against a built binary. Both writers and both readers resolve through the one check. (2) A refresh run in which NOTHING succeeded is REFUSED rather than committed, and only when a prior baseline existed: Check collapses DNS failure, refused connection and timeout into the same broken as a 404, so a run behind a captive portal would otherwise rewrite every entry as broken — stale human receipts included, since those are re-checked and so not covered by the blocked branch — and the operator would find the gate blocking every commit. A first run over genuinely dead citations has nothing to protect and still writes. (3) An unrecognised Status from a Checker is an ERROR, not a fall-through: the seam is exported for AC 5's adapter, and falling through would drop the URL from BOTH the baseline and the queue — the one outcome nothing downstream could detect. (4) The missing-entry lint message names BOTH verbs: the only state that produces a missing entry is a source refusing automated fetchers, so naming refresh alone sent the maintainer round a loop that cannot terminate — only confirm clears it. (5) A docs-lint config that arms the citation rule but fails to PARSE is reported to the release preflight as Unreadable and REFUSES, distinct from the nil "not armed" state — rendering a broken gate as an absent one would wave a release through on a false statement. Also consolidated: daysBetween is now the exported lint.DaysBetween, called by the verb and the gate alike, because two copies of the staleness boundary is two chances for the verb to call an entry current on the day the gate calls it overdue; and the CLI's ad-hoc citeErrorDetail was dropped for the canonical scrubPaths, which preserves the *PathError type the redactor needs (an absolute developer path was reaching machine output).

  • dcn-26072700000000082026-07-27

    2026-07-27 — itd-101 part (b) settled seven choices spc-17 left open, and consolidated one primitive. (1) The SSRF fetch guard moved from internal/core/memory to internal/urlguard rather than being copied for the second fetch path; its address predicate became a parameter so a fetch path can be exercised against an httptest server (which binds loopback) without the shipped policy ever being relaxed. (2) BLOCKED-FOR-AUTOMATION is classified by status code ONLY — 401, 403, 406, 429 — with no body sniffing for challenge-page markers: a heuristic over page text would be unreliable AND a reason to start reading content, and the challenge pages that matter answer with one of those codes anyway. Everything else non-2xx is broken. (3) One GET per URL, body never read and never retried: liveness is the status line, so a citation to a huge file costs a response header; a retry loop would make a run's duration a function of how many links are failing. (4) A blocked URL with NO prior entry writes NOTHING — the gate then reports it as unreceipted, which is exactly true; recording it broken would put a lie in a committed record the gate enforces. (5) A CURRENT manual receipt is preserved verbatim and not even re-requested; a STALE one is re-checked (AC 3's one clock) and, if the source still blocks, KEPT rather than deleted so the gate keeps warning honestly. Rejected: refetching every manual entry every run (downgrades a human's receipt to a robot's failure), and never refetching them (buys a permanent exemption from ageing). (6) confirm records ALIVE only — it is "I looked and it is there", never a channel for recording a link dead — and takes URLs positionally or a receipt file, both assembling ONE schema so the later generated checklist page is a different producer, not a second pathway. (7) refresh exits ZERO after recording broken links: it records, the gate decides; a verb that failed on a dead link could never write the record that reports it. Also: the release-gate promotion reuses ArmReceiptGate's shape (lint.ArmCitationOverdue, armed by abcd docs lint --release-gate) with the FLAG as trust root, and the abcd launch --dry-run citation gate takes its measurement from the CLI as data because core/lint imports core/launch for its semver — the same shape the cobra-tree walk already uses.

  • dcn-26072700000000072026-07-27

    2026-07-27 — itd-101 part (a) settled four choices spc-17 left open. (1) The committed baseline lives at .abcd/citations-baseline.json, alongside docs-lint.json/record-lint.json/rules.json — it is config the gate reads every commit, not development record; rejected .abcd/development/ (wrong tier) and .abcd/work/ (not a session artefact). (2) A table is a CROSSWALK when its nearest preceding heading matches (?i)crosswalk (configurable) — the narrowest heuristic that selects docs/reference/terminology.md's table and leaves every ordinary directory-map/comparison table alone; rejected column-header and any-table-in-docs identification (both sweep up README.md and docs/README.md tables that carry no citations by design). (3) A page's CITATION CORPUS is its footnote definitions, including wrapped continuation lines — not its prose; a URL in a body paragraph stays links_resolve's business, which is what keeps the syntax and source-policy rules off ordinary text. (4) refused_domains ships EMPTY: the repo states its admission rule in prose ("no single-author coinages, no aggregators", docs/reference/terminology.md + ACKNOWLEDGEMENTS.md) but nowhere names a domain, and the gate must not invent an editorial blacklist the project never agreed. Also: staleness is measured from last_checked for automatic and manual entries alike (AC 3's "same clock"), and the 365-day threshold surfaces as a distinct rule id citation_baseline_overdue at warn — the commit gate never calendar-blocks, so promotion to blocker is the release gate's job in part (b).

  • dcn-26072700000000062026-07-27

    2026-07-27: itd-101 spec minted as spc-16 collided with unmerged #156 (iss-80 class, both spc-N and iss-N allocators); renumbered to spc-17 by hand, duplicate capture folded into iss-80 — ids on this branch deliberately skip 16.

  • dcn-26072700000000052026-07-27

    2026-07-27 — GRILLED itd-101/102/103/104 to settlement (six decisions, each now in its intent's Grill Settlements + acceptance criteria): itd-103 guard fails open loudly, blocker/warn tiers with committed-only overrides, shell-token-aware command-position matching with an itd-81-style TNR-floored corpus; itd-101 refresh is manual-with-nagging (scheduled CI later, own sign-off), staleness warns at 180d and blocks releases at 365d, human verifications age on the same clock; itd-102 identity lives in a parseable markdown block (config points at it), check is warn-tier and never rewrites; itd-104 ideate is an optional verb, never a pre-capture gate, with a fresh-context off-policy adversary. All four drafts are grill-settled and await intent plan.

  • dcn-26072700000000042026-07-27

    2026-07-27 — itd-93 parity tension resolved: Branch A. The scaffold template is the single source for release.yml/auto-release.yml; abcd-cli's live workflows are regenerated from it; the only sanctioned live diff is the additive workflow_dispatch rehearsal (trigger + non-publishing dry-run job). Rejected: substitution-gating the rehearsal off for abcd (weakens the parity guarantee on the one novel component).

  • dcn-26072700000000032026-07-27

    2026-07-27 — ADOPTED the canonical tagline: "A host-agnostic configuration layer for intent-driven development." Canonical identity home is the brief product chapter (01-product README, Identity section: title / tagline / pitch); README strapline, plugin manifest description, and AGENTS.md opening render from it. README's former strapline ("An opinionated, intent-driven development framework for product thinkers") is retired as a surface line; the product-thinker framing lives on in the README body. Rejected wordings: "for agent harnesses" (object shift, host/harness redundancy, plural over-promise), "over any agent harness" (drops the domain). Resolves iss-143; itd-102 generalises the drift check for managed repos.

  • dcn-26072700000000022026-07-27

    2026-07-27 — DEFERRED the row-has-footnote structural docs-lint rule (spc-15 out-of-scope): no existing rule shape covers table-row-to-footnote structure, so it would need a bespoke check; the grill left it optional and the citation-gate intent (itd-101) is now its natural home — implement it there or not at all. Recorded per spc-15's deferral-is-recorded clause; surfaced by the itd-100 fidelity audit's gap check.

  • dcn-26072700000000012026-07-27

    2026-07-27 (salvage): the four 2026-07-13/14 ideation-session entries above are appended out of chronological order — recovered from an unmerged ideation branch during branch cleanup, together with their research/plan docs; the /abcd:ideate seed from that session is re-recorded as itd-104 (its branch-local iss-93 capture id had collided with main's iss-93 and is retired unused).

  • dcn-26072600000000012026-07-26

    2026-07-26 — itd-100 grill settled: crosswalk is a mapping not a registry (no canonical native definitions; gloss-only rows, docs/** links only, pending iss-40); alphabetical + thematic mini-index; footnote citations with per-line docs-lint allow for vendor names; British English. Positions: A2A and AP2/payments both WATCHING (AP2 via new capture — record silent, REJECTS never invented; x402 + OpenAI/Stripe ACP folded into the AP2 footnote); policy engine folded into policy-as-code row; agent skills is the sole REJECTS (brief 08-skills commands-only rule). Rejected-term admissions blessed (agentic workflow, ANP, AGNTCY, Verifiable Intent, harness engineering, ISO 22989-as-HITL-anchor). LinkedIn anecdote omitted from itd-100. Two OpenAI harness URLs await maintainer read before ship.

  • dcn-26072500000000012026-07-25

    2026-07-25 — Record-id collisions across parallel branches (iss-115, iss-120) fixed as a class: one canonical allocator primitive (recordid.MaxAcrossRefs) mints max+1 over the union of the working tree AND every git ref, so a committed id on another branch is seen; git-unreadable-over-a-repo degrades loudly to tree-only, a non-repo mints quietly (no refs to collide). Detection completes the class — a new spec_id_unique record-lint rule via the shared validateIDUnique primitive (ADR ids left out of scope: this directive is iss-/itd-/spc- only). Rejected: id-range leases per programme, mint-at-merge, and non-sequential/hash ids — all trade away human-readable sequential ids without a maintainer mandate. The residual uncommitted-mint window (both branches mint before either commits) is accepted behind the armed detectors on the merged PR union.

  • dcn-26072400000000052026-07-24

    2026-07-24 — Next-run queue reshaped by the grill: the small consequences fold into Track 1 (resolve iss-35; implement iss-122 pinning; amend + promote itd-93 — promotion only, implementation later as its own focused run); the spine stays friction fixes → itd-94 → walk fixes → itd-88. itd-28 implements in the following run against the adapter decision. Queue: plans/2026-07-24-next-run-queue.md (supersedes the 2026-07-18 queue file's pick-up role).

  • dcn-26072400000000042026-07-24

    2026-07-24 — itd-28 gitleaks sign-off: Stage 2 runs through the scanner seam — native patterns are the default engine, gitleaks is the stronger opt-in adapter when the binary is present, and the hook reports which engine ran (loud staging). CI's gitleaks pass stays the authoritative backstop; iss-96 pattern parity folds into the spec. No new hard dependency — adr-22 holds. Rejected: gitleaks as hard local dependency (first adr-22 exception, per-machine install burden); CI-only Stage 2 (secrets reach pushed remote history before CI sees them).

  • dcn-26072400000000032026-07-24

    2026-07-24 — itd-93 design settled in maintainer grill: (a) surface is a launch sub-verb (extends 04-launch; rejected: new top-level verb, ahoy install step, embark-time family); (b) SELF-SCAFFOLD PARITY — abcd-cli's own release workflows are regenerated from the shipped template and a test asserts parity, so the proven pattern and the template are one artifact (rejected: lockstep diff test between two artifacts; frozen verbatim copy); (c) built-in workflow_dispatch REHEARSAL mode — arms the full gate against a simulated roll, publishes nothing; a green rehearsal is the runbook precondition for the first real release; (d) the changelog dated-heading format IS the itd-73 seam — launch ship is one optional producer. Promotes standalone / severity minor, PRD synthesised from the interview (no grandfathering); the 5 seeded ACs stand, amended for rehearsal mode.

  • dcn-26072400000000022026-07-24

    2026-07-24 — iss-122 design: the crosscheck gate gets a committed input manifest (doc list, directions, checker count, prompt hash) with TIERED depth — full depth for feature/breaking releases, Direction-B-only shallow pass for patch. The receipt must echo the manifest hash AND the tier; receipt_gate refuses a receipt whose tier mismatches the release's declared impact. Automated refusal is PROCEDURAL ONLY (manifest/tier mismatch, undispositioned findings); confirmed findings go to the maintainer, whose PROMOTE with recorded dispositions is the gate (verifier-selects-gates- decide). Rejected: hard-blocking on confirmed majors (a stochastic LLM triage could block a release); never-worse ratchet (drift persists; tiers make counts incomparable).

  • dcn-26072400000000012026-07-24

    2026-07-24 — iss-35 resolves: everything it stayed open for is verified shipped (surface_coverage armed as blocker, 16 surface chapters incl. docs/history/version, skills→commands relabel, machine-checked staged Status column, crosscheck wired as release gate). The only residue is iss-122. Decided in a maintainer grill interview this date.

  • dcn-26072200000000032026-07-22

    2026-07-22 — When a brief is agreed upfront, it is a TARGET document; it becomes the state document claim-by-claim, at ship time, because shipping includes the brief row edit (spec-moves-with-the-surface). Unbuilt design lives in intents or under an explicit staged marking — never as unmarked present-tense brief prose. The 95 confirmed discrepancies are that ratchet skipped at scale; the crosscheck is the measuring instrument; promoting the principle to a mechanical discipline is the open follow-up (iss-121, iss-122).

  • dcn-26072200000000022026-07-22

    2026-07-22 — Detector findings are triaged adversarially BEFORE fixing, and the numbers justify it: the full-depth iss35 crosscheck returned 102 discrepancies; independent refuters confirmed 95 and killed 7 (two cross-direction duplicates, two wrong-reality, three legitimately staged/exempt). 93% precision is high enough to trust the detector and low enough that unfiltered fixing would have written seven falsehoods into the record. The refutation criteria are the detector's own exemptions plus adr-5; the refuters re-probe the binary rather than trusting the finding.

  • dcn-26072200000000012026-07-22

    2026-07-22 — A release is a release regardless of path: the clean-cutover manual roll follows the SAME two-commit release-branch shape as a derived ship (the content commit, then a receipts commit carrying the sha-keyed PROMOTE receipts for docs-currency-reviewer and iss35-brief-surface-crosscheck). The v0.4.0 roll landed as one commit with no receipts; the receipt gate refused fail-closed — its first genuine firing, and correct. Recovery uses the workflow's own escape hatch (tag on the receipts commit; content = tag^). Rejected: weakening the required-gates list to unblock the tag — that edits the release contract the whole programme was built to preserve.

  • dcn-26072100000000062026-07-21

    2026-07-21 — A probe walk of a foreign tree must be bounded in three dimensions, not one. itd-95 shipped WalkFiles with a regular-file cap; an independent security review of the itd-96 branch showed both remaining dimensions were exploitable — a tree of directories holding no regular file never reaches a file cap, and os.Root re-resolves each directory from the containment root one component at a time, making a directory chain quadratic in its depth (depth-1500 did not finish in two minutes). Directories are now counted against the same cap and descent is capped at maxWalkDepth. The general rule: any new whole-tree traversal states which of {entries, depth, aggregate bytes} bounds it, because a per-item cap and a count cap multiply and their product is not a bound.

  • dcn-26072100000000052026-07-21

    2026-07-21 — The mapping table's per-tier status columns are a ceiling, not merely a prediction. Every conventions adapter already honours its row (convGlossarySource returns partial where the row says partial; convPlatformSource returns grounded where it says grounded), so itd-95's and itd-96's three new adapters cap at StatusPartial — the value all three rows predict — and carry signal strength in Confidence instead. Rejected: returning StatusGrounded for a dedicated NAMING.md or a prose-bearing ARCHITECTURE.md, which would have made the rendered brief table wrong and required editing mapping.go, the brief-to-lifeboat contract both intents put out of scope. Every acceptance bar asks only for "non-blank", so the ceiling satisfies them. Revisit only by amending the mapping row first.

  • dcn-26072100000000042026-07-21

    2026-07-21 — impact is a KNOWN property of the issue ledger schema, and internal/core/capture validates it against the shared enum in internal/core/changelog rather than a private copy. The back-fill added impact: to every resolved issue, which validateStrict's additionalProperties:false allow-list rejected — abcd capture reported "resolved 0" and skipped all 57 records as malformed. Accepting the field without validating it was rejected: severity/category/source are all enum-checked on read, and a third definition of the impact enum is exactly what spc-10 exists to prevent. capture -> changelog is the import direction (no cycle: changelog imports launch/frontmatter/gitutil only).

  • dcn-26072100000000032026-07-21

    2026-07-21 — launch ship does not tag. It writes the dated ## [X.Y.Z] - <date> heading in the reviewed ship PR; the unchanged auto-release.yml greps it on merge and creates the tag. ADR-37 is preserved, not superseded: the reviewed ship IS the release decision, and the bot-on-main alternative stays rejected.

  • dcn-26072100000000022026-07-21

    2026-07-21 — itd-67's "a phase completed since the last launch -> minor" bump heuristic is SUPERSEDED by itd-73's impact derivation (spc-10). The bump falls out of the records' declared impact, not out of phase membership; spc-11 consumes the derived number and never computes one. Recorded so the two intents do not both claim version selection.

  • dcn-26072100000000012026-07-21

    2026-07-21 — itd-66 (launch-payload-render-parity) is DEFERRED to a follow-up after the derived-versioning + auto-changelog + distribution programme. itd-67's own AC frames its installability smoke as "light … later upgraded to call" itd-66's deep tier, so the split is clean: this programme builds the light tier and positions the surface-resolution seam so itd-66's deep render, .abcd/** leak-proof assertion, symlink resolution, parity diff, and isolated-subprocess deep smoke slot in as a drop-in upgrade rather than a rewrite. Ordering: this programme -> itd-66. Recorded in spc-11's "itd-66 is deferred" section.

  • dcn-26071800000000022026-07-18

    2026-07-18 — Acceptance-criteria sign-off is implicit in a human running abcd intent plan (itd-94): no ac_confirmed frontmatter field, keeping directory-as-truth pure and adding no forgeable schema surface. The gate (abcd intent ready) distinguishes only drafts vs planned; agents are barred from unattended planning at the protocol layer (run-protocol step 0 + /abcd:intent's interview script: plan is never run without the human's explicit in-session confirmation). Escalation path if violations appear: an ac_confirmed_by: field is lint-legal today and slots in as a fifth check.

  • dcn-26071800000000012026-07-18

    2026-07-18 — The iss-35 semantic release gate was self-referential (armed against the tagged commit, read receipts from that commit's own tree) and fail-closed the first public release; fixed in PR #99 by arming with the reviewed content commit (HEAD^2^ / HEAD^) from a full-history checkout, plus a check-reviews.sh RD001 exemption for sha-keyed receipt dirs. The gate is abcd-cli's OWN CI: it is NOT shipped or scaffolded to managed repos (launch-payload.json excludes .github/; ahoy/launch write no CI; lifeboat only reads .github/workflows as a grounding signal), so the flaw had no managed-repo reach — the iss-108 capture's "systemic" framing was corrected on resolve. Any future release-scaffolding intent should scaffold the fixed two-commit (roll -> receipts) pattern, not the original self-referential one.

  • dcn-26071700000000052026-07-17

    2026-07-17 — Release burst (maintainer-directed): adr-37 adopts changelog-driven releases (rolling Unreleased -> dated heading in a reviewed PR IS the release decision; auto-release.yml tags exactly that commit and calls release.yml as a reusable workflow; idempotent, GITHUB_TOKEN-only). Extends adr-31, does not replace it: number derivation stays itd-73's; the interim check is maintainer review of the roll PR. The detect step tolerates the historical [v0.1.0] heading style; new headings use the plain Keep-a-Changelog form. v0.2.0 rolls in the same PR as the port — the automation's first firing is its own acceptance test.

  • dcn-26071700000000042026-07-17

    2026-07-17 — Burst 5 (M5, itd-43/spc-8): GL002 enforces a deliberate subset (['epic']) of the glossary's forbidden_synonyms — the others are common English words whose false-positive rate would sink the gate; each becomes opt-in via .abcd/record-lint.json as the corpus is readied. Two sweep hits inside internal self-quotes (itd-48 quoting a working-log line and spc-12's overview) were swept, not exempted: abcd's own records carry the canonical word even when quoting themselves. spc-8 stays OPEN and itd-43 planned on AC3 (spec-review token), blocked by itd-28's maintainer-gated dependency.

  • dcn-26071700000000032026-07-17

    2026-07-17 — Burst 4 (M4, itd-46/spc-7): quoted-text create shipped; the seeded-draft shape spc-7 defines is canonical (the AC's "byte-identical to intent new" clause is historical — no such Go verb existed). Two intent scope bullets named old-system files with no native counterpart (commands/abcd/intent.md, docs/reference/commands.md) — adjudicated moot in the spec; the missing intent plugin-markdown surface is ledgered as iss-105 rather than silently absorbed. Typo-guard asymmetry vs capture ledgered as iss-104, not fixed (ACs don't require it).

  • dcn-26071700000000022026-07-17

    2026-07-17 — Burst 3 (M3, itd-4/spc-6), three record adjudications: (1) AC2's resolve note lives as the structured frontmatter scalar resolution: (the live setScalarField design), not body-appended prose as the AC letter says — recorded as intentional design evolution, not a gap. (2) AC3 (promote) is a genuine BLOCKED gap: skill-orchestrated by design but uncompletable with today's verbs (no intent-create until itd-46; no engine-backed related_intents back-link write; hand-editing frontmatter from markdown would violate the engine-backed convention) — spc-6 stays OPEN and itd-4 stays planned on it. (3) AC4 migration recorded satisfied-by-history (source absent, ledger populated iss-1..iss-103); no dead migration code built.

  • dcn-26071700000000012026-07-17

    2026-07-17 — Burst 2 (run test B), two mechanics decisions: (1) an already-planned intent with spec_id null (itd-40, created before the lifecycle verbs existed) is routed through a transient git mv planned->drafts so intent plan can mint+link its spec fail-closed — there is no standalone spec-create verb, and hand-authoring a spec file would bypass the mint lock's id allocation; net record churn is the spec_id write. (2) Implementation was delegated to an Opus 4.8 worker (recorded protocol deviation, manual test B); the orchestrator re-ran the gate on the output, and commits carry the trailer of the model that authored them (worker code: claude-opus-4-8; orchestrator record work: claude-fable-5).

  • dcn-26071600000000022026-07-16

    2026-07-16 — M6 synthesis, two plan amendments: the oracle audit is keyed by the lifeboat's manifest hash (audit/oracle-<manifest12>.json), not the plan's wall-clock <ts> (no timestamp ever enters a lifeboat artifact); and _provenance.json is never mutated post-pack — each synthesis artifact self-records its mode (deterministic|delegated) instead of the plan's "_provenance records which" (the commit marker stays immutable). Synthesis outputs (principles, press-release, audit/) join the lessons files outside manifest_sha256.

  • dcn-26071600000000012026-07-16

    2026-07-16 — M5 round-trip closure re-scoped: the plan's literal "re-pack of an embarked repo reproduces the same manifest hash" is structurally unmeetable (coverage/brief/archaeology are identity- and git-derived); ratified instead as (P1) record-derived sub-manifest closure — RecordManifestSHA256 over ADRs, issues, intents, specs, abandoned.json, recorded in provenance as record_manifest_sha256 — plus (P2) literal self-closure into a byte-copy of the source; the packer now carries specs (rescue/specs/) so the spec.Load round-trip assertion is real.

  • dcn-26071500000000022026-07-15

    2026-07-15 (post-M2 gate design) — Graduated to adr-36 and itd-90. The coverage gate raised a lifecycle question the plan implied but never named: the coverage report knows what to ask, but nothing said who answers a blank, when, or where — and the person with the tool (facilitator) is rarely the person with the answer (product thinker). Decision (adr-36): a blank is a durable, fillable object, not a fill-now-or-lose snapshot; answering is decoupled from disembark/embark and runs as its own async, environment-agnostic step over the coverage JSON; blanks carry a kind (extractable = coverage debt abcd can fix, vs human-owned = personas/ mental-model, never derivable and framed as a prompt not a failure — the durable form of the "personas is manual" gate call); and a filled blank is marked authored-by (a person + date), structurally distinct from a grounded section's extracted-from (a file), so an opinion never launders into a fact. Coverage schema grows to v2 (fillable object); mapping.go gains a per-section Kind. itd-90 specifies the product-thinker-facing interview (draft). Boundary: distinct from itd-86 cold-reading (which reviews for contradictions, denied context; the interview answers questions, fed context — opposite direction).

  • dcn-26071500000000012026-07-15

    2026-07-15 (M2 gate — maintainer-approved) — The lifeboat coverage experiment's cross-repo readout is in. Corpus (private repos anonymised): abcd-cli (git+conventions+abcd-native, 21/2/0 grounded/partial/blank), test repo 1 and test repo 2 (abcd-native scaffolding but no authored brief, 4/8/11 and 2/6/15), test repo 3 (git+conventions, no abcd, 3→4/8/11), and a git-only floor (0/2/21). Headline finding: scaffolding is not a record — test repos 1 and 2 carry .abcd/ directories yet ground barely more than the record-less test repo 3, because their .abcd/development/ has no brief/, no ADRs, no issue ledger; the native adapter is honest and grounds only authored prose. The brief structure holds (excluding the dogfood repo, 9 of 23 sections are blank across the messy corpus, not half). Decisions: (1) product/personas is demoted to a human-answered question in the lifeboat brief — the corpus confirms the M0 prediction that it is not derivable from a repository. (2) The other 8 always-blank sections stay in the brief but split: product/mental-model, delivery/verification-matrix, delivery/out-of-scope become human-answered questions; evidence/what-didnt, evidence/open-questions, constraints/naming, glossary, internals are blank more from thin adapters than genuine non-derivability and get adapter work before M3 decides (iss-98, iss-99, iss-100). (3) The dependency-manifest adapter under-detected Python/ Ruby/PHP packaging (test repo 3's pyproject.toml+uv.lock read as blank) — fixed now, so test repo 3's constraints/dependencies grounds. M3 (the packer) builds to this list: grounded/partial sections extracted-and-cited, the human-question sections surfaced as the blanks-with-questions the coverage report already produces.

  • dcn-26071400000000182026-07-14

    2026-07-14 (layout): ADOPTED "default to the local tier when in doubt". An artefact whose home is unclear (tool exports, oracle/review output, traces, intermediate analysis) goes to .abcd/.work.local/scratch/ or logs/ FIRST — never the repo root, never a tracked directory on a guess. Promotion to .abcd/work/ or .abcd/development/ is cheap and always available later; demotion is not, because a wrongly-committed artefact is already in the history. Guessing upward is irreversible; guessing downward costs nothing. Prompted by a RepoPrompt oracle export landing in a top-level prompt-exports/ during this session (moved to .abcd/.work.local/scratch/prompt-exports/). Recorded in AGENTS.md § Working-tree layout, the canonical home, rather than a new doc.

  • dcn-26071400000000172026-07-14

    2026-07-14 (process): TWICE this session a research pass reported a paper as saying something it did not (a fabricated cross-family finding; the non-existent 35.5% figure; and SpecBench described as "deferring" conformance when it scopes code out permanently). RULE: for any number that will be load-bearing in a design doc or paper, open the PRIMARY before citing it. Secondary reporting of benchmark figures has been wrong every time it was checked in this session.

  • dcn-26071400000000162026-07-14

    2026-07-14 (research, CORRECTION — supersedes the two entries above): the SWE-bench figures are now VERIFIED against OpenAI's primary posts, and one claim is WITHDRAWN. The "35.5% of audited tasks demanded implementation details never stated" figure DOES NOT EXIST in the primary — it came from secondary reporting. OpenAI's real taxonomy for SWE-bench Pro (% of full dataset, agent-flagged / human-flagged, read per-bar from the chart's aria-labels): overly strict tests 14.4/17.8; low-coverage tests 4.1/9.4; misleading prompt 6.3/7.5; miscellaneous 1.9/1.2; UNDERSPECIFIED PROMPT 0.6/0.8. Underspecification is the SMALLEST category (~1%); "overly strict tests" is the largest by ~20x. CONSEQUENCE: the pitch "abcd's specs-before-code prevents the underspecification that killed these benchmarks" is aimed at a 1% defect and is DEAD. The surviving claim is stronger and is what the work now defends: SWE-bench's oracle (a merged PR's tests) is authored independently of, and after, the task statement, so it can demand what the spec never said — whereas in abcd THE ACCEPTANCE CRITERIA ARE THE ORACLE, so the oracle cannot exceed the spec. abcd therefore cannot OVER-reject; it can only UNDER-check (the low-coverage failure, 4-9%), which compounds with judges over-accepting AI-written code by up to 1.91x. Claim to defend: "a spec-derived oracle cannot over-reject; it can only under-check — and under-checking is measurable." Verified figures: SWE-bench Verified (2026-02-23) 27.6% subset audited, >=59.4% flawed tests, 138 problems x >=6 engineers; SWE-bench Pro (2026-07-08, retracted) 731-task split, 200 (27.4%) agent-flagged vs 249 (34.1%) human-flagged — the two audits disagree by ~7 points, i.e. automated task-quality auditing UNDER-DETECTS relative to humans.

  • dcn-26071400000000152026-07-14

    2026-07-14 (research, UNVERIFIED): the SWE-bench Pro audit figures (27.4% automated / 34.1% human) and the SWE-bench Verified figures (>=59.4% flawed tests / 35.5% hidden implementation details) come from SECONDARY sources — openai.com 403s to the research fetcher. These numbers are the reference standard the proposed paper is scored against. VERIFY AGAINST THE PRIMARY before writing anything. Do not cite the decimals until read first-hand.

  • dcn-26071400000000142026-07-14

    2026-07-14 (review): ADOPTED splitting the conformance reviewer into a terse binary verdict call and a SEPARATE explanation call. Asking for verdict+explanation+fix in one call drives GPT-4o's false-negative rate from 26.2% to 73.2% (HumanEval) and 35.9% to 87.9% (MBPP) — it does not find more bugs, it REJECTS CORRECT CODE (arXiv 2603.00539, Springer Automated Software Engineering). All five abcd agents currently do the forbidden thing. Largest measured effect size in the research and free to apply. Also adopted: fix-guided verification filter (execute the proposed fix as a counterfactual; if no test outcome changes, the rejection was hallucinated — FNR 54.8% -> 16.3%). Full evidence: .abcd/development/research/notes/2026-07-14-research-platform-benchmarks.md

  • dcn-26071400000000132026-07-14

    2026-07-14 (research): ADOPTED pre-registration of acceptance criteria — hash + timestamp at spec time, BEFORE any code. The novelty claim is that abcd writes the specification before the code exists, which is exactly the defect that killed SWE-bench Verified (35.5% of audited tasks demanded implementation details never stated in the problem) and SWE-bench Pro (retracted 2026-07-08). Without a commitment artefact the claim is unprovable and CANNOT be retrofitted — every intent shipped without it is lost evidence. The primitive exists (receipt_id already hashes the AC section, excluding Audit Notes).

  • dcn-26071400000000122026-07-14

    2026-07-14 (research): REJECTED building an authoritative benchmark from abcd's own data. Three independently fatal defects: (1) the corpus is n=2 labelled triples, both graded by the model that wrote the code, with exactly one NOT_MET; (2) circularity — the system would generate the spec, write the code, judge conformance AND supply the labels, and self-preference appears perplexity-driven so it SURVIVES swapping model family; (3) N=1 has no methodological remedy (Epoch attacks SWE-bench Verified for concentration at 12 repos; we have one). Arithmetic also fails: ~500 oracle-backed tasks needed to resolve model differences, in-situ A/B needs 2,200-15,500 paired observations. CHOSEN instead: a task-quality instrument + methodology, validated against an EXTERNAL reference — OpenAI's 731-task SWE-bench Pro audit. Ground truth must originate outside the tool (executable test or retrospective event oracle, never an LLM judge). Template is Aider polyglot: the tool supplies the harness and distribution; ground truth comes from outside (225 external Exercism exercises).

  • dcn-26071400000000112026-07-14

    2026-07-14 (review): REJECTED per-commit review as the unit. No serious tool does it (all per-PR); findings on WIP commits are false positives by construction; cost is $75-500 per PR-equivalent at published frontier rates. Unit of review is the BRANCH DIFF. Also rejected: spec-conformance as a BLOCKING gate — best agent scores 44.4% on the easier adjacent task (SpecBench) and no precision/recall for implementation-vs-spec is published anywhere. It ships advisory only, per verifier-selects-gates-decide. Full evidence: .abcd/development/research/notes/2026-07-14-cross-model-review.md

  • dcn-26071400000000102026-07-14

    2026-07-14 (review): REJECTED a "super-reviewer" verb gated on a second model backend. Its motivating rationale does not survive: self-preference under genuine authorship is weak or absent (arXiv 2606.20093, gap -5.1pp, CI crosses zero), and the bias that DOES exist on code is a context-framing artefact, not model identity (arXiv 2603.04582). CHOSEN instead: a fresh-context, off-policy, same-model reviewer — re-present the diff in a new session as an artefact of unknown authorship. Captures the only measured debiasing effect, costs nothing, needs no second subscription, and removes the two-tier UX problem entirely. A second model, when present, is used for disagreement-as-triage per adr-25 asymmetric trust and itd-81 — NEVER a panel or a vote (nine judges = 2.18 effective votes; on code, consensus underperforms the naive baseline — the "popularity trap", arXiv 2510.21513).

  • dcn-26071400000000092026-07-14

    2026-07-14 (M1, iss-95 — maintainer decision) — The store-not-bootstrapped case is made LOUD, not self-bootstrapped by the hook (rejects having hook session-end create ~/.abcd/history/, which would put a dir-creating trust-boundary act inside a fail-closed hook and contradict the ownedDirsReal symlink discipline). Reality check: ahoy install ALREADY bootstraps the store (bootstrapHistory, plus the per-repo transcripts dir), and detection ALREADY emits history.bootstrap_missing as a required gap that bare abcd, ahoy, and ahoy doctor surface — so an installed user is never in the silent state. The only genuinely silent path is the SessionEnd hook itself, which by harness contract has NO output channel (its exit code and stdout are ignored), so it cannot speak at session end. "Loud" therefore lives where a channel exists: a SessionStart notice (SessionStart hook output is surfaced) that warns once when the store is absent, pointing at /abcd:ahoy install. Scoped as an M1 follow-up; keeps the hook fail-closed-silent and moves the loudness to the one event that can be heard.

  • dcn-26071400000000082026-07-14

    2026-07-14 (M1) — iss-95: wiring the hook does NOT by itself start the clock. history. Capture requires ~/.abcd/history/<root-sha>/transcripts/ to already exist and deliberately never creates it (the ownedDirsReal symlink-safety discipline); ahoy install bootstraps it. On a machine where install has not run — INCLUDING THIS ONE, where ~/.abcd/ does not exist — hook session-end fails closed, logs to stderr, exits 0, and captures nothing, silently. That is exactly itd-89's failure mode (a hook that looks wired while the corpus never accrues). Decision owed: hook self-bootstraps (changes Capture's precondition and has the hook create dirs, which the symlink discipline avoids) vs. ahoy install stays the sanctioned bootstrap and the not-installed case is made LOUD (ahoy doctor already flags history.bootstrap_missing). iss-96 records the adjacent point: automatic capture makes the scanner's secret-pattern coverage load-bearing — it catches anchored tokens (AKIA…, ghp_, sk-ant-) and home paths but not unanchored high-entropy values (a bare 40-char AWS secret, a prefixless token), so consider entropy detection or the gitleaks adapter for the transcript path.

  • dcn-26071400000000072026-07-14

    2026-07-14 (M1, itd-89/spc-4) — Transcript capture is wired to SessionEnd, NOT the Stop the plan specified. The plan's letter was wrong on a matter of harness fact: Stop fires once per assistant TURN, and Claude Code's transcript file grows through a session, so a Stop-wired capture stores a fresh, larger superset every turn — proven by live test (one session, 4 turns → 4 records; a 100-turn session → 100 records and O(N²) bytes). history.Capture's sha256 dedup only collapses byte-IDENTICAL re-captures, which never happens on a live transcript, so the plan's "re-capture is idempotent" acceptance is false under Stop. SessionEnd fires once at termination and by contract ignores exit code + stdout — a perfect fit for a fail-closed, non-blocking side-effect hook. Verified against the harness docs (code.claude.com/docs/en/hooks). Accepted cost, recorded not hidden: SessionEnd does not fire on a hard crash/SIGKILL, so an uncleanly-killed session is not captured; the Stop-with-session_id-dedup alternative that would recover that case needs a change to shipped core dedup semantics and is deferred. This is the M1 deviation the loop is required to surface.

  • dcn-26071400000000062026-07-14

    2026-07-14 — iss-93: adr-35 promises disembark is READ-ONLY over the source (a test hashes the tree before and after), but two paths in the design still write into it — Pass-0 dev-sync (.abcd/work/reviews/, .abcd/memory/, .abcd/work/issues/) and the backgrounded-execution checkpoint (.abcd/logbook/disembark/<ts>/_state.json). Either they move out-of-tree (under <dest> or the operator-level voyage) or they leave the disembark path entirely. adr-35 does not settle it; the decision is owed before the packer ships, and the read-only test is what will force it.

  • dcn-26071400000000052026-07-14

    2026-07-14 — adr-35's blast radius across the record was FAR wider than the plan anticipated, and the line drawn is: the brief, glossary and roadmap are reconciled; the intent corpus is NOT. An adversarial review (four hostile lenses, every finding independently verified) found the first pass had rewritten the vocabulary registry to the new model while ~14 other files still asserted the old one as fact — including an INVARIANT (03-invariants.md #6), the product's own press release, the verification matrix (which encoded adr-4's .bak overwrite as a TEST GATE), and the lint-enforced glossary SSOT. A registry contradicting an accepted ADR is drift of exactly the kind iss-35 exists to prevent, so all of it was swept. The INTENTS (itd-2/8/9/10/13/15/19/22/24) were deliberately left alone and tracked as iss-94: an intent is a proposal with its own lifecycle, and silently rewriting nine of them inside an unrelated change is worse than recording the drift — each reconciles when it is next planned. Where adr-35 genuinely does not settle a question (where embark scan searches now that destinations are operator-chosen; what the /abcd status board reads now that there is no in-tree lifeboat to stat), the text carries an explicit Open question (adr-35) note rather than an invented answer.

  • dcn-26071400000000042026-07-14

    2026-07-14 — Vocabulary registered in 02-constraints/04-naming.md, fulfilling a claim adr-4 made and never kept (voyage/, manifest_sha256, _provenance.json, history.jsonl were absent from the registry). Added with them: coverage.json, graveyard/, and two new controlled enums — coverage status ∈ {grounded, partial, blank} and source tier ∈ {git, conventions, abcd-native}, both with the Go enum named as the machine-readable source of truth. The brief's "sufficient" oracle verdict — a member of NO registered enum — is retired in favour of the registered {SHIP, NEEDS_WORK, MAJOR_RETHINK}; no third verdict family is minted (four brief locations).

  • dcn-26071400000000032026-07-14

    2026-07-14 — The brief↔lifeboat mapping table now EXISTS. 00-meta.md has always called it "the contract" while no such table existed anywhere (found by the 2026-07-06 plan-consistency review). It lands as Go — internal/core/lifeboat/ mapping.go is the single source of truth — and is rendered into 00-meta.md between generated markers, with a test asserting the two agree so the document cannot drift from the code. It is framed as the experiment's HYPOTHESIS, stating the best status each brief section could reach at each source tier, in the SAME three-valued vocabulary the probe reports (grounded/partial/blank) so prediction and evidence are directly comparable. M2 is expected to revise it. A monotonicity test (a richer tier can never ground a section worse than a poorer one — tiers are CUMULATIVE) caught a real error in the first draft of the table.

  • dcn-26071400000000022026-07-14

    2026-07-14 — adr-4 SUPERSEDED by adr-35 and pruned per the ADR convention (superseded ADRs are pruned; git preserves the text; the successor carries the transition rationale). What survives is restated in adr-35: the lifeboat is regenerable output, and the lifeboat(noun)/voyage(verb) distinction is load-bearing. What changes: disembark is READ-ONLY and OUT-OF-TREE (a test hashes the source tree before and after), and voyage/ moves to the OPERATOR level (~/.abcd/voyage/<source-root-sha>/, keyed like the history store). The voyage move is not cosmetic — voyage records absolute source paths, and the privacy-hygiene audit rule (itd-85) flags those in committed files, so abcd would have failed its OWN audit. adr-4's overwrite-with-.bak model is replaced by a destination safety gate (never overwrite a directory abcd did not produce); its shared_with field is dropped (nothing produces it, and an empty field is a lie in a schema); and its hash chain — asserted but never defined — is pinned. Nine inbound references repointed by hand (2 links, 7 prose/frontmatter).

  • dcn-26071400000000012026-07-14

    2026-07-14 — The lifeboat is built as a COVERAGE EXPERIMENT, not a feature (adr-35, itd-88/spc-3). Probe before pack: disembark probe <repo> produces a cross-repo coverage aggregate BEFORE a packer exists, because the brief's structure is an untested assumption and building the packer first assumes the answer. The headline number is the delta in section coverage between a rich-record repo and a git-only one — that is what the record is worth, and if half the brief is permanently blank everywhere, the structure is wrong and we learned it for one milestone instead of a phase. Phase 6's "depends on every prior substrate being native" rationale was checked against the BINARY and found mostly false (spec engine ships; reviews are committed markdown; backgrounding is a host affordance; the itd-2 host-delegation seam already ships twice — memory's --pages-json and intent review ingest --verdict-json). The ONE real dependency is data, not code: ~/.abcd/ does not exist, history.Capture is called by nothing, and Pass B's corpus cannot be obtained retroactively — the only permanent, compounding cost on the board, which is why the transcript hook ships ahead of any lifeboat code. Rejected: building the packer first (assumes the answer); amending adr-4 in place (two of its three operative claims change — a replacement, not a clarification).

  • dcn-26071300000000132026-07-13

    2026-07-13 (attribution): DEFERRED the ACKNOWLEDGEMENTS entry crediting the cold reading to abcd's co-author, pending confirmation of how they wish to be credited. Held loudly (stated in the method note), not silently; it must land before itd-86 ships. Do NOT guess the credit line.

  • dcn-26071300000000122026-07-13

    2026-07-13 (itd-86/87): recorded the two intents TOGETHER because they are coupled, not merely related — a blind cold reading re-raises old tensions by design, so pointing it at a ledger that dedupes them yields a detector fighting its own store. itd-87 is the precondition that makes itd-86's re-raising useful.

  • dcn-26071300000000112026-07-13

    2026-07-13 (sensemaking method): recorded the ABCD method (cold reading / warm ledger / disposition) as a research note — the parent that itd-27, itd-42, itd-55, itd-86 and itd-87 had all been accumulating under without one. Minted exactly ONE principle (recurrence-is-signal) rather than one per method element: the cold/warm split is already stated by evaluator-outside-the-loop and verifier-selects-gates-decide, and one-canonical-primitive forbids a third near-copy. Recurrence was the only element with no counterpart in the record. REJECTED minting a read-it-cold principle for the same reason.

  • dcn-26071300000000102026-07-13

    2026-07-13 (itd-85 M7): acknowledged repolinter (rule schema) and Conftest (severity/exit vocabulary) in ACKNOWLEDGEMENTS now, since both are actually adapted in the shipped audit engine. DEFERRED the SARIF acknowledgement to P3: the serializer seam is shaped for SARIF but no SARIF is emitted yet, and the convention is to credit a pattern in the change that lands it, never ahead. Add the SARIF entry when the --format sarif serializer ships.

  • dcn-26071300000000092026-07-13

    2026-07-13 (itd-85 M3): privacy-hygiene reads tracked files through os.OpenRoot (repo-root containment), not os.ReadFile. A leaf-only O_NOFOLLOW is insufficient — a symlinked INTERMEDIATE directory still escapes; security review PoC-confirmed an out-of-repo arbitrary read. os.Root refuses any escaping component. Plus O_NONBLOCK (FIFO/device non-blocking open) + IsRegular skip + 4 MiB size cap. Requires go 1.24+ (repo is 1.25); no new dependency.

  • dcn-26071300000000082026-07-13

    2026-07-13 (itd-85 M3): three-tier-layout does NOT require .abcd/.work.local/ to be present (diverges from the plan's literal "present and gitignored") — it is created on demand and a fresh clone has none; requiring presence would flag every clean checkout. The load-bearing assertion is "if present, gitignored". Mechanics revision, premise intact.

  • dcn-26071300000000072026-07-13

    2026-07-13 (itd-85 M3): docs-currency emits every finding at warn, downgrading docs-lint blockers, because audit is an advisory conformance surface and the authoritative docs gate is abcd docs lint (still exits 2 on a blocker). Re-raising a docs blocker as an audit error would double-gate the same check.

  • dcn-26071300000000062026-07-13

    2026-07-13 (itd-85 M3): privacy-hygiene uses a deterministic, identity-INDEPENDENT absolute-path regex, NOT the identity-aware scanner (internal/adapter/scanner). Rejected the scanner because its home-path detection is identity-PARAMETERISED (kindHomeSelf=hardfail vs kindHomeOther=warn) — machine-dependent severity — whereas AC3's contract is "ANY absolute local path is an error", deterministic across machines. The scanner also scans the release BUNDLE (a curated allowlist excluding tests); audit scans all tracked files, a scope the scanner was not built for. Flagged for future consolidation: absolute-home-path detection now lives in two predicates (scanner identity matchers + audit regex); a later phase should extract a shared identity-independent path matcher.

  • dcn-26071300000000052026-07-13

    2026-07-13 (itd-85 M2): audit engine uses severity vocabulary error|warn|off (repolinter/Conftest), NOT the record-lint engine's blocker|warn, because it maps directly onto the tri-state exit code (error->2, warn->1) and reads right in a human render. Reused docs-lint findings (blocker|warn) get mapped to error|warn at the docs-currency rule boundary in M3, not in the engine.

  • dcn-26071300000000042026-07-13

    2026-07-13 (itd-85, carry to M3): gitutil.CheckIgnored fails OPEN — git absent or not-a-repo returns "nothing ignored". The three-tier-layout rule MUST treat an empty result as "cannot tell", never as "compliant", or a repo with git unavailable silently passes the "is .abcd/.work.local/ gitignored" assertion. Security review flagged this as the one consumer-side spec note.

  • dcn-26071300000000032026-07-13

    2026-07-13 (itd-85 M1): kept core.exists (bool-only, swallows errors) and ahoy.fileExists (regular-file-only) as-is rather than folding all three exists copies into fsutil.Exists. Chose partial consolidation over the plan's full-consolidation because the other two hold different contracts; merging them would smuggle a behaviour change into a behaviour-preserving refactor. Only lint.fileExists (identical fail-closed contract) migrated.

  • dcn-26071300000000022026-07-13

    2026-07-13 — abcd audit (itd-85): a new read-only repo-conformance verb, distinct from ahoy doctor (doctor = tool-setup health, audit = does-the-repo-conform). Bespoke on internal/core/lint (adapt repolinter's rule-schema vocabulary + Conftest severity/exit codes + SARIF as an optional export), zero new deps → no dependency gate. v1 = five rules (three-tier-layout, conventions-router, decision-durability, docs-currency, privacy-hygiene); SARIF deferred to P3; wires into prepare-this-repo Phase 2, closing iss-86. SOTA-researched in plan 2026-07-13-abcd-audit-verb.md.

  • dcn-26071300000000012026-07-13

    2026-07-13 — Auto-merge is permitted ONLY to a non-protected trunk, gated on a SHIP review verdict (not merely green CI) + lint/smoke + an audit entry; never to main (explicit human abcd spec ship promotes). A bounded, opt-in reversal of the standing "a human merges" default — safe because the merge target is staging, not the protected branch, and the gate is a verdict, not a checkmark (green CI shipped a real leak during the 2026-07-12 drain; a security review then HELD it). Record homes: experience → itd-29 (already scoped, deferred v2); enforceable form → a brief invariant + an ADR when built, not now (capture-now-build-later). SOTA is itd-29's (GitHub-native auto-merge, host-owns- git, no new dep); the ADR inherits it. Surfaced the facilitator-default-thinker-optional principle.

  • dcn-26071200000000082026-07-12

    2026-07-12 — The four personal reviewer agents (ruthless, security, docs-currency, sota-researcher) MOVED from the machine-global ~/.claude/agents/ into abcd's plugin agents/ and deleted at source; they now resolve as abcd:<name> in every repo with the plugin enabled, versioned in-repo and reviewable by PR. Frontmatter key is prompt_version (itd-5's name), not version — intent-fidelity-reviewer renamed. Colour encodes the DOMAIN EXAMINED, never rank or taste: red=trust boundary, orange=code correctness, blue=documentation truth, green=the record, purple=external evidence; cyan reserved for artefact-producing (non-verdict) agents. Accepted cost: the reviewers no longer resolve in repos without abcd installed.

  • dcn-26071200000000072026-07-12

    2026-07-12 — itd-5 AMENDED (not superseded) per itd-81, two rules: (a) the v1.0.0 pre-flight's "shorter by >10%" tiebreak is STRUCK — length selects for ACE's brevity bias, and it selected against goldens that never measured false positives; the gate is now the calibration-corpus score, ties to the candidate. (b) 1.0.0 now MEANS measured — an agent stays in the 0.x band until it clears a corpus, because stamping 1.0.0 on an unmeasured prompt asserts a lock that never ran. All five shipped agents are 0.1.0.

  • dcn-26071200000000062026-07-12

    2026-07-12 — Judge calibration captured as a DISCIPLINE (itd-81), not a standalone intent: verdict-rendering agents are plumbing (no user moment), and itd-5 is the precedent for a cross-cutting rule over agent prompts. Core rule: no judge ships unmeasured — a labelled corpus with known-good cases ≥40%, scored on true-negative rate as a first-class metric alongside recall, with a declared TNR floor gating the prompt lock. Evidence: LLM code judges systematically over-flag and ~1/3 of their errors are hallucinated code (2603.00539); judges over-rate LLM-written and under-rate human-written code (2507.16587); ground truth is manufactured by injecting defects (CriticGPT 2407.00215). CORRECTS itd-5: its pre-flight tiebreak ("passes goldens AND >10% shorter") selects for the brevity bias that ACE (2510.04618) identifies as destroying instruction quality — struck; the gate is the corpus score. CONSTRAINS itd-64: reviewer verdicts are not ground truth (the reviewer is the instrument under measurement) and its tuning loop must stay human-gated — unattended proxy-optimisation reward-hacks at 73.8% (OpenReview ikrQWGgxYg). Rejected: judge panels/juries (nine judges → 2.18 effective votes, correlated errors, no better than the single best judge — 2605.29800); 1-5 severity scores (middle-drift, position bias); reasoning inside a JSON schema (2408.02442).

  • dcn-26071200000000052026-07-12

    2026-07-12 — autonomous-run surface named /abcd:run, taking itd-29's reserved name as the host-delegated realization of its operator surface (not a parallel /abcd:loop). Discovery: itd-29 (autonomous-run-resilience, planned) already owns this surface over the ADR-27 run seam, already scopes out-of-band-merge/chain reconciliation (host-owns-git MVP → future read-only abcd run reconcile --json) and 429/quota (spc-35), and is deliberately deferred pending real evidence (revisit trigger #5: two end-to-end autonomous runs). Sequence C→A: run the loop as a plan+protocol under the harness loop now to dogfood + generate that evidence; formalize commands/abcd/run.md + brief row + surface_coverage, reconciled into itd-29, after 1-2 successful runs. Binary operator verbs (budget preflight, rewind, ship, run reconcile) stay deferred in itd-29.

  • dcn-26071200000000042026-07-12

    2026-07-12 — /abcd:auto-loop design recorded (plans/2026-07-12-abcd-auto-loop-skill.md, pending sign-off, not built). SOTA pass (sota-researcher, primary sources) backs the design: durable handoff + fresh-context resume over compaction/RAG (Anthropic long-running-harnesses — compaction "isn't sufficient"); delegate reads/reviews but keep implementation in ONE agent (Cognition "Don't Build Multi-Agents" + Anthropic multi-agent — converging read/write boundary); reviewers must be a SEPARATE fresh- context lens, not intrinsic self-review (Huang et al. 2310.01798; CriticGPT 2407.00215); gate irreversible actions on action-class not self-confidence (RLHF miscalibration); attempt-journal lineage = Reflexion (NeurIPS 2023) + database WAL. Rejected: parallel multi-agent implementation, compaction-as-primary-continuity, RAG-over-ledger at single-milestone scale.

  • dcn-26071200000000032026-07-12

    2026-07-12 — iss-30 (memory ingest boundary) partially resolved: the fetch/read subset — C12 (HTTP status), P11 (SSRF NAT64/6to4), C13 (local size cap), the ~user tilde mangle — landed in PR #38. iss-30 stays OPEN for its remaining instances (the larger "ingest test-suite" effort): the --keep-original partial-failure reporting, CRLF parser-parity (parseFrontmatter vs splitFileFrontmatter), and broader URL-ingest/content-type/PDF path coverage.

  • dcn-26071200000000022026-07-12

    2026-07-12 — iss-66 rules-loader trust boundary. Fixed the two mechanical items: the Load Lstat→ReadFile TOCTOU on .abcd/rules.json (now open-once O_NOFOLLOW + fstat, C19) and the session-state dir moved off the world-writable shared /tmp to the per-user cache dir (P14). P15 document-accepted, NOT changed: a per-repo .abcd/rules.json can set a default domain dormant and flip the global kill switch (Merge is intentionally per-field + sticky-kill-switch). Rationale: rules are an opt-in, opinionated-but-overridable config layer; .abcd/rules.json is a committed file (editing it needs repo write access, like any committed guardrail), and the real enforcement of dangerous actions is harness-level (git-guardrails hooks, the iss-62 identity gate, pre-commit), not the injected advisory prose. Silencing a domain removes prose, not a hard gate. Deferred design alternative (surfaced, not taken): introduce a protected "guardrail" domain class that a per-repo override cannot set dormant and that the kill switch cannot silence — this adds a new protected-domain concept to the rules contract, a maintainer decision, not an autonomous change.

  • dcn-26071200000000012026-07-12

    2026-07-12 — clean-slate hardening run STEP 0 triage. A fresh adversarial sweep (15 ruthless + 9 security reviewers over current main, every finding independently verified) returned 34 real findings (19 CONFIRMED, 15 PLAUSIBLE, 0 REJECTED; full corpus .abcd/.work.local/logs/clean-slate-run/sweep-findings.json). Key result: the sweep INDEPENDENTLY RE-CONFIRMED the 2026-07-08 review's code-defect backlog (iss-29/30/32/33/34) is real and still unfixed — prior runs deferred those code fixes for docs-reconciliation (iss-35/36) and itd-80 feature work. Draining them is this run. Two BLOCKs found: the scanner serialises a finding's snippet masking only its own token, leaking sibling secrets on the same line (iss-65). Triage disposition: newer-package findings (scanner, rules, intent, spec, frontmatter, lint receipt-gate, capture concurrency, core) minted as iss-65..72; older-package findings map to existing homes — memory ingest (C12/C13/P11)→iss-30, atomic-write/fsutil (P1/P6/seed2)→iss-32, ahoy install (C2/C3)→iss-33, launch glob panic (C11)→iss-34, identity fail-open (C8/P12)→iss-63, history redaction (C6/C7/P2)→iss-29. iss-70's C16 fix adds policy.detector to the receipt-JSON schema — a record-lint CONTRACT change flagged for maintainer sign-off before landing (a STOP-adjacent design surface). Ledger triage committed to main as a chore: record commit (matches prior record-to-main practice; keeps the fix branches clean); each code fix lands on its own auto/* branch + PR.

  • dcn-26071100000000072026-07-11

    2026-07-11 — spc-N minting rule for slice 1: max(N over spec-store files ∪ N over every intent's spec_id) + 1, so the first mint is spc-2 (itd-3's reserved spc-1 is respected without a backing spec file). Reconciling the store's sequential minting with the brief's aspirational spc-numbering is deferred to the richer spec-store slice. Reviewer roles 2/3 (itd-48), loop-to-acceptance (itd-50), bundle/discipline lifecycles, and the spec dependency graph are all explicitly deferred.

  • dcn-26071100000000062026-07-11

    2026-07-11 — Intent-lifecycle slice 1 (build sign-off given): the pipeline is dogfooded — itd-3 stays shipped as the reference fixture (option b), and a new tightly-scoped intent itd-80-intent-lifecycle-automation (ACs = the steel thread) is the pipeline's first real payload, driven drafts→planned→ shipped through the machinery it specifies. Slice scope: minimal native spec store (internal/core/spec, directory-as-truth open/closed, intent: link), abcd intent (plan/link/review-ingest + bare render) and abcd spec (close + bare render) verbs, deterministic reconcile inside spec close (no vendor event), host-delegated intent-fidelity-reviewer markdown agent (Role 1 only) + async outbox/inbox verdict ingest to ## Audit Notes.

  • dcn-26071100000000052026-07-11

    2026-07-11 — itd-3 shipped manually ahead of the intent-lifecycle pipeline. Moved planned/ → shipped/ by hand with spec_id: spc-1 (reserved — the future native spec store adopts spc-1 for itd-3, never re-mints it) and a hand-authored ## Audit Notes (the intent-fidelity-reviewer agent does not exist yet; judge = Claude Opus 4.8). Rollup 3 MET / 1 MET_WITH_CONCERNS / 1 INCONCLUSIVE / 1 NOT_MET; every divergence is a signed-off D1–D4 delta, the one gap is the AC6 legacy-harvest completeness. Inbound links repointed planned→shipped by hand — the link-drift-on-move the future reconcile pass automates.

  • dcn-26071100000000042026-07-11

    2026-07-11 — itd-3 rules-loader design signed off (plan 2026-07-11-itd-3-rules-loader.md, prefer-sota verdict). Surviving shape: a transport-agnostic internal/core/rules capability with two front doors (abcd rules [domain] verb + abcd hook prompt-router), not an adapter seam. Four intent deltas approved: D1 event-driven refresh on SessionStart(compact) (fixed-N demoted to a ~15–20 backstop, not primary); D2 keep the shipped {schema_version,disabled,domains{}} shape (legacy extends/overrides sketch superseded); D3 zero model-facing tokens on no-match + out-of-band diagnostic log (supersedes the "<200-token header" acceptance criterion); D4 .abcdignore rejected for v1. Build proceeds phased/TDD from Phase 1 (internal/core/rules).

  • dcn-26071100000000032026-07-11

    2026-07-11 — itd-3 rules-loader hook is Go, not Python. abcd is Go-only, so the UserPromptSubmit router is a Go subcommand invoked by hooks/hooks.json — the intent's hooks/prompt_router_hook.py is a stale pre-Go-rebuild detail and is superseded. No Python is added for the loader.

  • dcn-26071100000000022026-07-11

    2026-07-11 — iss-35 graduation SIGNED OFF (maintainer, 4 decisions): (1) Graduation = Option C (hybrid) — build the deterministic surface_coverage record-lint rule AND wire the LLM cross-check as a standing release gate for semantic (Direction-A) drift. (2) docs/history/version = user-facing surfaces — each gets a 04-surfaces/ chapter + README row (resolves adjudication item 5). (3) consult/ingest/prepare-this-repo reclassify skills → commands via relabel — they stay host-delegated markdown workflows (no Go verbs; the "host-delegated by default" boundary holds), but the brief calls them commands with command-shaped homes; the read-only skill boundary rule is kept as-is — the skill classification was what gave (resolves adjudication item 6). abcd ships zero skills again. (4) Push/merge policy — the run's blanket "never push" was an unattended-safety override, not the standing rule; normal repo policy resumes when the maintainer is driving (docs/chore direct-to-main OK; feat/fix via PR awaiting their merge). Main pushed to origin; auto/context-status-lint opened as PR #12 (awaits maintainer merge; no auto-merge on a feat).

  • dcn-26071100000000012026-07-11

    2026-07-11 — iss-35's brief↔surface cross-check is bidirectional, but only the structural half is deterministically lintable: Direction B (every commands/+skills/ entry has a brief home) is a coverage lint like directory_coverage; Direction A (brief claims match binary behaviour — flags, exit codes, schema fields, counts) is irreducibly semantic and stays an LLM/agent job (encoding binary facts into the linter just moves the drift). So "graduate the detector to a record-lint rule" is a reshaping (extract the deterministic half; keep the semantic half as a periodic/agent check), not a port. The graduation is a design gate held for maintainer sign-off — options in .abcd/development/plans/2026-07-11-iss35-record-lint-graduation.md (recommend Option A, structural surface_coverage rule) — and it is blocked until the docs/history surface-taxonomy adjudication is decided (a coverage rule fires on the three chapterless shipped verbs the moment it is armed).

  • dcn-26071000000000062026-07-10

    2026-07-10: Repo preparation is a plugin skill (/abcd:prepare-this-repo), superseding the external scaffold-repo script's entry point. Grilled rulings: the committed AGENTS.md working-conventions section is full-inline and NAMELESS (a pre-public repo name never lands in target repos) between dated markers for later tooling; the skill hard-refuses not-owned repos (no audit, no local layer — we don't impose our principles on others' repos); legacy root .work/ layouts migrate propose-then-sign-off, never leaving two working-state homes; no re-run/update machinery now — the CLI will own managed-repo migration (gaps seeded as iss-84/iss-85, originally minted as duplicate iss-56/iss-57). Rejected: a standalone handover prompt file (drifts, unversioned); naming abcd in private-only target repos (two-class rule someone eventually gets wrong).

  • dcn-26071000000000052026-07-10

    2026-07-10 — CONTEXT.md goes status-free: it keeps orientation and the live sharp-edges list only; hand-written phase/status claims are banned (extending adr-5's no-status-in-design-docs rule to the work tier) and a record-lint rule on .abcd/work/CONTEXT.md is the detector, armed before the rewrite per fix-the-detector. The content rewrite rides with iss-35's brief-vs-surface reconciliation. Rejected: deleting the file (loses the only committed shared home for sharp edges); generating it (a committed generated file is its own drift problem).

  • dcn-26071000000000042026-07-10

    2026-07-10 — AI-generated-only ("tainted") proposals are recorded as hypotheses and never adopted until independently verified against a citable source — the manual form of tier-travels-with-the-source (iss-52).

  • dcn-26071000000000032026-07-10

    2026-07-10 — Public sources whose titles collide with locally-banned private names are cited by author + arXiv/DOI identifier, never by title or corpus key, in committed artifacts; the corpus ledger carries the real key. First instance: Tan et al. (UCL, 2026; arXiv 2604.09581).

  • dcn-26071000000000022026-07-10

    2026-07-10 — Doctrine grows on observed need: the 31 deferred medium proposals from the extraction stay parked in the 2026-07-09 research note until a live instance arises; calibrate-the-judge deliberately waits for the first live LLM gate (its measured-agreement requirement is already recorded in verifier-selects-gates-decide's promotion path).

  • dcn-26071000000000012026-07-10

    2026-07-10 — The practice/MVP/tool trichotomy lands as an amendment to the principles README promotion path (one canonical three-rung ladder: principle -> enabling convention/script/format -> discipline-kind intent or core absorption), never as a third doctrine file — the adversarial review found standalone adoption would duplicate and contradict existing doctrine. Intake rules kept verbatim: articulate the full ladder for every candidate; never fabricate an absent rung (research/notes/2026-07-09).

  • dcn-26070800000000152026-07-08

    2026-07-08 — Post-review recording follows fix-the-detector: findings are captured as clustered issues (iss-29..49), each naming the detector (gate, lint rule, or test convention) that catches its class and carrying its instances as the detector's acceptance corpus; instances drain behind the armed detector, never hand-fixed ahead of it. Ten principles recorded from the 2026-07-08 multi-agent review; distillation in research/notes.

  • dcn-26070800000000142026-07-08

    2026-07-08 — itd-37's itd-36 edge downgraded blocked_by → builds_on: the capture + enforcement half ships independently (Phase 0 registration) and only extraction-to-memory waits on itd-36 (iss-18); the launch deepenings' unscheduled state is recorded in the phase index pointing at adr-33 (iss-20); itd-6 stays planned/ — ADR-25 superseded its framing only, and scheduled implies planned per adr-34 (iss-22).

  • dcn-26070800000000132026-07-08

    2026-07-08 — Predecessor spc-N artefacts inside intents (do-not-implement banners, implementation-complete AC tables) are demoted to Prior Art design input per the delivery-state provenance doctrine — never implementation authority, never a delivery claim (iss-16 itd-66, iss-17 itd-50); their deltas become spec-time Open Questions.

  • dcn-26070800000000122026-07-08

    2026-07-08 — Severity ≠ priority (records an earlier-session decision): intents declare severity (capture-ledger enum) and edges (blocked_by, builds_on); effective priority is DERIVED via priority inheritance (max of own severity and severity of everything transitively blocked) and never stored — a minor blocker of a major intent jumps the queue while staying minor. Phases keep sequencing authority (adr-9); lint makes contradictory schedules fail. Recorded as itd-78; piloted on itd-76/77.

  • dcn-26070800000000112026-07-08

    2026-07-08 — Corpus restructured to class-segregated per-source folders (confidential/<key>/, public/<key>/): confidentiality is declared at ingestion and LOCATION is its single source of truth (flag mirrors, tooling refuses on mismatch); derived artifacts inherit by location; declassification is a visible git mv.

  • dcn-26070800000000102026-07-08

    2026-07-08 — Author bans FLIPPED to opt-in (ban_authors: true), superseding today's default-on decision: the actual corpus population (own submitted work, purchased reports, private repos) makes author bans near-pure false positives — they would ban the user's own name — while title/alias patterns carry the real protection.

  • dcn-26070800000000092026-07-08

    2026-07-08 — ~/.abcd/ blessed as abcd's user-level home (fourth tier, additive to repo .abcd/), path configurable; relocation wizard recorded as itd-77.

  • dcn-26070800000000082026-07-08

    2026-07-08 — itd-76 grilled: leak guard promises literal strings only (paraphrase risk stated, handled behaviourally + review); citation is a two-level AND (source permission_status AND per-line cited_publicly); author bans default on with per-source ban_authors opt-out; standalone source domain (itd-16 a possible backend, not a dependency); pre-commit auto- refreshes the generated banlist; public render proven by structural filter AND post-render lint; team share of citation data via committed .abcd/work/references.json (share/ingest); durability = machine backup + git bundle, multi-machine deferred.

  • dcn-26070800000000072026-07-08

    2026-07-08 — Edges stay one-way (dependent-authored), reverse views derived only; itd-78 lint rejects hand-authored reverse fields; edges gain optional content fingerprints (itd-N@hash) so a target's change marks inbound edges suspect. Intent doneness = spec closed AND the intent's own itd-1 criteria MET (never inferred from spec close) — full consume-vocabulary decision deferred to a follow-up interview.

  • dcn-26070800000000062026-07-08

    2026-07-08 — Intents gain a required ## Prior Art section (positions the intent against corpus + outside work; ≥1 resolvable reference or an explicit "none found — searched X"). Coherence stays at promotion (itd-42), whose Tier 2 now also loads principles/; capture stays severity + edges.

  • dcn-26070800000000052026-07-08

    2026-07-08 — Persona SSOTs reconciled: personas.json is the single registry (13, expandable, alphabetical sequence); selection is BY ROLE, the role's registered name is used, never a name picked directly; all personas and the real user are they/them. Principle file updated to point at the registry; registry-membership lint is the intended gate.

  • dcn-26070800000000042026-07-08

    2026-07-08 — persona_registry lint shipped (record-lint blocker: quote attributions must name registry personas); the personas principle promoted to discipline itd-79 the same change, per the promotion path — first test case of enforced-principle ⇒ discipline. principles/ file retired.

  • dcn-26070800000000032026-07-08

    2026-07-08 — Consume-model interview: spec_id is SCALAR (never a list) — split-the-intent is doctrine (itd-67/72 precedent); task decomposition lives inside the spec. Principles/disciplines get a promotion path: enforced principle ⇒ discipline-kind intent (personas principle promotes when its registry lint ships). Coverage vocabulary (uncovered / covered-shallow / covered-deep / orphaned / unwanted) lands as itd-53's gate reporting language; "done" = covered-deep AND the intent's own criteria MET.

  • dcn-26070800000000022026-07-08

    2026-07-08 — Personas in any scenario are always Alice, Bob, Carol (in that order); the user is they/them. Recorded as a principle.

  • dcn-26070800000000012026-07-08

    2026-07-08 — Confidential sources: global user-level corpus (CSL-JSON + grep corpus, local no-remote git), append-only JSONL influence ledger per repo, banlist patterns generated from confidential entries into the itd-74 private guard; convention + skill first, abcd source verbs deferred (itd-76). Quarto chosen for eventual paper reconstruction; RAG rejected at this scale.

  • dcn-26070600000000082026-07-06

    2026-07-06 — Module path github.com/<personal account>/abcd-cli, the original repository's path under the product thinker's own account before the project moved to the intentdriven organisation; Cobra approved as the CLI framework (matches ferry and the companion harness).

  • dcn-26070600000000072026-07-06

    2026-07-06 — Three-tier .abcd/ layout: development (durable) / work (shared) / .work.local (local). docs/ user-facing only.

  • dcn-26070600000000062026-07-06

    2026-07-06 — Single repo, curated release (no dev→public mirror); the repo is the marketplace. Private companion repo deferred (trigger: shared transcripts).

  • dcn-26070600000000052026-07-06

    2026-07-06 — Spec/task layer native-minimal; the companion harness ccpm the primary deeper backend; flow-next dropped. Autonomous run not a Ralph port (host orchestrators).

  • dcn-26070600000000042026-07-06

    2026-07-06 — LLM work host-delegated by default; native/CLI/API/MCP oracles are opt-in adapters.

  • dcn-26070600000000032026-07-06

    2026-07-06 — Peer with the companion harness via conventions + MCP; no Go dependency either way.

  • dcn-26070600000000022026-07-06

    2026-07-06 — Transport-agnostic Go core; CLI is the reliable default front door; MCP is an additive front door on the same core, added later.

  • dcn-26070600000000012026-07-06

    2026-07-06 — Rebuild abcd from scratch in Go, no external tools (specstory, RepoPrompt, flow-next, Ralph, codex); ship an MVP, extend via the companion harness then Claude Code.