perf: faster CI and one scanner identity read, and repo files rewritten under a lock - #744
Merged
Merged
Conversation
itd-74's first criterion gates a banned public token in README, docs/ and the shipped artefact. The banned_tokens `names/` family read the docs-lint roots and this repository's name_roots (.abcd, AGENTS.md, CONTRIBUTING.md, scripts), so a banned token in commands/, agents/ or hooks/, which the plugin payload carries, shipped ungated. name_roots now lists commands, agents and hooks: the `names/` family alone widens to them, not the writing rules. This repository has no skills/ tree, and a root that does not resolve fails the lint, so the coverage test pins every plugin surface the checkout carries rather than a fixed list. Refs: iss-2609261457358637 Assisted-by: Claude:claude-opus-5-5
itd-2609221656373558's sixth criterion: on contention of any kind the second session backs off and the log names the reason and the minutes spent. Three gaps closed: - A run state locked past the lock's timeout by another session's change returned contention and wrote nothing. withLock now carries the session it acts for, and the second session's backoff from the lock is logged with `on: run_state`, the reason and the minutes it waited. The append takes no lock, so the line lands while the lock is held. - The claim-denied backoff carried `minutes: 0` as a constant. It now carries the minutes the attempt spent, measured from the claim's start; the unreadable-claim contention inside its grace is logged the same way. - A hand-logged backoff, the only path for contention the verb cannot see (the merge queue), could omit both. `implement log backoff` now refuses a line without a reason or without minutes as a number no smaller than zero. The plugin page, the CLI help and the brief's implement surface say so. Refs: iss-2609231206196407 Assisted-by: Claude:claude-opus-5-5
itd-2609221656361680's fourth criterion has the inbox name the sender repository of every waiting report. A report the parser refuses (a later template version, a malformed reporter field) was listed with a 12-hex key prefix and no name, because the parser judges schema_version before any other key and never reaches the envelope. That is exactly the report that most needs a reply: a sender running a newer abcd. The envelope is abcd's own writing, so report.EnvelopeSender reads it apart from the reporter's block: the name is taken only when the block names sender_key once, equal to the key the file is filed by, and sender_name once in the shape a filing writes. The inbox listing and `inbox show` carry it, and the text listing's unreadable line names the sender beside the key. Refs: iss-2609240133234244 Assisted-by: Claude:claude-opus-5-5
…ct thinker Each record finds a shipped intent's acceptance criterion promising more than the code does, and making the promise true is a product choice rather than an implementation step: a workflow cost on the second session, a new writer to a committed file, a placement fork the record already lists, a verb the product thinker has not asked for, or a lab runner the intent scopes out. None of the shipped criteria is edited. Each record carries deferred_after v0.11.0 and a deferral_reason naming the one question owed (rulings-owed section D, narrowing a shipped promise). Refs: iss-2609231206190526, iss-2609261423214723, iss-2609261457353277 Refs: iss-2609261457365969, iss-2609261457366568 Assisted-by: Claude:claude-opus-5-5
…ded already The fidelity audit read the tree at cede78b and found one live `epic` noun inside the fenced lifecycle diagram on the brief's intent surface page. The owed-review drain (af1c19d) rewrote that passage, and a word-bounded grep of the brief outside the glossary's own declarations finds none, so itd-43's first criterion holds at the tip with no change here. Resolves: iss-2609231206207995 Assisted-by: Claude:claude-opus-5-5
…ed plugin surfaces Resolved by 868b9c3: name_roots carry the names/ family over commands/, agents/ and hooks/, the plugin surfaces the shipped artefact carries. Resolves: iss-2609261457358637 Assisted-by: Claude:claude-opus-5-5
…and minutes Resolved by fbbd0d7: a locked run state, a held claim and an unreadable claim each log the second session's backoff with its reason and measured minutes, and a hand-logged backoff without either is refused. Resolves: iss-2609231206196407 Assisted-by: Claude:claude-opus-5-5
…sender Resolved by efe9aa6: the inbox reads an unreadable report's envelope apart from its reporter block and names the sender when the envelope does, under the key the file is filed by. Resolves: iss-2609240133234244 Assisted-by: Claude:claude-opus-5-5
itd-69's first two criteria promise a checker run with `--tree public` and `--tree dev`. The check (launch.CheckLockstep) took the tree as a Go parameter and had no front door: the preview and the cut ran it at dev over the source tree, and only the payload render ran it at public over its own output, so a public checkout (a marketplace install, a release source archive) could not be checked at all. `abcd launch manifests --tree public|dev [--root <dir>]` runs the check over a named tree at the chosen polarity, through launch.CheckTree, which reads that tree's own version-location contract and artefact declaration exactly as the preview does. It reads and never writes, exits 0 consistent, 1 drift (one line per field) and 2 unreadable or an unknown polarity, and has no flag that waives a finding. The verb is named for what it checks: a backticked `lockstep` is the artefact declaration's key in the launch chapter's prose, which the shape-in-prose gate would read as the verb. Wired on the plugin page, the sentence manifest and a worked example; the reference page, the surface snapshot and the chapter appendix are regenerated, and the chapter's sub-verb table gains its row. Refs: iss-2609261423222935 Assisted-by: Claude:claude-opus-5-5
…door Resolved by 9a33bdc: abcd launch manifests runs the manifest lockstep check over a named tree at the polarity the caller chooses, exiting with its 0/1/2 code. Resolves: iss-2609261423222935 Assisted-by: Claude:claude-opus-5-5
…ads fold A table of 37 shapes, each built from real configuration files and run against the real git binary: no configuration, each key alone, multi-valued keys, every file scope and an includeIf persona, the scrubbed parent variables (GIT_DIR, the legacy GIT_CONFIG, GIT_CONFIG_* injection, both -c forms, a malformed -c entry, a -c entry that changes discovery), hostile values (escaped newline, control bytes, an equals sign, a 70 KB value), unreadable and malformed configuration, the remote.origin.url rules, and git absent. Every case passes at the base; the fold that follows must pass it unchanged. The issue the fold resolves is captured alongside. Refs: iss-2609281546130900 Assisted-by: Claude:claude-opus-5-5
ProbeIdentity ran four git processes per scanner.New: --get-all user.name, --get-all user.email, the -z persona listing over user/author/committer, and --get remote.origin.url. The first, second and fourth read the same configuration under the same scrubbed environment as the third whenever the parent carries no `git -c` configuration, so one NUL-delimited listing, git -C <root> config -z --get-regexp over those seven keys, answers all of them. The user.* values are joined on newlines and split exactly as the --get-all listing was; the remote is the last url listed, as --get resolved. With -c configuration in the parent the persona listing still runs apart, under the scrubbed env plus only those entries: a -c entry can move discovery (safe.bareRepository, safe.directory) or fail the whole command when malformed, so folding it in would let it move or blind the effective identity and the remote. That case costs two processes. The 37-shape table pinned in the previous commit passes unchanged; a counting git shim on PATH holds scanner.New to one exec (two with -c). Refs: iss-2609281546130900 Assisted-by: Claude:claude-opus-5-5
…it exec Resolves: iss-2609281546130900 Assisted-by: Claude:claude-opus-5-5
The name_roots pin test hand-listed four plugin surfaces, while the launch
payload also ships .claude-plugin/, LICENSE and .gitignore, so itd-74's first
criterion ("the shipped artefact") was met for the prose surfaces only. The
test now reads the includes through launch.LoadIncludes, the bundler's own
reader, and asserts each is reached by a root or a name root; the three
missing surfaces join name_roots. TestDocsLintHarnessNameGate builds its
fixture roots from the config instead of a second hand list, and the banlist
brief chapter names the widened coverage.
Refs: iss-2609261457358637
Assisted-by: Claude:claude-opus-5-5
… unlogged Join passed the joining id to withLock, whose contention path looked the session's role up in its record; a second session's Join has no record yet, so a Join that met a locked run state logged no backoff, and logBackoff dropped requireSession's refusal on the floor. Join now takes the lock through withLockAs with the role it is recording, which places the line when no record exists; a record that exists still decides the role (a resume). Any other lookup failure, a session that never joined included, is returned, so the contention error says the backoff could not be logged. The implement page and the brief's implement chapter say both. Refs: iss-2609231206196407 Assisted-by: Claude:claude-opus-5-5
… the slowest race package late Refs: iss-2609281715083637 Assisted-by: Claude:claude-opus-5-5
…orage Every durable write in the module now flushes through one call, fsutil.Flush: the WriteFileAtomic family, CreateExclusiveIn, the parent-directory syncs and the history-index bootstrap in ahoy. Flush skips File.Sync (F_FULLFSYNC on macOS, about 8.8 ms a synced write) only when testing.Testing() reports a test binary AND ABCD_TEST_SKIP_FLUSH is exactly "1". The Makefile's test and preflight targets and ci.yml's two test steps set the opt-in; a binary the go command builds is not a test binary, so the variable does nothing there, and a shipped abcd flushes whatever its environment says. The tests pin each half: a truth table over the gate, a durability test that clears the opt-in and counts two flushes (file and parent) for each write primitive, a probe under testdata built with go build and run with the opt-in set that still flushes, and a walk that refuses any direct Sync, Fsync or F_FULLFSYNC outside Flush. Dropping either half of the gate on a scratch copy turns the truth table red, and dropping the test half turns the probe red too. Linking package testing adds 32 bytes to a stripped release build. Ruling AR (2026-09-28, the technical facilitator). Refs: iss-2609281715083637 Assisted-by: Claude:claude-opus-5-5
Two banlist tests lint a fixture tree under the real docs-lint config and hand-listed its name_roots to make each one resolve, so widening name_roots to the payload's .claude-plugin/, LICENSE and .gitignore failed them with an unresolved root. They now take one file per configured root from the config, as TestDocsLintHarnessNameGate does, so a root added there needs no edit here. Refs: iss-2609261457358637 Assisted-by: Claude:claude-opus-5-5
The race lane named only ./internal/..., which go test runs in import-path order, a few packages at a time: on the three-core macOS runner internal/surface/cli started among the last and ran alone as the step's tail. The command now names the nine slowest packages under -race (cli, reading, launch, lifeboat, lint, scanner, capture, ahoy, site) ahead of the pattern. go test runs a package named twice once, so the set is unchanged: go list resolves both to the same 78 packages. The same list goes to all four spellings of the lane (ci.yml's check job, the Makefile's preflight, release.yml's verify job and the scaffold template it is rendered from). TestRaceLaneBudgetIsDeclared- AndFitsItsJob now also holds the three commands to one package list and resolves it with go list to exactly ./internal/...'s set, with the pattern last; dropping the pattern or adding a package outside it turns the test red. Measured on a scratch snapshot with -p 3 to stand in for the runner: 845s in import-path order (cli started at 546s and ran alone for its last 171s), 557s slowest-first. On the last green macOS run (36444242193) the step took 888s and cli, 259s, finished last. Ruling AR (2026-09-28, the technical facilitator). Refs: iss-2609281715083637 Assisted-by: Claude:claude-opus-5-5
…owest race packages start first Resolves: iss-2609281715083637 Assisted-by: Claude:claude-opus-5-5
The ahoy rewrites of .abcd/config.json (the skeleton seed, the four config values, the version stamp and the attribution opt-in), of abcd's .gitignore block and of the marker block in CLAUDE.md / AGENTS.md, and the release cut's writes to CHANGELOG.md, each read a file, changed it in memory and wrote it back with no lock, so two abcd runs in one working tree could write from the same stale read and erase each other's change. Each now reads and writes under fsutil.WithFileLock, the one inter-process load-modify-write primitive, on a lock file beside the guarded file (.config.json.lock, .gitignore.lock, .CLAUDE.md.lock, .CHANGELOG.md.lock). The holder removes the lock file before letting go, which WithFileLock's inode revalidation makes safe, so a rewrite leaves nothing in the user's tree. The config-values step prompts first and takes the lock only for the re-read and the write. The release lock covers the whole ingest, derivation included, and the undo, so a second cut derives after the first wrote and is refused as a release in flight instead of overwriting it. Each lock is a leaf: nothing is taken inside it, and the one caller that holds other locks (lifeboat embark, ledger then intent then spec) plants its marker after releasing them. Intent transitions needed no change: at this base every intent writer already reads and writes under the intent store's lock (withIntentMintLock, WithLedgerThenMintLock). Refs: iss-127 Assisted-by: Claude:claude-opus-5-5
The four families the record names, surveyed at this base: intent transitions were already guarded by the intent store's lock; ahoy's config.json, .gitignore-block and marker-block rewrites and the release cut's CHANGELOG path now take fsutil.WithFileLock (352b21e). Resolves: iss-127 Assisted-by: Claude:claude-opus-5-5
…17, itd-131 The three intents v0.12.0 ships were audited against the tree at ceb4b6d (promise vs delivered reality, agents/intent-auditor.md, Role 1) and each verdict ingested into the intent's Audit Notes through `abcd intent audit ingest` from re-emitted requests. - itd-63 (setup wizard explains installs): MET 2, MET_WITH_CONCERNS 2, NOT_MET 1. Criterion 4 names a safety gate that is not on main (itd-62 is a draft); the gh explanation is shown but its install is never offered. Both captured. - itd-2609212137116617 (a new capture or draft is matched against the record): MET 5; the one scope condition survived. The ledger's other writers (inbox promote, consistency and reading ingest) file without the match; captured. - itd-131 (managed-repo identity gate): MET 4, MET_WITH_CONCERNS 1. The runner half of criterion 4 rests on iss-2608210932052003, still open; no new record, the open issue is the marker. Refs: iss-2609281911015826 Refs: iss-2609281911024838 Refs: iss-2609281911024185 Refs: iss-2608210932052003 Assisted-by: Claude:claude-fable-5-1
stepRules planted the empty .abcd/rules.json skeleton through writeRepoJSON, an atomic rename with no re-check, after the interactive prompt phase. Detection had set rules.missing before the prompts, so a rules.json written in that window (a hand-written override) was replaced by the empty-domains skeleton and the receipt said the rules were written. The skeleton is now created through fsutil.CreateExclusiveIn behind a new createRepoJSON (store.go), contained through the same os.Root as writeRepoJSON. The exclusive create is the re-check and the write in one act, so no lock is taken and every lock stays a leaf. An existing file is kept, not written: no receipt line and no refusal, the shape stepSkeleton uses for a config written meanwhile. The new file's mode stays pinned to 0644 as the atomic writer gave it. Sweep: writeRepoJSON's only other caller is writeConfig; its one create-if-absent (stepSkeleton) already re-checks under the config lock. The banlist scaffolds already create through CreateExclusiveIn. Refs: iss-2609281931185016 Assisted-by: Claude:claude-opus-5-5
…tten meanwhile Resolves: iss-2609281931185016 Assisted-by: Claude:claude-opus-5-5
Tests skip the flush to stable storage when opted in, and the slowest race packages start first. Assisted-by: Claude:claude-opus-5-5 # Conflicts: # Makefile
…anch The repo-local rewrites ahoy and release make take a file lock, and the rules skeleton keeps a rules.json written after detection. Refs: iss-127, iss-2609281931185016 Assisted-by: Claude:claude-opus-5-5
…n branch Four fidelity-drift records are built, one was already met and five are deferred as rulings owed to the product thinker. Conflicts, resolved by hunk: main moved the contribution guide to .github/ (c250bc7) while this lane widened the name gate's roots and rebuilt the test fixtures from the config. docs-lint.json keeps main's .github/CONTRIBUTING.md root and adds the lane's commands, agents, hooks, .claude-plugin, LICENSE and .gitignore; the banlist brief chapter names the moved path in the lane's sentence; nameroots_test.go pins the moved path through the lane's prefix-covering check; public_test.go and lint_test.go take the lane's config-derived fixture loops and keep main's provisionDocsLintTrees and links_resolve blocks around them. Assisted-by: Claude:claude-opus-5-5
…branch Three shipped intents carry their fidelity audit, and the three minor divergences it found are captured. Assisted-by: Claude:claude-opus-5-5
…ased one The walk that holds every flush to fsutil.Flush matched only a Sync() call, a called Fsync and the macOS full-flush fcntl. The ciSpeed review found three spellings it let through: an Fdatasync, the raw SYS_FSYNC/SYS_FDATASYNC syscall number, and an Fsync taken as a value and called under another name. None exists in the tree, and a miss would flush more in tests, never less in a shipped binary, but the walk exists to keep the gate the only flush. The pattern now names each, and a table test pins each form and the lines that must stay clear of it. Refs: iss-2609281715083637 Assisted-by: Claude:claude-opus-5-5
Measured on a clean clone of 5a7d45d (dry-run assemble). Widening dropped under the one per cent headroom the rule asks for, so its window moves to the next boundary that leaves it; the other two keep theirs: - widening 1,327,107 tokens / 5,109,365 bytes: 1,340,000 left 0.97%, so 1,350,000 (1.73%) - entailment 383,721 / 1,477,329: 390,000 kept (1.64%) - detection 1,336,143 / 5,144,153: 1,350,000 kept (1.04%) comparative is unchanged. Refs: iss-2609251455354719 Assisted-by: Claude:claude-opus-5-5
Seven files conflicted and each is resolved by hunk, both sides kept: - implement/log.go: main's checkFields (drainI's required fields per event, the agent_start ceiling) and this branch's backoffFields (reason= and minutes=) both run before the lock; withLock takes the session (drainDrift) and requireSession's record feeds main's ceiling check. - cli/implement.go help, commands/implement.md and brief 27-implement.md: main's required-fields text and table, with the backoff's reason and minutes added (a table row, and the lock-contention backoff sentences kept inside main's enforced-ceiling paragraph). - banlist/public_test.go and lint/lint_test.go: this branch's config-derived name_roots fixtures, widened to every banned token's extra_roots so main's role-ban roots resolve without a second list. - reading-presets.json: main's figures, re-measured at the tip after. DECISIONS.md and the release files are main's (this branch adds no ledger line); `## [Unreleased]` is empty. go generate refreshed commands.md. Assisted-by: Claude:claude-opus-5-5
scanner.New reads the caller's identity with one git exec (two when the parent carries `git -c` configuration) instead of four; the 37 pinned ProbeIdentity answers are unchanged. Merged cleanly; build, vet, the scanner and gitutil tests (the pin table and the exec-count test) pass. Security review SHIP (ruling AR). Resolves: iss-2609281546130900 Assisted-by: Claude:claude-opus-5-5
Measured on a clean clone of 3a282f5 (dry-run assemble). Widening 1,346,734 tokens left 0.99% under 1,360,000, so it moves to 1,370,000; entailment 388,426 keeps 400,000 (2.98%); detection 1,355,770 keeps 1,370,000 (1.05%). Comparative is untouched. Refs: iss-2609251455354719 Assisted-by: Claude:claude-opus-5-5
REPPL
enabled auto-merge
September 29, 2026 04:16
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Sep 29, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Sep 29, 2026
…claration read refuse The merge-group macOS leg of PR 744 failed TestConcurrentConnectsKeepEveryKeyAndBlock: one connect refused ~/.abcd/config.json because another connect renamed its rewrite into place between the guarded read's vetting lstat and its open. Refs: iss-2609290518278152 Assisted-by: Claude:claude-opus-5-5
…ts read ReadDeclaration vets a home-scoped declaration on an Lstat, opens it, and confirms with os.SameFile that the descriptor is the file it vetted. A file renamed into place inside that window was refused on sight, so the ordinary rewrite another abcd process of the same user makes through WriteFileAtomic made the reader refuse its own ~/.abcd/config.json (TestConcurrentConnectsKeepEveryKeyAndBlock on the loaded macOS CI leg). A replacement is now judged from scratch: the Lstat and every guard run again on whatever the path names, up to declarationAttempts (8) times, and the bytes returned are always those of a descriptor os.SameFile ties to an Lstat that passed every guard. A same-owner, owner-only-writable regular file is read; a symlink, FIFO or directory, a file writable by group or other, and a file another uid owns are refused by the guard that judges each, as if they had been there before the first Lstat; and a replacement still unsettled after the bound is refused with ErrDeclarationSwapped. Refusing on sight bought nothing the re-vet does not: whoever can rename a guard-passing file into place after the vetting can equally do so before it. A shared lock on the writers' lock file was the other option. It was not taken: the readers are generic (layered.Load reads every family, rules and trusted-roots have no writer lock), a read would create a lock file in ~/.abcd, and a hand edit or any writer outside abcd's lock would still trip the refusal. ReadGuardedInRoot closes the same window for files inside a checkout and refused a WriteFileAtomicInRoot rewrite the same way, as ErrNotRegular; it takes the same bounded re-vet and still answers ErrNotRegular for a non-regular replacement or one that outlasts the bound. TestReadDeclarationRefusesAFileSwappedInAfterVetting asserted the refusal on sight of a guard-passing file; it is replaced by the endless-replacement and non-benign-replacement detectors in replaced_test.go. Refs: iss-2609290518278152 Assisted-by: Claude:claude-opus-5-5
… replacement The fix is b342b2b: ReadDeclaration and ReadGuardedInRoot judge a file renamed into place after their vetting from scratch, a bounded number of times, rather than refusing it on sight. Resolves: iss-2609290518278152 Assisted-by: Claude:claude-opus-5-5
Main carries #743 (gateFix), #742 (drainAhoy) and #746 (integ14). One conflict, .abcd/config/reading-presets.json (widening's measured figures): main's figures taken on the conflict hunk only; the windows are re-measured at the integration tip afterwards. DECISIONS.md and CHANGELOG.md are main's byte for byte; [Unreleased] is empty. Assisted-by: Claude:claude-opus-5-5
A guarded declaration read (ReadDeclaration) and an in-root guarded read (ReadGuardedInRoot) re-vet a file a peer process replaced between the vetting lstat and the open, up to eight times, instead of refusing on sight. This closes the oracle race that ejected this branch from the merge queue (TestConcurrentConnectsKeepEveryKeyAndBlock). Security review: SHIP. internal/fsutil/fsutil.go merged cleanly by hunk: the re-vet loop and its test hooks sit beside this branch's flush skip (ciSpeed, flush.go and the syncFile path), which neither side's hunks overlap. Resolves: iss-2609290518278152 Assisted-by: Claude:claude-opus-5-5
Dry-run assemble on a clean clone of 24e7850: detection measures 1,358,267 tokens / 5,229,331 bytes, which left the 1,370,000 window 0.86% headroom, so it moves to 1,380,000. Widening (1,349,231, 1.54%) and entailment (390,570, 2.41%) keep their windows and figures. Refs: iss-2609251455354719 Assisted-by: Claude:claude-opus-5-5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This lands four reviewed lanes as one change. The test suite stops paying for a flush to disk that no test checks, and CI starts its slowest race packages first. The files abcd rewrites inside a repository (its config, the
.gitignoreblock, the plugin marker, the changelog a release cut writes) are rewritten under a file lock, so two runs at once no longer lose one another's change. Four places where shipped behaviour had drifted from what its intent promised are fixed, and three shipped intents carry their fidelity audit.ciSpeed (CI speed). A test binary skips the flush to stable storage when the test targets opt in, so the macOS leg no longer spends a sync of about 9 ms on every write a test makes. A built or released binary always flushes, whatever its environment says. Every flush in the module goes through one gate, and a test refuses a flush that bypasses it. The race step names its nine slowest packages first, so they start with the step instead of running alone at its tail. This integration widens the bypass check to catch a datasync, the raw fsync syscall and an fsync taken as a value (the review's LOW), with a test naming each.
lmw127 (repo-local locks).
ahoyrewrites the repository's config,.gitignoreblock and plugin marker under a file lock, andlaunch shiptakes one around the changelog it writes. A change another run made in the meantime is kept, not overwritten. The rules skeletonahoywrites no longer replaces arules.jsonwritten after it looked.drainDrift (fidelity drift). A session that backs off on contention logs why and for how many minutes, a session joining the run included, and a hand-logged backoff must name both. An unreadable report in the inbox still names its sender.
abcd launch manifests --tree public|devruns the manifest lockstep check on its own. The public banlist's name gate reaches every surface the shipped artefact carries, held by a test to the launch payload's own include list. One record was already met. Five are deferred as rulings owed to the product thinker.audits10 (fidelity audits). itd-63, itd-2609212137116617 and itd-131 carry their fidelity audit. The audit files three minor divergences as open captures. One of them is itd-63 criterion 4, a NOT_MET: the release notes for itd-63 should not say the safety gate goes through the install wizard.
Reviews: flakeOracle SHIP (security). scanFold SHIP (security). ciSpeed SHIP (two LOWs, one addressed here). lmw127 SHIP, then fix2 DONE. drainDrift SHIP, then fix2 DONE (MINOR 1 and 3 fixed). audits10 has no code and no review.
Integration. The drainDrift merge conflicted with main's move of the contributing guide to
.github/. It was resolved by hunk: the name gate keeps.github/CONTRIBUTING.mdand adds the lane's new roots, and the test fixtures read the roots from the config. The Makefile conflict kept both main's pinned toolchain for the preflight and the lane's flush opt-in. Every caller of the changed implement lock compiles and passes. No script in the tree hand-logs a backoff. The reading windows were re-measured at the merged tip: widening 1,327,107 tokens (window 1,350,000, up from 1,340,000), entailment 383,721 (390,000) and detection 1,336,143 (1,350,000). The five deferrals name v0.11.0 and all are minor.scanFold (one git exec for the scanner's identity). Building a scanner asks git for the caller's identity once instead of four times, or twice when the parent process carries
git -cconfiguration, and gives the same answers: a table of 37 configuration shapes pins them, and a test counting git processes holds the number. Ruling AR (2026-09-28, the user as technical facilitator) asked for the fold and treated it as a trust path. Security review SHIP. Measured on the cli package: identity reads fell from 3,416 git processes to 854, all git processes from 14,698 to 12,130, and a plain test run from 166 s and 183 s to 145 s and 145 s (about 17% faster).Re-merge after #741. Main's
implement logchecks (the required fields per event, including the new intervention, stop and decision events, and the agent ceiling held atagent_start) and this branch's backoff check (reasonandminutes) both run on every logged event, under the lock that takes the session. The command page, the brief chapter and the verb's help carry both sides: the required-fields table gains a backoff row. The name-gate test fixtures read every configured root from the config, now including the role ban's extra roots from main. The reading windows were re-measured at the merged tip: widening 1,346,734 tokens (window 1,370,000, up from 1,360,000), entailment 388,426 (400,000) and detection 1,355,770 (1,370,000).flakeOracle (concurrent config reads). Two abcd processes on one machine no longer make one refuse its own config when the other rewrites it. Reading a file under
~/.abcd(the config, the credentials, the rules) or a guarded file inside a checkout checks the file and then opens it; when another abcd process atomically replaced the file in between, the read refused it as swapped. The read now checks the replacement from scratch, up to eight times, and reads it when it passes every check. A symlink, a special file, a file others can write, a file another account owns, or a file that never stops changing is still refused. This is the race that ejected this change from the merge queue twice (TestConcurrentConnectsKeepEveryKeyAndBlock). Security review SHIP.Re-merge after #746. Main (#742, #743 and #746) merged with one conflict, the widening window's measured figures, where main's were taken before re-measuring. The race fix merged cleanly beside this branch's flush skip in the same file. The race test passes 200 of 200 runs under the race detector on the merged tree with the flush skip CI sets. The reading windows were re-measured at the merged tip: detection 1,358,267 tokens (window 1,380,000, up from 1,370,000); widening 1,349,231 and entailment 390,570 keep their windows.
Resolves: iss-2609281715083637
Resolves: iss-127
Resolves: iss-2609281931185016
Resolves: iss-2609231206196407
Resolves: iss-2609231206207995
Resolves: iss-2609240133234244
Resolves: iss-2609261423222935
Resolves: iss-2609261457358637
Resolves: iss-2609281546130900
Resolves: iss-2609290518278152
Refs: iss-2609231206190526
Refs: iss-2609261423214723
Refs: iss-2609261457353277
Refs: iss-2609261457365969
Refs: iss-2609261457366568
Refs: iss-2609281911015826
Refs: iss-2609281911024838
Refs: iss-2609281911024185
Refs: iss-2609251455354719
Assisted-by: Claude:claude-opus-5-5