This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

abcd's unattended work is spot-checked against specs and intents

specopenspc-2610301925429250

Summary

Delivers itd-2610301750162657. abcd gains a spot-check in two lanes that never hold each other up. The collection lane runs inside the landings abcd already makes: when a change lands and the repository's window has passed, abcd fetches one value from a public randomness beacon, draws up to the set number of items per group from the work decided alone in that window, and appends the drawn items to a review queue on the shared remote. The review lane is a new verb, abcd spotcheck, through which the technical facilitator, a human facilitator and the product thinker work the queue whenever they have time, one judgement per item, never reading code. A finding files an issue against the rule that admitted the item; a clean cycle states per group what it rules out. Two smaller pieces ride with it: the drain's summary counts its hand-backs per pull request, and the implement loop refuses to have a change reviewed by the model that wrote it.

The intent is blocked by itd-2610301850454860 (the landing record), planned with spc-2610301950480609, settles the shape this spec reads and nothing more: the evidence of how a change was admitted is written into history before the merge (an Admitted-by: trailer on every lane's records commit); a read-only abcd landings reader classes every first-parent commit of the default branch as person-approved, drain, automatic or person-push, naming the rule that admitted it, from history and from the forge only where history cannot answer; its --unattended view lists drain and automatic and every row the evidence cannot place with a person; and a revert is traced through This reverts commit <sha>. This spec depends on no freeze of that listing at a release cut: each drawn item's state is copied into the queue at the draw. The drain's hand-backs and the automated facilitator's decisions are outside that record, so this spec records them itself.

Grounding, read on 30 October 2026:

  • The drain's run state is DrainState (internal/core/implement/loop/drain.go:124), written to .abcd/.work.local/run/drain.json (drain.go:49, state.go:73): one worktree's local tier, which git worktree remove deletes. Its hand-backs are DrainState.HandBacks []DrainRoute (drain.go:138, type at :183-208 with Issue, From, Kind, Route, Rule, Reason, At, Blob and no pull request), built by routeHandBack (:1365); the lane's pull request number is DrainLane.PR (:179). The only durable trace of a hand-back is the reservation tombstone's Abcd-Handed-Back: <kind> trailer (internal/core/claim/message.go:27, written by markHandBack, claim/remote.go:709), which reserve --sweep later deletes.
  • The automated facilitator's decisions are of two kinds. The merge gate shipped with itd-2610150602547271: DecideMerge (internal/core/landing/facilitator.go:396) gathers the mode as the default branch's committed .abcd/config.json and the machine layer declare it, the author's role, the counted approval and, in auto, whether a review receipt names the head (reviewReceipt, landing/review.go:179, under .abcd/.work.local/review-receipts), and mergeGate (facilitator.go:329) decides by its table: auto arms a maintainer's pull request only when a review receipt names its head, human only once an approval of the head counts, the facilitator's own recorded abcd land --approve first (countedApproval :188, RecordApproval :264, ApprovalsRelDir :54), a contributor's needs a maintainer's approval in either mode, and an unverified author arms nothing. It is asked from abcd land's enqueue (landing/land.go:1284) and the loop's arm (loop/land.go:898), and its MergeDecision{Arm, Method, Why} is kept nowhere. The second kind is the drain's judgement a model answered: DrainJudgement{Issue, Answer, Kind, Reason, Route *runner.RouteRecord, …} (loop/judgement.go:118-134), Route set by adapterJudgement (loop/drain_decide.go:167) and nil when a person answered.
  • abcd proves a landing in three places: a lane's landMerged ancestor check (loop/land.go:939, ld.Merged at :1030), abcd land's own Landed and mergedAt re-run checks (landing/land.go:300, :315, from primitives.go:173, :217), and every drain move's fetch of origin's default branch (loop/drain.go:447). abcd land itself never waits for the merge and writes no file after one (landing/land.go:184, the PR body alone at prbody.go:145).
  • The drain's summary is renderDrainRun and renderDrainCounts (internal/surface/cli/drain.go:326, :435-445) over DrainCounts (loop/drain.go:298, filled at :1283); hand-backs are listed flat through DrainSummaryLine (loop/drain.go:1570).
  • The review set: ReviewSet{Roles, Judge, MaxReviewers} and ReviewClass{Class, Model, …} (loop/reviewset.go:126, :95), resolved by resolveReviewSet (:260) and stored at State.Review (loop/state.go:381); the writer's model is the implementer's self-reported ReceiptRecord.Model and its Route (state.go:548, :552); a validator's route is set at loop/validate.go:594 (host-run) and :1003 (runner); ValidatorRun.Verdict at state.go:636. Nothing compares the two models; the only same-model logic is matrix.sameModel (internal/core/matrix/export.go:560).
  • Filing an issue from Go is capture.Capture(CaptureRequest) (internal/core/capture/workflow.go:65); the request (capture.go:168-222) takes Text, Severity, Category, Source (one of issueschema.Sources, internal/core/issueschema/issueschema.go:206-218), FoundDuring, FoundAt, Remedy, RelatedIntents, RelatedSpecs; the record lands in .abcd/work/issues/open/ (alloc.go:319). The drain's admission asks its rules in order in eligibility (capture/eligible.go:131), and a remedy opening Waits on is handed back by RuleWaitsOnRuling (:158), whatever the category.
  • The board: boardOutput (cli/board.go:26-64), filled at cli/cli.go:361, rendered through board.Render (internal/core/board/board.go); rows are board.Row{Label, Text, Items} (board.go:75) appended in boardRows (cli/board_view.go:74-101) and shown by the facilitator view (board.go:338-386); the product view (:265-323) shows building, the next three and a count. --json writes boardOutput.
  • Asking: question.Ask and Question{Material, Ask, Options, Later, Typed, …} (internal/core/question/ask.go:14, :20), its limits (limits.go:42: two to four options, 24 rows at 80 columns), the asking rules (asking.go:35, the thing decided quoted in full in the question), the terminal picker ask.Terminal.Put (internal/surface/cli/ask/loop.go:114) and the host route through Fields() (ask.go:209). The mode's states are managed, facilitator and product-thinker (internal/core/mode/mode.go:54-61), set from a question's chip (cli/guard_question.go:248).
  • Shared-remote state abcd already keeps outside the tree: reservations on refs/heads/abcd-reserved/<id> (internal/core/claim/claim.go:36-43), pushed by push (claim/remote.go:454) and fetched by fetch (:1052), with every fetch named in invariant 7 (.abcd/development/brief/02-constraints/03-invariants.md:21-184).
  • Configuration: there is no config struct; each consumer claims its namespace through layered.Load and Stack.Claim (internal/core/layered/layered.go:248, :610) and reads a bounded integer through Get[int] with a check, as QuietDays does (internal/core/ahoy/worktree/quiet.go:57-73).
  • A bounded HTTPS GET is urlguard.NewDownload (internal/urlguard/download.go:38: https only, pinned hosts, no proxy, dial-time address check, bounded redirects), used by tools/fetch.go:58 and update/update.go:880 with io.LimitReader.
  • The beacon, read live on 30 October 2026: https://api.drand.sh/v2/beacons/quicknet/rounds/latest answers {"round": <n>, "signature": <96 hex>}; …/quicknet/info gives chain_hash 52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971, period 3, scheme bls-unchained-g1-rfc9380. The round's randomness is SHA-256 of the signature bytes, which abcd computes itself. The verification check of 31 October 2026 (.abcd/development/research/notes/2026-10-31-drand-beacon-verification-sota.md): signatures on G1 and keys on G2, the message SHA-256 of the big-endian round, and github.com/cloudflare/circl/sign/bls v1.6.5 verifying that shape with the same domain separation tag, with three indirect modules and no cgo.
  • The research note (.abcd/development/research/notes/2026-10-30-spot-check-unattended-changes-sota.md:24-36, :45-52, :61-72): a seed the agents cannot touch and a chance for every item; zero findings in n reads bound the failure rate at about 3/n; the reader sees the item before any automated verdict.

Approach

  1. The store: one branch on the shared remote, written only by appending files. A new package internal/core/spotcheck keeps the spot-check's record on refs/heads/abcd-spotcheck on origin, tracked at refs/remotes/origin/abcd-spotcheck, with claim's push and fetch exported for it (one refspec added to the fetch the calling verb already makes). The branch is an orphan whose tree holds four folders of small JSON files, each written once and never edited:
    • window-open.json: The commit and time the first window opened (written by the first check that finds no cycle, which draws nothing).
    • cycles/<cycle-id>.json: One per draw: the window (from_commit, to_commit, from_time, to_time, closed_by = days or changes, the observing site), the beacon (url, chain_hash, round, signature, randomness, fetched_at), the sample (per_group from the configuration, size applied, why = full or halved, the closed cycles counted), and per group the population's item keys (or, above 5,000 keys, the key range and the population's SHA-256) and the keys drawn.
    • items/<cycle-id>/<nn>-<group>-<key>.json: One per drawn item: its group, its key, the roles it is for, and the whole of its state at the draw, copied in (the landings row, the promise, the outcome and the withheld verdicts, approach 6), so what a person later sees as then never depends on a later read of history or the forge.
    • handbacks/<at>-<issue>.json and decisions/<at>-<ref>.json: The drain's hand-backs and the automated facilitator's decisions (approach 2).
    • judgements/<cycle-id>/<nn>-<group>-<key>.<role>.json: One per judgement (approach 7). The queue is derived: an item waits while a role it is for has no judgement file. Because every write is a new file keyed by item and role, two writers never conflict; a push origin rejects is retried once after a fetch, and a judgement whose key the fetch shows already on origin is dropped and the earlier one named. A push that fails offline leaves its commit on the local tracking copy, the sitting goes on, and the next push carries it; a sitting's end and the board say how many judgements have not reached origin. Why the shared remote and not a tier of the tree: The draw runs inside a landing, which has no tree to write into (land refuses a dirty tree, landing/land.go:274; a lane's worktree is removed at landMerged), and the landing on one machine must be seen by the facilitator and the product thinker on others, so a per-machine store under ~/.abcd.noindex/ would fragment the queue across whichever machines land. A committed .abcd/work/spot-checks/ would dirty the observing worktree at every draw and send a hundred judgements through a pull request per sitting, through the very gates being checked. The remote branch is where abcd already keeps state every copy must see (reservations, announcements), under invariant 7's named-verb rule; the findings themselves become committed issues, the reviewed and durable trace, so a lost branch loses judgements but never a finding. A repository with no origin has no unattended landings to draw from; there the check and the verb refuse, naming the missing remote, and write nothing.
  2. Hand-backs and the automated facilitator's decisions are recorded as they happen. The drain writes handbacks/<at>-<issue>.json (issue, kind, From, Route, Rule, Reason, the lane's pull request if one was opened, the run id, the record blob) from routeHandBack (loop/drain.go:1365), and decisions/<at>-<issue>.json (kind drain-judgement: issue, question, answer, kind, the route's model, the rule record, the reason) from decideDrainJudgement when Route is set (loop/drain_decide.go:167). The merge gate's two callers (landing/land.go:1284, loop/land.go:898) write decisions/<at>-pr<n>.json (kind merge-gate: pull request, head, the mode and its layer, the author's role, whether a receipt named the head, Arm, Method, Why) whenever the mode is auto and the author a maintainer, which is the case in which abcd is the facilitator and no person's approval was counted; a decision in human mode, or over a contributor's pull request, waits for a person and is not recorded here. Each file is committed on the local tracking copy at once and pushed with the next push its verb makes anyway (the tombstone, the lane's branch, the half-lease renewal, land's own push), and at the drain's end; none adds a push of its own. DrainRoute gains PR int from the lane, and renderDrainCounts (cli/drain.go:435) gains the per-pull-request table the intent asks for: One line per pull request the run opened with its hand-back count and kinds, then the hand-backs with no pull request.
  3. The window and the trigger. .abcd/config.json gains a spotcheck block, claimed through layered (Claim("spotcheck", "window_days", "window_changes", "per_group")): window_days (1 to 90, bundled default 7), window_changes (10 to 100,000, no default, 0 meaning unset), per_group (1 to 100, default 10). Either window may be set and the first to pass closes it; the repository layer is read last and wins, as the drain's pace keys are read. One function, spotcheck.AfterLanding(root, now) Note, is called from the three observing sites: landMerged after ld.Merged is set (loop/land.go:1030), Land when Landed or mergedAt reports the branch on the default branch (landing/land.go:300, :315), and the drain move after its fetch of the default branch (loop/drain.go:447). It reads the last cycle's to_commit and to_time from the branch as last fetched, counts git rev-list --first-parent --count <to_commit>..origin/<default> and compares now with to_time; when neither bound is passed it returns at once, having read two files and run one local git command and touched no network. Its return is a note for the run record or the verb's text, never an error, an outcome or a hold: a draw that refuses for any reason (beacon unreachable, forge unread, push rejected twice) leaves the window passed, writes nothing, and the next observed landing tries again. The window closes at the observing instant and spans everything since the last cycle, so a week with no landing is drawn at the next one and nothing falls between windows.
  4. The beacon and the draw. beacon.go pins two constants: the quicknet chain hash 52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971 and the chain's group public key, the 96-byte compressed G2 point 83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a (both from the chain's info reply, read on 31 October 2026 and recorded in 2026-10-31-drand-beacon-verification-sota.md). The draw fetches the chain's latest round, addressed by the pinned hash (https://api.drand.sh/<chain-hash>/public/latest), through urlguard.NewDownload pinned to api.drand.sh (falling back once to api2.drand.sh, then api3.drand.sh), ten seconds in all, body bounded at 4 KiB, and accepts only a positive round with a 96-hex signature; a reply that names a chain hash other than the pinned one is refused. abcd then verifies the signature itself, at pick time: the pinned key is unmarshalled into bls.PublicKey[bls.KeyG2SigG1] from github.com/cloudflare/circl/sign/bls (v1.6.5, pure Go, BSD-3-Clause), the message is SHA-256 of the round as a big-endian uint64, and bls.Verify(&pk, msg[:], sig) must hold; circl's built-in G1 domain separation tag is the one drand's bls-unchained-g1-rfc9380 scheme signs under, so no tag is passed. The randomness is SHA-256 of the signature bytes, which abcd computes itself, and a reply that carries a randomness field must carry that value. A reply that is late, malformed or unreachable, or whose signature does not verify, refuses the draw alike: nothing is written, one line names the beacon and the round, the landing's outcome is unchanged. The dependency is the one this spec adds, with the product thinker's sign-off of 31 October 2026: the build runs go get github.com/cloudflare/circl@v1.6.5 and go mod tidy, reports every line it adds to go.mod and go.sum (circl's own module requires only go-ristretto, x/crypto, and x/sys; which of those lines are new is known only when tidy runs), and lands the ACKNOWLEDGEMENTS.md entries for circl and for drand in that same change, since credit lands with the change that integrates a tool. TestBeaconVerify holds the published vector for round 1000 (signature b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39, randomness fe290beca10872ef2fb164d2aa4442de4566183ec51c56ff3cd603d930e54fdd) as its positive case and the same signature against round 1001 as its negative; the vector was not run against circl during the check, so the test's first run is that check, and a failure stops the build and is reported rather than loosened. The populations are read for the window: Groups drain-landed and automatic-merges from the landings reader's rows in from_commit..to_commit classed drain and automatic (every row the evidence cannot place with a person included, its decision 9; a person-approved row excluded, its decisions 7 and 8); groups drain-hand-backs and facilitator-decisions from the branch's handbacks/ and decisions/ files with at in from_time..to_time. A row whose approval the reader could not settle from history and reports as unread from the forge refuses the draw, so a person's approval is never drawn as unattended on a guess. An automatic merge's rule is facilitator.mode: auto, the requirement the gate's table holds; the review receipt itself stays in the local tier and is not recovered afterwards (itd-2610301850454860, decisions 6 and 7), so the reader names the mode's requirement and the item copies it. Each item's key is its merge commit or its file name; within a group the keys are sorted, each is given HMAC-SHA256(randomness, cycle-id || group || key), and the size smallest are drawn. The same stored randomness and population give the same list, every item has a chance, and no agent can steer it: the value does not exist until the window has closed. The cycle record stores round, signature and chain hash, so the verification abcd made at the draw can be repeated by anyone later. The fetch is written into the documented meaning of land, drain and implement step in invariant 7 and their pages, so abcd still asks the network nothing on its own.
  5. The sample size adapts over fully reviewed cycles only. size is per_group unless the three most recent closed cycles, in window order, each have zero findings, when it is ceil(per_group / 2), never below one; a closed cycle with any finding makes the next size full. A cycle is closed when every role slot of every item has a judgement; an open cycle is skipped in the count and counts as neither clean nor a finding. The cycle record names the cycles it counted.
  6. A card, never code. spotcheck.Card(item) renders what a role sees, in plain text, from records alone: the landings row (class, rule by id and path, when, pull request number); the promise, which is the issue's text and remedy, or the spec's criteria, or, for the product thinker, the intent's press release and acceptance criteria; the outcome, which is the pull request's title and the record section of the body the loop composed (prbody.go:61), the resolved_by stamp and the changelog line where one exists; and for a hand-back the issue, the kind, the route, the clause of the rule that applied and the question whether the drain was right to hand it back; for a decision the question put, the answer given and the rule record. Every card ends with then and now: then is the item file's own copy, written at the draw and never re-read from history or the forge; now is read at the sitting from the default branch as last fetched: still on it, reverted by <sha> (the landings reader's revert trace), changed again by later first-parent commits touching the change's paths, the issue reopened, or the handed-back issue since resolved, by whom. A card never includes a diff, a file body or a test body; TestCardCarriesNoCode renders every fixture and refuses a fence, a diff --git line or a path with a line number. Withheld until the judgement is saved, though copied into the item file at the draw: the validators' verdicts the pull request body carries, the drain judge's reason on a judgement item, the gate's Why on a merge-gate item, and any reviewer's verdict; show and next leave them out and the card says verdicts: shown after you judge.
  7. The sitting. abcd spotcheck review [--as facilitator|human-facilitator|product-thinker] (the role defaults from the mode file and is asked when unset) makes one fetch of the branch and the default branch, then walks the queue in window order, oldest cycle first, group order within a cycle, item order within a group, for the role's unjudged slots. Each item is put through question.Ask with the card as Material, the one question for its group (Does the outcome match its spec?, Was the drain right to hand this back?, Was the decision right under its rule?, Does what came back match the intent?) and the options sound, wrong and the decide-later option, a typed line for why on wrong; in a terminal through ask.Terminal.Put, one key per item; in a host session the page has the agent render spotcheck next --json --as <role> [--batch N] and put the same question through the host's tool, then record the answer with spotcheck judge <item> sound|wrong --why "<text>" --as <role>. Both routes end in the same judgement file (verdict, why, role, answered_in, at, state_now, the issue id on wrong), committed and pushed as it is made, so a sitting stopped at any item resumes at the first unjudged slot with nothing to restore. later moves the item to the end of this pass and writes nothing. A progress line reads item 37 of 112, cycle 3 of 9. After each saved judgement the withheld verdicts print, one line each, and the next card is already read.
  8. A finding files an issue; abcd never edits the rule. On wrong, spotcheck calls capture.Capture with Source: review-followup, FoundDuring: spot-check <cycle-id>, FoundAt the admitting rule's file (the drain rule record for a drain item, .abcd/config.json for an automatic merge or a merge-gate decision), Text naming the item, its group, its cycle, the rule by id and the person's words, severity minor unless the person raises it, category process, and a Remedy that opens Waits on <rule id>: <the person's why>. That opening is what eligibility hands back under RuleWaitsOnRuling (eligible.go:158), so no drain can take the issue and rewrite the rule; TestFindingIsNeverDrainEligible runs PlanDrain over such a record. The issue's id is written into the judgement.
  9. The closing statement. abcd spotcheck bare and spotcheck cycles render each cycle: per group, drawn n of N, judged j, findings k, and for a group with j = n and k = 0: rules out a failure rate above about one in r (95%), r = round(1 / (1 - 0.05^(1/n))), which is one in four at ten, and in words what it cannot rule out: a lower rate, and the N - n items not read. A group with no items says nothing drawn: no items in the window. No render ever says no problems; TestStatementNeverSaysNoProblems holds the phrase out of every fixture.
  10. The board and the verb's surface. boardOutput gains SpotCheck{Waiting, ByRole, OldestDays, Unpushed, Due} computed from the branch as last fetched (disk only, nothing fetched), and boardRows a spot-check row: 37 wait (facilitator 30, product thinker 7), oldest 41 days; the product view adds one line when items wait for the product thinker; --json carries it. Due says the window has passed and no landing has been observed since. The verb is new and top-level, abcd spotcheck, with sub-verbs review, next, judge, show <item> and cycles: no existing verb's documented meaning holds a review queue people work across months (reflect is one release's interview, lab one snapshot, status the hour's announcements, landings a read-only listing), and a sub-verb of land or drain would put the reader's verb under a writer's. It lands with its brief row (41, 04-surfaces/README.md), its chapter 04-surfaces/42-spotcheck.md with the ## Sub-verbs table, its page commands/spotcheck.md (block people), its sentence in the internal/core/surface manifest, the regenerated snapshot, and the spotcheck block in 05-internals/03-configuration.md. Invariant 7 gains the branch's fetch and push for spotcheck, and the beacon fetch and branch push for land, drain and implement step.
  11. Nothing waits for the queue. spotcheck exports to loop and landing only AfterLanding, the two record writers of approach 2, and nothing that returns a hold, a count or a boolean; mergeGate, DrainJudging, RunningUnattended and the away mode's Judge are untouched. TestNothingWaitsForTheQueue lands a lane and plans a drain over a branch holding ten thousand unjudged items and asserts the same outcomes and no read of items/ or judgements/.
  12. A model other than the writer's reviews every change. Before a validator is dispatched (loop/validate.go:594, :1003), the loop compares the implementer's reported model (ReceiptRecord.Model, or its Route.Model) with the reviewer's resolved ReviewClass.Model, by matrix.sameModel's normalisation; on a match it takes the next class in BundledClasses whose model differs, and when none does the lane hands back as stuck with the reason no reviewer model other than the writer's. A host-run validator's return must name its model, as the implementer's receipt does; a return naming none is treated as the writer's. ValidatorRun gains WriterModel and ReviewerModel, the lane receipt and the composed pull request body name both, and renderReview (cli/build.go:540) shows them.

How each criterion is met

  • Seeded from a public value, stored, every item a chance, recomputable. Approaches 1 and 4. Tests: TestDrawIsDeterministic (same cycle file, same list, across two runs and a shuffled population), TestEveryItemCanBeDrawn (over many fake randomness values every key of a 50-item group is drawn at least once), TestBeaconUnreachableWritesNothing (a refusing fake beacon: no cycle file, no item, the landing's Merged still set and exit 0), TestBeaconVerify (the round-1000 vector verifies under the pinned key and yields its published randomness; the same signature against round 1001 fails), TestBeaconBadSignatureWritesNothing (a fake beacon serving a round with a signature that does not verify, and one naming another chain hash: no cycle file, no item, one line naming the beacon and the round, the landing's Merged still set and exit 0).
  • Groups, ten by default, half after three clean, full after a finding. Approaches 3 to 5. Tests: TestFourGroupsFromTheirSources (rows classed drain and automatic and the branch's handbacks/ and decisions/ files; a person-approved row never drawn), TestSizeHalvesAfterThreeClosedCleanCycles, TestSizeFullAfterAFinding, TestOpenCycleCountsAsNeither, TestPerGroupBounds (0, 101 and a string refused with the key named).
  • Never code; the right thing beside each item; verdicts after the judgement. Approaches 6 and 7. Tests: TestCardCarriesNoCode, TestCardPerRole (facilitator sees spec and outcome or rule and decision, product thinker sees the intent, human facilitator sees only decision items a model took), TestVerdictsShownOnlyAfterJudging (the rendered card lacks the verdict text; the post-judgement text holds it).
  • A finding files an issue naming item, group and rule; abcd never edits the rule. Approach 8. Tests: TestWrongFilesAnIssue (the record names all three and the person's why), TestFindingIsNeverDrainEligible.
  • A clean cycle states what it rules out, never "no problems". Approach 9. Tests: TestStatementAtTen (one in four), TestStatementAtFive (one in two), TestStatementNeverSaysNoProblems, TestEmptyGroupStatesNothingDrawn.
  • The window passes at a landing; otherwise nothing is drawn. Approach 3. Tests: TestWindowByDays, TestWindowByChanges, TestWindowNotPassedDrawsNothingAndFetchesNothing (the zero-network harness), TestFirstCheckOpensTheWindow, TestThreeObservingSites (lane landing, land re-run, drain move each call once).
  • Nothing autonomous waits for the queue. Approach 11. Test: TestNothingWaitsForTheQueue.
  • Items keep across months, ordered by window and group, stop and resume anywhere. Approaches 1 and 7. Tests: TestQueueOrderOldestFirst (nine cycles, four groups), TestResumeAtFirstUnjudged (a sitting quit at item 37 resumes there, judgements intact on the branch), TestNoItemExpires (a two-year-old item still listed).
  • A late item shows then and now; its finding is filed like any other. Approaches 6 and 8. Tests: TestCardThenAndNow (reverted, changed again, issue since resolved), TestLateFindingFilesAgainstItsRule.
  • Only fully reviewed windows count towards the halving. Approach 5. Tests: TestOpenCycleCountsAsNeither, TestSizeCountsClosedCyclesInWindowOrder.
  • The board says how many wait, for whom, how old. Approach 10. Tests: TestBoardSpotCheckRow (text, markdown, --json), TestBoardReadsTheBranchFromDiskOnly.
  • Hand-backs per pull request in the drain summary. Approach 2. Test: TestDrainSummaryHandBacksPerPullRequest (two pull requests with one and zero hand-backs, three with none; text and --json).
  • A model other than the writer's, both named. Approach 12. Tests: TestReviewerDiffersFromWriter (same model served: the next class is taken; the state names both), TestNoOtherModelHandsBack (one model only: stuck, reason named), TestHostValidatorMustNameItsModel.

Out of scope, recorded elsewhere: The landing classes, the admitting evidence written into history, the landings reader and the revert trace (itd-2610301850454860, which this spec reads and does not build; its landings.List honours the caller's context, so the draw passes its own deadline and refuses past it, while landing.ForgeTimeout bounds each forge call and the reader's per-pull-request cache keeps a window's second read cheap); the merge gate's table itself (itd-2610150602547271, shipped; this spec records its answers and changes none); a draw on a timetable (itd-13); a by-hand draw (ruled out by decision 3); the verification ladder (itd-173); the autonomy grant's report (itd-2610240850336695).

Footprint

  • packages: internal/core/spotcheck/store.go, internal/core/spotcheck/window.go, internal/core/spotcheck/beacon.go, internal/core/spotcheck/draw.go, internal/core/spotcheck/groups.go, internal/core/spotcheck/size.go, internal/core/spotcheck/card.go, internal/core/spotcheck/judge.go, internal/core/spotcheck/statement.go, internal/core/spotcheck/config.go, internal/core/claim/remote.go, internal/core/implement/loop/drain.go, internal/core/implement/loop/drain_decide.go, internal/core/implement/loop/handback.go, internal/core/implement/loop/land.go, internal/core/implement/loop/validate.go, internal/core/implement/loop/reviewset.go, internal/core/implement/loop/state.go, internal/core/implement/loop/receipt.go, internal/core/landing/land.go, internal/core/landing/prbody.go, internal/core/board/board.go, internal/core/surface/manifest.go, internal/surface/cli/cli.go, internal/surface/cli/spotcheck.go, internal/surface/cli/board.go, internal/surface/cli/board_view.go, internal/surface/cli/drain.go, internal/surface/cli/build.go, commands/spotcheck.md, commands/drain.md, commands/land.md, commands/build.md, commands/implement.md, .abcd/development/brief/04-surfaces/README.md, .abcd/development/brief/04-surfaces/42-spotcheck.md, .abcd/development/brief/04-surfaces/35-drain.md, .abcd/development/brief/04-surfaces/38-land.md, .abcd/development/brief/04-surfaces/27-implement.md, .abcd/development/brief/02-constraints/03-invariants.md, .abcd/development/brief/05-internals/03-configuration.md, .abcd/development/release/surface.json, go.mod, go.sum, ACKNOWLEDGEMENTS.md
  • tests: internal/core/spotcheck/store_test.go, internal/core/spotcheck/window_test.go, internal/core/spotcheck/beacon_test.go, internal/core/spotcheck/draw_test.go, internal/core/spotcheck/groups_test.go, internal/core/spotcheck/size_test.go, internal/core/spotcheck/card_test.go, internal/core/spotcheck/judge_test.go, internal/core/spotcheck/statement_test.go, internal/core/spotcheck/config_test.go, internal/core/implement/loop/drain_handbacks_perpr_test.go, internal/core/implement/loop/drain_spotcheck_records_test.go, internal/core/implement/loop/land_spotcheck_test.go, internal/core/implement/loop/validate_other_model_test.go, internal/core/landing/land_spotcheck_test.go, internal/surface/cli/spotcheck_surface_test.go, internal/surface/cli/board_spotcheck_test.go, internal/surface/cli/drain_counts_surface_test.go, internal/surface/cli/build_reviewset_surface_test.go

Steps

  1. The store, the drain's hand-backs and judgements and the merge gate's decisions recorded as they happen, with hand-backs per pull request in the summary
    • packages: internal/core/spotcheck/store.go, internal/core/claim/remote.go, internal/core/implement/loop/drain.go, internal/core/implement/loop/drain_decide.go, internal/core/implement/loop/handback.go, internal/core/implement/loop/land.go, internal/core/landing/land.go, internal/surface/cli/drain.go, commands/drain.md, .abcd/development/brief/04-surfaces/35-drain.md
    • tests: internal/core/spotcheck/store_test.go, internal/core/implement/loop/drain_handbacks_perpr_test.go, internal/core/implement/loop/drain_spotcheck_records_test.go, internal/core/landing/land_spotcheck_test.go, internal/surface/cli/drain_counts_surface_test.go
  2. The window, the beacon and the draw at the three observing sites. This step waits for itd-2610301850454860 to ship, since its reader supplies two of the four groups; steps 1 and 4 do not. It opens by adding the one dependency (go get github.com/cloudflare/circl@v1.6.5, then go mod tidy), reports every line added to go.mod and go.sum, and runs TestBeaconVerify before anything else is written, so a vector that fails stops the step at once; the ACKNOWLEDGEMENTS.md entries for circl and drand land in this step's change.
    • needs: 1
    • packages: go.mod, go.sum, ACKNOWLEDGEMENTS.md, internal/core/spotcheck/config.go, internal/core/spotcheck/window.go, internal/core/spotcheck/beacon.go, internal/core/spotcheck/groups.go, internal/core/spotcheck/draw.go, internal/core/spotcheck/size.go, internal/core/implement/loop/land.go, internal/core/implement/loop/drain.go, internal/core/landing/land.go, commands/land.md, commands/build.md, commands/implement.md, .abcd/development/brief/04-surfaces/38-land.md, .abcd/development/brief/04-surfaces/27-implement.md, .abcd/development/brief/02-constraints/03-invariants.md, .abcd/development/brief/05-internals/03-configuration.md
    • tests: internal/core/spotcheck/config_test.go, internal/core/spotcheck/window_test.go, internal/core/spotcheck/beacon_test.go, internal/core/spotcheck/groups_test.go, internal/core/spotcheck/draw_test.go, internal/core/spotcheck/size_test.go, internal/core/implement/loop/land_spotcheck_test.go, internal/core/landing/land_spotcheck_test.go
  3. The review lane: cards, the sitting, judgements, findings and the closing statement, through abcd spotcheck and its page
    • needs: 2
    • packages: internal/core/spotcheck/card.go, internal/core/spotcheck/judge.go, internal/core/spotcheck/statement.go, internal/core/surface/manifest.go, internal/surface/cli/cli.go, internal/surface/cli/spotcheck.go, commands/spotcheck.md, .abcd/development/brief/04-surfaces/README.md, .abcd/development/brief/04-surfaces/42-spotcheck.md, .abcd/development/release/surface.json
    • tests: internal/core/spotcheck/card_test.go, internal/core/spotcheck/judge_test.go, internal/core/spotcheck/statement_test.go, internal/surface/cli/spotcheck_surface_test.go
  4. A model other than the writer's reviews every change, both named
    • packages: internal/core/implement/loop/validate.go, internal/core/implement/loop/reviewset.go, internal/core/implement/loop/state.go, internal/core/implement/loop/receipt.go, internal/core/landing/prbody.go, internal/surface/cli/build.go
    • tests: internal/core/implement/loop/validate_other_model_test.go, internal/surface/cli/build_reviewset_surface_test.go
  5. The board's row, and the proof that nothing waits for the queue
    • needs: 3
    • packages: internal/core/board/board.go, internal/surface/cli/board.go, internal/surface/cli/board_view.go
    • tests: internal/surface/cli/board_spotcheck_test.go, internal/core/implement/loop/land_spotcheck_test.go

Frontmatter

idspc-2610301925429250
typespec
lifecycleopen

References1

mentions6