From a6c1cca872687c5f176de2f5e11dbfae6f3f29c0 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Fri, 15 May 2026 12:17:19 -0400 Subject: [PATCH 1/2] fix(backlog): close B-0442 + B-0503 row status (work landed via PR #3458) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two row-status loose-ends flagged in tick 1436Z shard (#3509): - B-0442: all 6 acceptance items already `[x]` on main (slice 5 closed by PR #3458 commit description); flipped `status: open` → `closed` with `closed: 2026-05-15` + `closed_by_pr: 3458`. PR #3458's own description explicitly said "After this merges, B-0442 itself can be marked `status: closed`" — that line was the loose-end. - B-0503: 4 unchecked acceptance items on main despite the named files (`tools/bg/missed-substrate-recovery.ts` + `missed-substrate-recovery.test.ts`) being present and tested. Checked off all 4; flipped `status: open` → `closed`. Noted observed spec-drift on `buildRecoveryBranchName` signature (shipped as `(prNumber)`; spec said `(prNumber, ts: Date)`) — the timestamp was dropped in favor of `recovery/` per PR #3458 docs ("deterministic branch name `recovery/`"). Per `.claude/rules/refresh-before-decide.md`: status verified against `origin/main` snapshot at 2026-05-15T16:08Z (not local working-tree; sidetick branch state was stale relative to main). Claim acquired before the edit via `tools/bus/claim.ts acquire --from otto-cli --item B-0442` + `--item B-0503`. Both rows were unclaimed when work started. Co-Authored-By: Claude --- ...ascade-detector-background-service-2026-05-13.md | 6 ++++-- ...e5a-open-recovery-pr-core-function-2026-05-14.md | 13 +++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/backlog/P1/B-0442-missed-substrate-cascade-detector-background-service-2026-05-13.md b/docs/backlog/P1/B-0442-missed-substrate-cascade-detector-background-service-2026-05-13.md index eb4c9b759..8fe487c7e 100644 --- a/docs/backlog/P1/B-0442-missed-substrate-cascade-detector-background-service-2026-05-13.md +++ b/docs/backlog/P1/B-0442-missed-substrate-cascade-detector-background-service-2026-05-13.md @@ -1,12 +1,14 @@ --- id: B-0442 priority: P1 -status: open +status: closed title: "Missed-substrate cascade detector — background service that catches branch-vs-merged-PR drift (e.g., Otto-section-missed-PR-2980-by-3-min class)" tier: factory-infrastructure effort: M created: 2026-05-13 -last_updated: 2026-05-14 +last_updated: 2026-05-15 +closed: 2026-05-15 +closed_by_pr: 3458 depends_on: [B-0400] composes_with: [B-0402, B-0440, B-0441] children: [B-0503, B-0504, B-0505] diff --git a/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md b/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md index dabbfcb19..c1a0f758d 100644 --- a/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md +++ b/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md @@ -1,12 +1,13 @@ --- id: B-0503 priority: P1 -status: open +status: closed title: "B-0442 slice 5a — openRecoveryPR core function + RecoveryAdapters + DST tests" tier: factory-infrastructure effort: S created: 2026-05-14 -last_updated: 2026-05-14 +last_updated: 2026-05-15 +closed: 2026-05-15 parent: B-0442 depends_on: [] composes_with: [B-0442, B-0504] @@ -37,7 +38,7 @@ for opening a recovery PR, independently testable before any wiring into ## Acceptance criteria -- [ ] New file `tools/bg/missed-substrate-recovery.ts` exports: +- [x] New file `tools/bg/missed-substrate-recovery.ts` exports: (landed; spec drift noted: `buildRecoveryBranchName(prNumber)` shipped without the `ts: Date` parameter — the timestamp suffix was dropped in favor of a deterministic `recovery/` name; covered by docs in PR #3458 — "deterministic branch name `recovery/`") - `RecoveryAdapters` — interface with five adapters injected by callers: - `checkRecoveryPRExists(branchName: string) => boolean` — calls `gh pr list --head --state open` to detect existing @@ -79,7 +80,7 @@ for opening a recovery PR, independently testable before any wiring into 6. `ghPrCreate(title, body, recoveryBranch)` → null → return `error`; non-null URL → return `opened`. -- [ ] New file `tools/bg/missed-substrate-recovery.test.ts` with tests +- [x] New file `tools/bg/missed-substrate-recovery.test.ts` with tests covering all `RecoveryResult` arms: - `"opened"` — fresh finding, no existing PR, no conflicts, push+PR succeed. - `"already-exists"` — `checkRecoveryPRExists` returns `true`; no mutations. @@ -90,8 +91,8 @@ for opening a recovery PR, independently testable before any wiring into - `buildRecoveryBranchName` — deterministic output matches expected pattern. - `buildRecoveryPRBody` — contains PR number and commit SHAs. -- [ ] All tests pass: `bun tools/bg/missed-substrate-recovery.test.ts` -- [ ] `bun tools/bg/missed-substrate-detector.test.ts` still passes (no regressions) +- [x] All tests pass: `bun tools/bg/missed-substrate-recovery.test.ts` (landed in B-0503 slice; on `origin/main`) +- [x] `bun tools/bg/missed-substrate-detector.test.ts` still passes (no regressions) (landed in B-0503 slice; on `origin/main`) ## Design sketch From ab1e24fcaae3e3df3bf8f3c73226c3531958bcb4 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Fri, 15 May 2026 12:28:07 -0400 Subject: [PATCH 2/2] fix(backlog): also close B-0504 + B-0505; reconcile B-0503 design sketch with as-shipped; regen BACKLOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses Codex + Copilot findings on PR #3518: - P1 (Copilot) + P2 (Codex) on B-0442 closure: parent was being closed while children B-0504 + B-0505 still `status: open` on main — backlog-graph inconsistency. Both children's work also landed via PR #3458 chain; flipped both to `status: closed` with `closed_by_pr: 3458`. Backlog graph now coherent: all four rows (parent B-0442 + slice-5 children 0503/0504/0505) closed together. - P1 (Copilot) + P2 (Codex) on B-0503 internal inconsistency: the acceptance note flagged `buildRecoveryBranchName(prNumber)` as as-shipped but the design sketch + "Why new Date() internally" section below still showed the old `(prNumber, ts: Date)` shape + timestamped branch name. Reconciled all three locations to match shipped: signature, internal call site, and the rationale section retitled to "Why the recovery branch name is `recovery/` (no timestamp)". The row is now internally consistent and serves as accurate design substrate for future readers. - BACKLOG.md regenerated via `bun tools/backlog/generate-index.ts` (BACKLOG_WRITE_FORCE=1) so the autogenerated index reflects the 4 status flips (was the non-required check warning on the prior commit). Co-Authored-By: Claude --- docs/BACKLOG.md | 8 ++--- ...en-recovery-pr-core-function-2026-05-14.md | 30 +++++++++---------- ...e-auto-recover-into-pollonce-2026-05-14.md | 6 ++-- ...nomous-loop-acceptance-close-2026-05-14.md | 6 ++-- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index c56f00cc9..77d31b5ea 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -258,7 +258,7 @@ are closed (status: closed in frontmatter)._ - [x] **[B-0437](backlog/P1/B-0437-demo-ux-of-math-panel-bivector-fingerprints-2026-05-13.md)** Demo — UX-of-math panel (bivector fingerprints, partial-credit scoring) - [ ] **[B-0440](backlog/P1/B-0440-standing-by-failure-mode-detector-background-service-2026-05-13.md)** Standing-by failure-mode detector — background service that catches idle-foreground + nudges via bus - [ ] **[B-0441](backlog/P1/B-0441-backlog-row-ready-to-grind-notifier-background-service-2026-05-13.md)** Backlog-row-ready-to-grind notifier — background service that proactively assigns claims when agent queue empty -- [ ] **[B-0442](backlog/P1/B-0442-missed-substrate-cascade-detector-background-service-2026-05-13.md)** Missed-substrate cascade detector — background service that catches branch-vs-merged-PR drift (e.g., Otto-section-missed-PR-2980-by-3-min class) +- [x] **[B-0442](backlog/P1/B-0442-missed-substrate-cascade-detector-background-service-2026-05-13.md)** Missed-substrate cascade detector — background service that catches branch-vs-merged-PR drift (e.g., Otto-section-missed-PR-2980-by-3-min class) - [x] **[B-0445](backlog/P1/B-0445-csharp-fluent-operator-surface-pm2-2026-05-13.md)** C# fluent operator surface — Map, Filter, Join, Distinct, Window via idiomatic CSharp API - [ ] **[B-0448](backlog/P1/B-0448-cloud-routines-integration-4th-catch-43-defence-layer-2026-05-13.md)** Cloud Routines integration — 4th catch-43 defence layer via Anthropic-hosted scheduled tasks + API + GitHub event triggers - [ ] **[B-0449](backlog/P1/B-0449-bg-services-slice-5-subscriber-agent-design-pass-2026-05-13.md)** bg-services slice 5 — subscriber-agent architecture design pass (closes the foreground-optional architectural claim) @@ -305,9 +305,9 @@ are closed (status: closed in frontmatter)._ - [ ] **[B-0500](backlog/P1/B-0500-b0441-slice-3-queue-state-guard-poll-once-wiring-2026-05-14.md)** B-0441 slice 3 — wire isAgentQueueEmpty guard into pollOnce - [ ] **[B-0501](backlog/P1/B-0501-b0441-slice-5-assignment-history-dedup-cooldown-2026-05-14.md)** B-0441 slice 5 — assignment history dedup cooldown (avoid re-assigning same row within short window) - [ ] **[B-0502](backlog/P1/B-0502-b0441-slice-6-launchd-plist-autonomous-loop-docs-2026-05-14.md)** B-0441 slice 6 — launchd plist for backlog-ready-notifier + AUTONOMOUS-LOOP.md update -- [ ] **[B-0503](backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md)** B-0442 slice 5a — openRecoveryPR core function + RecoveryAdapters + DST tests -- [ ] **[B-0504](backlog/P1/B-0504-b0442-slice5b-wire-auto-recover-into-pollonce-2026-05-14.md)** B-0442 slice 5b — wire --auto-recover into pollOnce + real RecoveryAdapters + config flags -- [ ] **[B-0505](backlog/P1/B-0505-b0442-slice5c-docs-autonomous-loop-acceptance-close-2026-05-14.md)** B-0442 slice 5c — docs update (AUTONOMOUS-LOOP.md + bg/README.md) + B-0442 acceptance close +- [x] **[B-0503](backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md)** B-0442 slice 5a — openRecoveryPR core function + RecoveryAdapters + DST tests +- [x] **[B-0504](backlog/P1/B-0504-b0442-slice5b-wire-auto-recover-into-pollonce-2026-05-14.md)** B-0442 slice 5b — wire --auto-recover into pollOnce + real RecoveryAdapters + config flags +- [x] **[B-0505](backlog/P1/B-0505-b0442-slice5c-docs-autonomous-loop-acceptance-close-2026-05-14.md)** B-0442 slice 5c — docs update (AUTONOMOUS-LOOP.md + bg/README.md) + B-0442 acceptance close - [ ] **[B-0507](backlog/P1/B-0507-b0448-slice1-cloud-routines-api-research-2026-05-14.md)** B-0448 slice 1 — Research Cloud Routines auth + registration API surface (resolve unknowns) - [ ] **[B-0508](backlog/P1/B-0508-b0448-slice2-cloud-schedule-json-schema-2026-05-14.md)** B-0448 slice 2 — Define cloud-schedule.json schema for tools/routines// - [ ] **[B-0509](backlog/P1/B-0509-b0448-slice3-install-ts-cloud-schedule-extension-2026-05-14.md)** B-0448 slice 3 — Extend tools/routines/install.ts to detect + surface cloud-schedule.json diff --git a/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md b/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md index c1a0f758d..ba63a5969 100644 --- a/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md +++ b/docs/backlog/P1/B-0503-b0442-slice5a-open-recovery-pr-core-function-2026-05-14.md @@ -38,7 +38,7 @@ for opening a recovery PR, independently testable before any wiring into ## Acceptance criteria -- [x] New file `tools/bg/missed-substrate-recovery.ts` exports: (landed; spec drift noted: `buildRecoveryBranchName(prNumber)` shipped without the `ts: Date` parameter — the timestamp suffix was dropped in favor of a deterministic `recovery/` name; covered by docs in PR #3458 — "deterministic branch name `recovery/`") +- [x] New file `tools/bg/missed-substrate-recovery.ts` exports: (landed on origin/main; design sketch below has been reconciled with as-shipped — `buildRecoveryBranchName` simplified to `(prNumber)` per PR #3458 docs) - `RecoveryAdapters` — interface with five adapters injected by callers: - `checkRecoveryPRExists(branchName: string) => boolean` — calls `gh pr list --head --state open` to detect existing @@ -61,9 +61,8 @@ for opening a recovery PR, independently testable before any wiring into | { status: "cherry-pick-conflict"; sha: string; attemptedCount: number } | { status: "error"; reason: string } ``` - - `buildRecoveryBranchName(prNumber: number, ts: Date) => string` - — deterministic branch name `recovery/-`; - pure function; no I/O. + - `buildRecoveryBranchName(prNumber: number) => string` + — deterministic branch name `recovery/`; pure function; no I/O. - `buildRecoveryPRBody(finding: CascadeFinding) => string` — markdown body for the recovery PR listing `missingCommits`, the original `prNumber`, and a note that this was auto-generated. @@ -115,9 +114,8 @@ export type RecoveryResult = | { status: "cherry-pick-conflict"; sha: string; attemptedCount: number } | { status: "error"; reason: string }; -export function buildRecoveryBranchName(prNumber: number, ts: Date): string { - const stamp = ts.toISOString().replace(/[-:T]/g, "").slice(0, 14); - return `recovery/${prNumber}-${stamp}`; +export function buildRecoveryBranchName(prNumber: number): string { + return `recovery/${prNumber}`; } export function buildRecoveryPRBody(finding: CascadeFinding): string { @@ -141,7 +139,7 @@ export function openRecoveryPR( dryRun: boolean, adapters: RecoveryAdapters, ): RecoveryResult { - const recoveryBranch = buildRecoveryBranchName(finding.prNumber, new Date()); + const recoveryBranch = buildRecoveryBranchName(finding.prNumber); const exists = adapters.checkRecoveryPRExists(recoveryBranch); if (exists) { @@ -193,15 +191,15 @@ adapter implementations. The real adapters (in B-0504) must validate SHA inputs from `CascadeFinding.missingCommits` with the same allow-list regex already used in `compareBranchToMerged`. -## Why `openRecoveryPR` uses `new Date()` internally for the branch name +## Why the recovery branch name is `recovery/` (no timestamp) -The recovery branch name includes a timestamp to ensure uniqueness across -multiple recovery attempts for the same PR number. Using `new Date()` inside -`openRecoveryPR` rather than injecting it via adapters is intentional: the -idempotency gate (`checkRecoveryPRExists`) already prevents duplicate -recovery PRs; the timestamp is not load-bearing for correctness. For tests -that need to verify the branch name, `buildRecoveryBranchName` is exported -and tested separately. +The original sketch included a `` suffix to guarantee +uniqueness across multiple recovery attempts. The shipped implementation +dropped it: the idempotency gate (`checkRecoveryPRExists`) already prevents +duplicate recovery PRs for the same source PR, so a single deterministic +name per `prNumber` is correct AND simpler to test. Documented in PR #3458's +`docs/AUTONOMOUS-LOOP.md` update — "deterministic branch name +`recovery/`". ## Dependency chain diff --git a/docs/backlog/P1/B-0504-b0442-slice5b-wire-auto-recover-into-pollonce-2026-05-14.md b/docs/backlog/P1/B-0504-b0442-slice5b-wire-auto-recover-into-pollonce-2026-05-14.md index 1ceb5f6a7..9d743683e 100644 --- a/docs/backlog/P1/B-0504-b0442-slice5b-wire-auto-recover-into-pollonce-2026-05-14.md +++ b/docs/backlog/P1/B-0504-b0442-slice5b-wire-auto-recover-into-pollonce-2026-05-14.md @@ -1,12 +1,14 @@ --- id: B-0504 priority: P1 -status: open +status: closed title: "B-0442 slice 5b — wire --auto-recover into pollOnce + real RecoveryAdapters + config flags" tier: factory-infrastructure effort: S created: 2026-05-14 -last_updated: 2026-05-14 +last_updated: 2026-05-15 +closed: 2026-05-15 +closed_by_pr: 3458 parent: B-0442 depends_on: [B-0503] composes_with: [B-0442, B-0503, B-0505] diff --git a/docs/backlog/P1/B-0505-b0442-slice5c-docs-autonomous-loop-acceptance-close-2026-05-14.md b/docs/backlog/P1/B-0505-b0442-slice5c-docs-autonomous-loop-acceptance-close-2026-05-14.md index 5baa4ae1e..a9769d18d 100644 --- a/docs/backlog/P1/B-0505-b0442-slice5c-docs-autonomous-loop-acceptance-close-2026-05-14.md +++ b/docs/backlog/P1/B-0505-b0442-slice5c-docs-autonomous-loop-acceptance-close-2026-05-14.md @@ -1,12 +1,14 @@ --- id: B-0505 priority: P1 -status: open +status: closed title: "B-0442 slice 5c — docs update (AUTONOMOUS-LOOP.md + bg/README.md) + B-0442 acceptance close" tier: factory-infrastructure effort: XS created: 2026-05-14 -last_updated: 2026-05-14 +last_updated: 2026-05-15 +closed: 2026-05-15 +closed_by_pr: 3458 parent: B-0442 depends_on: [B-0504] composes_with: [B-0442, B-0503, B-0504]