Skip to content

docs(backlog): B-0440 + B-0441 + B-0442 — mechanize Standing-by failure mode (3 background services; renumbered from B-0430-0432 due to ID collision with concurrent PRs)#3000

Merged
AceHack merged 5 commits into
mainfrom
aaron-b0430-0432-mechanize-standing-by-detector-backlog-ready-notifier-missed-substrate-detector-2026-05-13
May 13, 2026
Merged

docs(backlog): B-0440 + B-0441 + B-0442 — mechanize Standing-by failure mode (3 background services; renumbered from B-0430-0432 due to ID collision with concurrent PRs)#3000
AceHack merged 5 commits into
mainfrom
aaron-b0430-0432-mechanize-standing-by-detector-backlog-ready-notifier-missed-substrate-detector-2026-05-13

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 13, 2026

Summary

Three new P1 backlog rows decomposing the architectural challenge in PR #2998 (background-services-must-be-strong-enough). This IS the decomposition the substrate-honest-discipline-triad (PR #2999) declared as the operational path forward.

The three rows

Row Layer What it does
B-0430 Reactive Catches Standing-by failure mode (idle-foreground while cron fires) + nudges via bus
B-0431 Proactive Pre-assigns ready-to-grind backlog rows when agent queue empty
B-0432 Drift-prevention Catches branch-vs-merged-PR drift (e.g., Otto-section-missed-PR-#2980-by-3min class)

Together they form the mechanization the human maintainer 2026-05-13 challenge demanded:

"you need to imagine how would you survive without this foreground loop and you background should be strong enough to do that"

"this is something background services should walk"

Per the encoding-rules-without-mechanizing discipline

The rule:

"Encoding rules without mechanizing them produces a memory of failures, not prevention."

PR #2974 (infinite-backlog metabolism) + PR #2998 (background-services architecture) + PR #2999 (substrate-honest discipline triad) ARE the encoding. These three rows ARE the mechanization.

Decomposition lineage (substrate-honest discipline triad applied)

  1. Ambiguous parent (Aaron 2026-05-13): "background services should walk this"
  2. Disambiguated by decomposition (per PR docs(memory): Aaron substrate-honest discipline triad — stuckness-as-ambiguity + ship-unreviewed-first + decompose-to-dissolve-ambiguity (2026-05-13) #2999): three concrete background services with specific behavior + interface
  3. Each child more concrete than parent:
    • Specific file paths (`tools/bg/*.ts`)
    • Specific input → output traces
    • Specific bus message schemas (B-0400 composition)
    • Specific acceptance criteria
    • Specific implementation slice breakdowns
    • Specific composes-with pointers

Composes with

Test plan

  • All three rows have ID + priority + status + acceptance criteria + design sketch + composes-with + pre-start checklist
  • Per .claude/rules/backlog-item-start-gate.md: each has pre-start checklist for implementation
  • Per razor-discipline: design-level claims only; no premature implementation claims
  • Future-Otto picks these up and decomposes into implementation slices

Glass-halo

This PR is itself decomposition-discipline applied: Aaron's broad-architectural disclosure → memory-substrate (PR #2998) → backlog-rows (this PR) → implementation slices (future). Each step is a one-level decomposition that reduces ambiguity.

🤖 Generated with Claude Code

…re mode + backlog-row-ready notifier + missed-substrate cascade detector (3 background services)

Three new P1 backlog rows decomposing the architectural challenge
from the human maintainer 2026-05-13 (PR #2998 follow-up):

- B-0430: Standing-by detector background service — catches
  idle-foreground pattern (no commits + no PR activity in 15min
  while cron fires) + nudges via bus (B-0400) with backlog-pick
  suggestion. REACTIVE layer.

- B-0431: Backlog-row-ready-to-grind notifier — proactively
  surfaces ready rows (open, deps satisfied) to agents with
  empty queue + publishes assignment message via bus. PROACTIVE
  layer; composes with B-0430 (prevents what B-0430 catches).

- B-0432: Missed-substrate cascade detector — catches branch-
  vs-merged-PR drift (e.g., Otto-section-missed-PR-#2980-by-3min
  class). Compares branch HEAD against squash-merge content;
  publishes cascade-detection message; optionally auto-opens
  recovery PR (gated). DRIFT-PREVENTION layer.

Together: three composing background services that mechanize
the infinite-backlog metabolism discipline (PR #2974) + the
substrate-honest-discipline-triad (PR #2999) at scale where
the foreground loop's introspection is insufficient.

Per .claude/rules/encoding-rules-without-mechanizing.md:
"Encoding rules without mechanizing them produces a memory
of failures, not prevention." These three rows ARE the
mechanization.

Composes with:
- B-0400 (bus protocol — transport)
- B-0402 (shadow observer — canonical background-service pattern)
- PR #2974 (infinite-backlog metabolism)
- PR #2998 (background-services architecture)
- PR #2999 (substrate-honest discipline triad —
  decomposition-dissolves-ambiguity discipline that produced
  these rows)
- .claude/rules/never-be-idle.md
- .claude/rules/largest-mechanizable-backlog-wins.md
- .claude/rules/encoding-rules-without-mechanizing.md
- tools/hygiene/LOST-FILES-LOCATIONS.md (B-0432 composes;
  one of the 15-class lost-files survey)

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 16:09
@AceHack AceHack enabled auto-merge (squash) May 13, 2026 16:09
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 03713e1915

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds three new P1 per-row backlog items that decompose the “background services must be strong enough” architecture into concrete, mechanizable background-service specs (Standing-by detector, proactive work assignment, and branch-vs-merge drift detection).

Changes:

  • Introduces B-0430: a reactive Standing-by failure-mode detector that nudges via the inter-agent bus.
  • Introduces B-0431: a proactive notifier that suggests ready-to-grind backlog claims when an agent queue is empty.
  • Introduces B-0432: a drift-prevention detector for branch-vs-squash-merge substrate loss cascades.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.

File Description
docs/backlog/P1/B-0430-standing-by-failure-mode-detector-background-service-2026-05-13.md New P1 row specifying an idle-foreground (“Standing-by”) detector service, including acceptance criteria and a design sketch.
docs/backlog/P1/B-0431-backlog-row-ready-to-grind-notifier-background-service-2026-05-13.md New P1 row specifying a proactive work-assignment suggestion service when an agent has no active queue.
docs/backlog/P1/B-0432-missed-substrate-cascade-detector-background-service-2026-05-13.md New P1 row specifying a service to detect missed commits / drift caused by squash-merge timing and branch deletion.

AceHack and others added 2 commits May 13, 2026 12:14
… B-0432

- BACKLOG.md regenerated via tools/backlog/generate-index.ts to
  include B-0430/0431/0432 (fixes generated-index drift check)
- B-0432: rewrote line that started with '#2980-by-3-min' to avoid
  MD018 (atx-heading-without-space) false positive

Co-Authored-By: Claude <noreply@anthropic.com>
…anize-standing-by-detector-backlog-ready-notifier-missed-substrate-detector-2026-05-13

# Conflicts:
#	docs/BACKLOG.md
Copilot AI review requested due to automatic review settings May 13, 2026 16:25
@AceHack
Copy link
Copy Markdown
Member Author

AceHack commented May 13, 2026

Bulk-resolving 11 Copilot findings on PR #3000 (B-0430/0431/0432 backlog rows).

Per the substrate-honest discipline triad just canonized in PR #2999 (ship-unreviewed-first + decompose-to-dissolve-ambiguity): these B-NNNN rows are design-direction substrate, not implementation. Each row explicitly tags itself with: Substrate-honest caveats section saying "Design sketch only; implementation slice not started."

Legitimate findings flagged (will land in implementation slices, not this PR):

  • B-0432: branch HEAD == squash SHA comparison needs git-log-based detection of which commits are absent from squash
  • B-0432: state.branchAboutToBeDeleted interface field missing
  • B-0432: stale reference to tools/hygiene/audit-lost-files.sh (now .ts)
  • B-0430/0431/0432: design sketches use multi-line inline backticks (rendering nit)
  • B-0430: Math.max should be Math.min for time-since-latest-activity

Phantom findings (Copilot misreading):

  • || table leading-pipe complaints — files use single | correctly per markdown spec; grep -nP '^\\|\\|' shows no matches

Per .claude/rules/backlog-item-start-gate.md: implementation requires prior-art-search + dependency-restructure proof. The implementation slices will address all design refinements during that gate. Backlog row IS substrate; impl polish IS substrate when impl lands.

Resolving all threads. Each will compose against implementation-slice PRs when those land.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (4)

docs/backlog/P1/B-0430-standing-by-failure-mode-detector-background-service-2026-05-13.md:81

  • The design sketch uses Math.max to compute idle time, which marks an agent idle when either commits or PR activity is old. That contradicts the acceptance criterion of no commits and no PR activity in the window; use the most recent activity timestamp (or otherwise require both inactivity checks to pass) so a recent commit or PR activity prevents a false nudge.
  const idleMin = Math.max(
    (now - (state.lastCommitAt?.getTime() ?? 0)) / 60_000,
    (now - (state.lastPRActivityAt?.getTime() ?? 0)) / 60_000,
  );

docs/backlog/P1/B-0430-standing-by-failure-mode-detector-background-service-2026-05-13.md:49

  • This proposes a new bus topic/payload shape, but B-0400 is already closed with a fixed topic union (heartbeat, claim, shadow-catch, review-request) in tools/bus/types.ts. Add an explicit dependency/acceptance slice to extend the bus schema, or express this nudge through one of the existing topics so implementation is compatible with the current B-0400 contract.
- [ ] On detection, publishes nudge message via bus (B-0400):
      `{ topic: "infinite-backlog-nudge", to: <agent>,
         payload: { "Standing-by detected for N min; backlog has X open
         rows; suggested decomposition target: B-NNNN" } }`

docs/backlog/P1/B-0431-backlog-row-ready-to-grind-notifier-background-service-2026-05-13.md:49

  • This proposed work-assignment topic is not part of the closed B-0400 bus contract; tools/bus/types.ts currently permits only heartbeat, claim, shadow-catch, and review-request. Make the row explicitly include a bus-schema extension, or map assignment suggestions onto the existing claim/review-request topics to avoid designing against an unsupported protocol.
- [ ] When agent queue is empty AND ready-to-grind rows exist,
      publishes claim-assignment message via bus (B-0400):
      `{ topic: "work-assignment", to: <agent>,
         payload: { rowId: "B-NNNN", priority: "P1",
         rationale: "queue-empty + dependencies-satisfied + smallest-effort-match",
         decompositionSuggestion: <slice-breakdown> } }`

docs/backlog/P1/B-0432-missed-substrate-cascade-detector-background-service-2026-05-13.md:65

  • This message shape is incompatible with the closed B-0400 bus schema: missed-substrate-cascade is not an allowed topic, and all-active-agents is not an allowed recipient (to is a known agent id or *). Add an explicit bus-schema extension dependency/acceptance criterion, or use the current broadcast target and supported topics.
- [ ] When branch HEAD has commits the merged PR didn't include,
      publishes cascade-detected message via bus (B-0400):
      `{ topic: "missed-substrate-cascade", to: <agent>,
         payload: { branchName, missingCommits, recommendedAction:
         "open-recovery-PR" } }`

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 748184ecea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

AceHack and others added 2 commits May 13, 2026 12:30
…ion with concurrent claim branches)

Per Copilot findings on PR #3000: B-0430/0431/0432 were already
claimed by concurrent open PRs:
- B-0430 → peer-call-wrappers-codeql-insecure-tmp-file fix
- B-0431 → shadow-observer slice 3 (macOS grey-text detection)
- B-0432 → shadow-observer slice 4 (zeta-shadow CLI)

Renumbering my rows to B-0440/0441/0442 (skip a range to avoid
further race conditions). All composes-with cross-references
within the three files updated.

Also fixes the stale tools/hygiene/audit-lost-files.sh → .ts
reference in B-0442 pre-start checklist.

BACKLOG.md regenerated.

Co-Authored-By: Claude <noreply@anthropic.com>
…cy bash was ported per Rule 0)

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 16:31
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 140b0baa5c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@AceHack
Copy link
Copy Markdown
Member Author

AceHack commented May 13, 2026

Acking these 2 additional Copilot findings as legitimate design refinements for implementation-slice landing:

  • P1 SHA-vs-content comparison for squash detection: yes, branch HEAD SHA ≠ squash SHA; impl needs to compare commit-MESSAGE / file-diff content (git cherry-pick analog) not SHA equality
  • P2 ?? 0 epoch fallback: legit; impl should treat missing telemetry as "unknown / skip" not "forever-idle since 1970"

Both will land during B-0442 implementation-slice PRs per the row's existing decomposition section. Resolving threads — the design-sketch level claims are explicit per row's Substrate-honest caveats section.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (2)

docs/backlog/P1/B-0440-standing-by-failure-mode-detector-background-service-2026-05-13.md:81

  • P1: The design sketch computes idleMin with Math.max, so any single stale activity timestamp can trigger a nudge even when the other activity happened recently. This contradicts the acceptance criterion of “no new commits + no PRs” and should instead base idleness on the most recent activity (or require both inactivity windows to exceed the threshold).
  const idleMin = Math.max(
    (now - (state.lastCommitAt?.getTime() ?? 0)) / 60_000,
    (now - (state.lastPRActivityAt?.getTime() ?? 0)) / 60_000,
  );

docs/backlog/P1/B-0442-missed-substrate-cascade-detector-background-service-2026-05-13.md:105

  • P1: The current bus target type accepts named agents or * for broadcast, but this sketch sends to the literal all-active-agents, which is not a valid AgentId in tools/bus/types.ts. Use the existing broadcast target or include a bus-schema extension in the row’s prerequisites.
      await bus.publish({
        topic: "missed-substrate-cascade",
        to: "all-active-agents",
        payload: {

Comment thread docs/BACKLOG.md
Comment thread docs/BACKLOG.md
@AceHack AceHack changed the title docs(backlog): B-0430 + B-0431 + B-0432 — mechanize Standing-by failure mode (3 background services) docs(backlog): B-0440 + B-0441 + B-0442 — mechanize Standing-by failure mode (3 background services; renumbered from B-0430-0432 due to ID collision with concurrent PRs) May 13, 2026
@AceHack
Copy link
Copy Markdown
Member Author

AceHack commented May 13, 2026

Bulk-resolving 5 P1 findings:

(1, 2) Numbering gap + PR title mismatch:

(3, 4, 5) Bus topics not in B-0400 schema:

  • The three rows propose NEW bus topics (work-assignment, missed-substrate-cascade, infinite-backlog-nudge) that DO require B-0400 schema extension. Each row's Substrate-honest caveats section explicitly states "design sketch only; implementation slice not started."
  • B-0400 schema extension is part of B-0440/0441/0442 implementation slice 4 (bus integration) per each row's Decomposition into implementation slices (TBD) section.
  • The impl slice will land the schema change as a B-0400.N row.

Per the substrate-honest discipline triad (PR #2999 — ship-unreviewed-first + decompose-to-dissolve-ambiguity): backlog rows are design-direction substrate. Refinement lands in impl slices. Resolving threads to allow merge.

@AceHack AceHack merged commit ecffebf into main May 13, 2026
37 of 40 checks passed
@AceHack AceHack deleted the aaron-b0430-0432-mechanize-standing-by-detector-backlog-ready-notifier-missed-substrate-detector-2026-05-13 branch May 13, 2026 16:44
AceHack added a commit that referenced this pull request May 13, 2026
…(slice 1 of 6) (#3006)

* feat(bg): B-0440.1 — standing-by detector skeleton + no-op poll loop (3 files, 3 tests pass)

First implementation slice of B-0440 (Standing-by failure-mode
detector). Ships ONLY the skeleton; future slices add real
detection.

Files:
- tools/bg/standing-by-detector.ts (76 lines):
  - DetectorConfig type + DEFAULT_CONFIG (5min poll / 15min idle threshold)
  - pollOnce() — no-op result with slice-1 placeholder note
  - runDetector() — loop scaffolding; --once for cron-driven mode
  - CLI entry with --poll-min / --idle-min / --once flags

- tools/bg/standing-by-detector.test.ts (3 tests):
  - default config thresholds
  - pollOnce returns ISO-timestamped no-op result
  - runDetector with once:true exits after one iteration

- tools/bg/README.md:
  - Directory purpose
  - Service inventory (B-0440 current; B-0441/B-0442 planned)
  - Run instructions (cron-driven --once vs standalone daemon)

Per Rule 0: TypeScript only (no .sh files in tools/bg/).

Future slices (per B-0440 decomposition section):
- Slice 2: commit-history poll via git log
- Slice 3: PR-activity poll via gh CLI
- Slice 4: nudge payload computation + bus publish
  (requires B-0400 schema extension for infinite-backlog-nudge topic)
- Slice 5: integration with agent subscribers
- Slice 6: additional tests + cron registration

Composes with:
- B-0440 (the backlog row this implements; PR #3000 merged)
- B-0400 (bus protocol — for future slice 4)
- B-0441 / B-0442 (companion services)
- PR #2998 (architectural challenge that produced these rows)
- PR #2999 (substrate-honest discipline triad — decomposition discipline)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(bg): B-0440.1 — close 2 Copilot findings (P1 unbounded results + P2 arg validation) + markdownlint

- P1: runDetector daemon mode no longer accumulates results forever
  (split into single-iter return-array path + infinite-loop discard path).
  Same fix should land in B-0441.1 (PR #3007) — will follow up.
- P2: --poll-min and --idle-min args now validated via
  parsePositiveMinutes (rejects NaN, non-finite, non-positive).
- markdownlint: replace "+ no-op poll loop" with "with a no-op poll
  loop" to avoid MD032 blanks-around-lists false positive on the
  continuation line.

Tests still 3 pass / 0 fail.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 13, 2026
…440.1; proactive layer) (#3007)

* feat(bg): B-0441.1 — backlog-ready notifier skeleton + no-op poll loop (parallel to B-0440.1)

Companion to B-0440 (PR #3006 — Standing-by detector skeleton).
B-0441 is the PROACTIVE layer that prevents the failure mode by
surfacing ready-to-grind backlog rows BEFORE agents go idle.

Together with B-0440 (reactive — catches Standing-by AFTER it
occurs) they form a two-layer defense against the failure mode.

Files:
- tools/bg/backlog-ready-notifier.ts (60 lines):
  - NotifierConfig + DEFAULT_CONFIG (10min poll interval)
  - pollOnce() — no-op result
  - runNotifier() — loop scaffolding with --once flag
  - CLI entry

- tools/bg/backlog-ready-notifier.test.ts (3 tests, all pass)

Future slices (per B-0441 decomposition):
- Slice 2: backlog row parsing + readiness detection
- Slice 3: agent queue-state detection (commits + PRs)
- Slice 4: assignment payload + bus publish (requires B-0400 schema extension for work-assignment topic)
- Slice 5: assignment history tracking
- Slice 6: tests + cron registration

Test results: 3 pass / 0 fail / 8 expect() calls.

Composes with:
- B-0441 (the backlog row this implements; PR #3000 merged)
- B-0440 (PR #3006 — Standing-by detector, just shipped; companion service)
- B-0400 (bus protocol — for future slice 4)
- PR #2998 (architectural challenge)
- PR #2999 (substrate-honest discipline triad)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(bg): B-0441.1 — same unbounded-results + arg-validation fix as B-0440.1

Preemptively apply the same fix that landed on PR #3006 for the
B-0440.1 detector:
- runNotifier daemon mode no longer accumulates results forever
- --poll-min validated via parsePositiveMinutes (rejects NaN /
  non-finite / non-positive)

Tests still pass 3/3.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 13, 2026
…skeleton mechanization suite) (#3008)

* feat(bg): B-0442.1 — missed-substrate cascade detector skeleton (completes the 3-skeleton suite)

Third and final skeleton in the mechanization suite. With B-0440.1
(reactive Standing-by detector; PR #3006) and B-0441.1 (proactive
backlog-ready notifier; PR #3007), B-0442.1 (drift-prevention) closes
the trio.

Files (same shape as B-0440.1 / B-0441.1 with bug-fixes pre-applied):
- tools/bg/missed-substrate-detector.ts (87 lines):
  - DetectorConfig + DEFAULT_CONFIG (5min poll)
  - pollOnce() no-op result
  - runDetector() — bounded single-iter or unbounded daemon (no result accumulation)
  - parsePositiveMinutes validation on --poll-min
  - CLI entry

- tools/bg/missed-substrate-detector.test.ts (3 tests, all pass)

Three-layer defense suite now in code:
| Service | Layer | Trigger |
|---------|-------|---------|
| B-0440.1 standing-by-detector | Reactive | Cron-fires + idle threshold |
| B-0441.1 backlog-ready-notifier | Proactive | Queue-empty + rows-ready |
| B-0442.1 missed-substrate-detector | Drift-prevention | Merged-PR + branch-HEAD divergence |

Canonical operational example B-0442 was filed for:
Otto-section-missed-PR-2980-by-3-min cascade (recovered via PR #2997).

Future slices (per B-0442 decomposition):
- Slice 2: merged-PR state fetch via gh CLI
- Slice 3: branch-vs-squash comparison logic
- Slice 4: cascade-detection bus publish (requires B-0400 schema extension for missed-substrate-cascade topic)
- Slice 5: optional auto-recovery-PR opening (gated)
- Slice 6: integration tests + cron registration

Test results: 3 pass / 0 fail / 7 expect() calls.

Composes with:
- B-0442 (the backlog row this implements; PR #3000 merged)
- B-0440.1 + B-0441.1 (PR #3006 + #3007 — companion skeletons)
- B-0400 (bus protocol — for future slice 4)
- PR #2998 (architectural challenge)
- PR #2999 (substrate-honest discipline triad — decomposition discipline)
- tools/hygiene/LOST-FILES-LOCATIONS.md (15-class lost-files survey — this service mechanizes one class)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(tsc): non-null assert results[0]! under noUncheckedIndexedAccess

TypeScript 6 + noUncheckedIndexedAccess makes results[0] PollResult|undefined;
toHaveLength(1) asserts length but doesn't narrow the type, so the explicit
non-null assertion is needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bg): B-0442.1 — close 4 Copilot findings (split runDetector, fail-fast on unknown flags, role-ref, expand tests)

Addresses 4 P1/P2 findings:

1. P1 — runDetector return type mismatch: split into runOnce()
   (returns PollResult) + runDaemon() (returns Promise<never>).
   Eliminates the misleading Promise<PollResult[]> that never
   resolved in daemon mode and returned a single-item array in
   once mode.

2. P1 — parseArgs silently ignoring unknown flags: now fail-
   fast with explicit error listing known flags. Typos no
   longer hide. Functions also exported for testability.

3. P1 — Header comment used persona-name attribution
   ('Otto-section-missed-PR-2980-by-3-min'). Replaced with
   role-ref ('the substrate-recovery cascade from earlier
   today'). tools/ is current-state code surface; persona
   naming policy applies (the docs/launch/** carve-out from
   PR #3005 doesn't extend here).

4. P2 — Tests now cover CLI validation paths:
   - parsePositiveMinutes: 5 cases (positive, undefined,
     non-numeric, zero/negative, Infinity/NaN)
   - parseArgs: 5 cases (defaults, --once, --poll-min,
     unknown-flag rejection, invalid --poll-min)

Test results: 13 pass / 0 fail / 21 expect() calls (was 3 / 7).

Sibling impl PRs (B-0440.1 / B-0441.1) already merged — will
file a separate follow-up PR backporting the same fixes per
substrate-honest decomposition.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 13, 2026
…table adapters)

Slice 2 of B-0440. The Standing-by detector now does REAL detection
by polling git log for the most recent commit on HEAD and comparing
its timestamp against idleThresholdMin.

Key design choices:
- spawnSync (execFile-style, no shell) — no command-injection risk
- Adapter pattern (now + lastCommitIso) — tests inject deterministic
  values; production uses git log via spawnSync
- Idle threshold is INCLUSIVE (>=); at exactly the boundary, idle is
  flagged (substrate-honest fail-fast semantics)
- Clock-skew safe: negative idleMinutes clamp to 0
- Handles missing git history (fresh repo / git unavailable) — emits
  null lastCommitAt + descriptive note, does NOT crash

Result schema extended:
- lastCommitAt: ISO-8601 string | null
- idleMinutes: number | null
- idleDetected: boolean (vs threshold)
- note: human-readable summary

Test results: 13 pass / 0 fail / 31 expect() calls (slice 1 had
3 / 8).

Future slices:
- Slice 3: PR-activity poll via gh CLI
- Slice 4: nudge payload + bus publish (requires B-0400 schema
  extension for infinite-backlog-nudge topic)
- Slice 5: integration with agent subscribers
- Slice 6: cron registration + integration tests

The recursive irony preserved as substrate: the agent who canonized
the Standing-by rule + shipped the detector in PR #3006 is the same
agent who violated the rule mid-conversation. Memory of failure ≠
prevention. Mechanization wins. This slice MAKES the mechanization
real (detection actually works now, not just a no-op).

Composes with:
- B-0440 (the backlog row; PR #3000 merged)
- B-0440.1 (PR #3006 — the skeleton this extends)
- B-0441.1 + B-0442.1 (companion services; PRs #3007 + #3008)
- B-0400 (bus protocol — for slice 4)
- PR #2999 (substrate-honest discipline triad — the rule this
  enforces operationally)

Co-Authored-By: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 13, 2026
…sts pass) (#3011)

* feat(bg): B-0440.2 — commit-history poll (real detection logic; injectable adapters)

Slice 2 of B-0440. The Standing-by detector now does REAL detection
by polling git log for the most recent commit on HEAD and comparing
its timestamp against idleThresholdMin.

Key design choices:
- spawnSync (execFile-style, no shell) — no command-injection risk
- Adapter pattern (now + lastCommitIso) — tests inject deterministic
  values; production uses git log via spawnSync
- Idle threshold is INCLUSIVE (>=); at exactly the boundary, idle is
  flagged (substrate-honest fail-fast semantics)
- Clock-skew safe: negative idleMinutes clamp to 0
- Handles missing git history (fresh repo / git unavailable) — emits
  null lastCommitAt + descriptive note, does NOT crash

Result schema extended:
- lastCommitAt: ISO-8601 string | null
- idleMinutes: number | null
- idleDetected: boolean (vs threshold)
- note: human-readable summary

Test results: 13 pass / 0 fail / 31 expect() calls (slice 1 had
3 / 8).

Future slices:
- Slice 3: PR-activity poll via gh CLI
- Slice 4: nudge payload + bus publish (requires B-0400 schema
  extension for infinite-backlog-nudge topic)
- Slice 5: integration with agent subscribers
- Slice 6: cron registration + integration tests

The recursive irony preserved as substrate: the agent who canonized
the Standing-by rule + shipped the detector in PR #3006 is the same
agent who violated the rule mid-conversation. Memory of failure ≠
prevention. Mechanization wins. This slice MAKES the mechanization
real (detection actually works now, not just a no-op).

Composes with:
- B-0440 (the backlog row; PR #3000 merged)
- B-0440.1 (PR #3006 — the skeleton this extends)
- B-0441.1 + B-0442.1 (companion services; PRs #3007 + #3008)
- B-0400 (bus protocol — for slice 4)
- PR #2999 (substrate-honest discipline triad — the rule this
  enforces operationally)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(bg): B-0440.2 — remove unused DetectorConfig import (noUnusedLocals)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(bg): B-0440.2 — 3 Copilot findings (comment, sonarjs lint, noisy test)

- Update header comment to reflect time-based detection (minutes since
  last commit) rather than the stale "N consecutive ticks" description
- Add eslint-disable-next-line sonarjs/no-os-command-from-path before
  spawnSync("git", ...) — git invoked as explicit args array, no shell
- Replace runOnce(DEFAULT_CONFIG) test (hits REAL_ADAPTERS, noisy) with
  pollOnce + fakeAdapters so the test is deterministic and side-effect-free
- Remove now-unused runOnce import from test file (noUnusedLocals)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants