Skip to content

feat(bg): B-0440.4 — bus publish on idle detection (full reactive loop closed)#3017

Merged
AceHack merged 2 commits into
mainfrom
otto-b0440-4-bus-publish-slice-4-impl-2026-05-13
May 13, 2026
Merged

feat(bg): B-0440.4 — bus publish on idle detection (full reactive loop closed)#3017
AceHack merged 2 commits into
mainfrom
otto-b0440-4-bus-publish-slice-4-impl-2026-05-13

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 13, 2026

Summary

Slice 4 of B-0440. The Standing-by detector now closes the full reactive loop: detect idle → publish `infinite-backlog-nudge` envelope via B-0400 bus.

End-to-end smoke-verified:

```
{
pollAt: 2026-05-13T18:36:32.921Z,
idleDetected: true,
lastCommitAt: 2026-05-13T18:32:13.000Z,
idleMinutes: 4.33,
publishedEnvelopeId: 54bc55da-90ee-484c-8b03-680cd23731a6,
note: idle 4.3min >= threshold 1min — Standing-by candidate (nudge published)
}
```

Envelope lands at `/tmp/zeta-bus/.json` ready for subscriber agents.

What lands

Tests

```
bun test
17 pass
0 fail
45 expect() calls
```

Slice ordering note

Slice 3 (PR-activity poll) is intentionally skipped — slice 4 was prioritized because it closes the full reactive loop (detect → nudge → react) and slice 3 is additive detection signal that can layer on top without restructuring.

Composes with

🤖 Generated with Claude Code

…nudge topic; 17 tests pass)

Slice 4 of B-0440. When idle is detected, the Standing-by detector now
publishes an `infinite-backlog-nudge` envelope via B-0400 bus
(PR #3016 schema extension) so any subscribing agent can react.

End-to-end working: detector polls git → flags idle → publishes nudge
envelope to /tmp/zeta-bus/<uuid>.json. Smoke-verified against real
bus.

Key design choices:
- Adapter pattern extended with publishNudge for deterministic tests
  (no real bus IO in unit tests)
- New flags: --no-publish (dry-run), --agent (sender identity), --to
  (recipient; default "*" = broadcast)
- Publish only fires when idleDetected && !noPublish
- Rationale string includes the infinite-backlog-metabolism reminder
  per PR #2974

Test coverage:
- Bus publish path (3 cases: idle+publish, idle+no-publish dry-run,
  not-idle)
- --agent / --to flag plumbing + validation (rejects invalid agent
  IDs, rejects "*" as sender)
- Existing detection paths (idle threshold, null commit, clock skew)

Tests: 17 pass / 0 fail / 45 expect() calls (slice 2 had 12 / 29).

Note: slice 3 (PR-activity poll via gh CLI) is intentionally skipped
ahead of slice 4 because:
- Slice 4 unblocks the full reactive loop (detect → nudge → react)
- Slice 3 adds a second detection signal (PR activity) that can be
  layered on later without restructuring
- The composes-with chain (B-0440 → B-0440.4 → B-0440.3) makes
  shipping order operationally honest

Future slices:
- Slice 3: PR-activity poll via gh CLI (additional detection signal)
- Slice 5: integration with agent subscribers (downstream consumers)
- Slice 6: cron registration + integration tests

Composes with:
- B-0440.2 (PR #3011 — commit-history poll this extends)
- B-0400 schema extension (PR #3016 — infinite-backlog-nudge topic)
- B-0441 + B-0442 (companion services; same slice-4 pattern will
  land for each)
- PR #2974 (infinite-backlog metabolism — the rule the nudge cites)

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 18:37
@AceHack AceHack enabled auto-merge (squash) May 13, 2026 18:37
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

Slice 4 of B-0440 wires the Standing-by detector into the B-0400 bus: when idle is detected, the detector publishes an infinite-backlog-nudge envelope and reports the published envelope ID in the poll result. Adds CLI flags (--no-publish, --agent, --to) and extends the adapter pattern with a publishNudge seam for deterministic tests.

Changes:

  • pollOnce now publishes a nudge envelope on idle (unless noPublish), records publishedEnvelopeId in the result, and includes a rationale string referencing infinite-backlog metabolism.
  • DetectorConfig gains noPublish, fromAgent, toAgent; CLI argument parsing adds --no-publish, --agent, --to with allow-list validation.
  • Test suite restructured around slice-4 behavior with fake publishNudge capturing calls; coverage added for publish/skip/identity paths.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tools/bg/standing-by-detector.ts Adds bus-publish path, new flags, and local agent-ID allow-lists.
tools/bg/standing-by-detector.test.ts Reworks tests around captured publish calls and new flag parsing.

Comment thread tools/bg/standing-by-detector.ts Outdated
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: efc46de5fc

ℹ️ 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".

Comment thread tools/bg/standing-by-detector.ts Outdated
Comment thread tools/bg/standing-by-detector.ts Outdated
…ENT_IDS, catch bus publish failures)

1. Removed duplicate VALID_SENDER_IDS / VALID_AGENT_IDS — now
   reuses the canonical SENDER_IDS / AGENT_IDS exports from
   tools/bus/types.ts (single source of truth).

2. P1: Wrapped publishNudge() in try/catch so bus IO failures
   don't kill the daemon poll loop. Failures captured in
   publishError and surfaced in the result note.

3. Same as #1 (different reviewer's perspective on duplicate
   constants). Resolved by the same fix.

Tests: 17 pass / 0 fail / 45 expect() calls (unchanged).

Co-Authored-By: Claude <noreply@anthropic.com>
@AceHack AceHack merged commit 2e5f270 into main May 13, 2026
25 checks passed
@AceHack AceHack deleted the otto-b0440-4-bus-publish-slice-4-impl-2026-05-13 branch May 13, 2026 18:49
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: 8805e14750

ℹ️ 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".

Comment on lines +115 to +116
if (idleDetected && !config.noPublish) {
const rationale = `Standing-by detected: ${idleMinutes.toFixed(1)}min since last commit on HEAD (threshold ${config.idleThresholdMin}min). Pick decomposition work per infinite-backlog metabolism.`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Delay nudge publish until full idle heuristic is satisfied

This now emits infinite-backlog-nudge whenever commit age crosses the threshold, but pollOnce still does not include PR-activity checks (the Standing-by heuristic in B-0440 requires both commit and PR inactivity). In a common case where an agent is actively working in PR threads without new commits, this will publish false-positive nudges every poll interval and can trigger downstream automation on incorrect signals.

Useful? React with 👍 / 👎.

idleThresholdMin: 15,
once: false,
noPublish: false,
fromAgent: "otto",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid hard-coding the default sender to a single agent

Defaulting fromAgent to "otto" causes misattributed bus envelopes whenever this detector runs under any other agent identity without an explicit --agent override. That breaks provenance and any consumer logic keyed on sender identity, so the sender should be required or derived from runtime identity instead of silently impersonating one agent.

Useful? React with 👍 / 👎.

AceHack added a commit that referenced this pull request May 13, 2026
…sh catches multi-agent duplicate work (2026-05-13)

Observed multiple times today during the bg-services + Debank
launch cascade. Aaron's framing:

> "that's a good failure mode, someone else already fixed"

When Otto prepares a fix locally, fetch-before-push reveals
another factory agent has already pushed the same fix. The
catch mechanism is in the fetch step. Without it, two agents
would produce duplicate commits or stomp each other.

Today's operational examples:
- PR #3011: auto-fixer pushed unused-import fix; reset to remote
- PR #3012: auto-fixer pushed 4-Copilot-findings fix; reset to remote
- PR #3018: Vera + Lior pushed lint + casing fixes; reset to remote

Generalizable principle: in multi-agent collaborative editing,
fetch-before-push is the cheap convergence mechanism. The cost
is one extra git fetch per push. The benefit is correctness
in the multi-agent loop.

Composes with:
- .claude/rules/glass-halo-bidirectional.md
- PR #2999 (substrate-honest discipline triad — ship-unreviewed-first composes with fetch-before-push)
- PR #3016 / #3017 / #3018 (today's bg-services + Debank cascade)

MEMORY.md paired edit included.

Co-Authored-By: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 13, 2026
… + P1 structured lastPublishError field (#3022)

Resolves Riven's adversarial review (bus envelope 6c689634-14e7-4cf9-acf8-00c018f1bded):

P0 (AC VIOLATION) — Standing-by detector previously only checked
commit-history. Per B-0440 AC: "no new commits + no PRs opened/closed
in last 15min while autonomous-loop cron is firing". The commit-only
implementation produced false negatives for any agent doing
PR-review-only / bus-coordination / claim-work without committing —
the exact failure mode the service was built to catch.

Fix: pollOnce now reads BOTH signals via injected adapters:
- lastCommitIso() → ISO-8601 of most recent commit on HEAD
- lastPrActivityIso() → ISO-8601 of most recent PR activity in repo

Idle gap = pollAt - MAX(commit, pr_activity). Either signal recent
means NOT idle.

Repo-level (no --author filter) per substrate-honest framing: factory
agents share the AceHack GitHub account, so author-filtering would
miss most activity. Cited in adapter docstring.

P1 (silent failure) — Added structured lastPublishError field to
PollResult. Bus publish failures are now machine-readable, not just
buried in the note string. The note still surfaces it for human ops
but daemons / dashboards can consume the structured field directly.

Real smoke test verifies both signals:
{
  lastCommitAt: 2026-05-13T18:49:06.000Z,
  lastPrActivityAt: 2026-05-13T19:17:58.000Z,
  idleMinutes: 1.08,   // gap from MAX of the two
  publishedEnvelopeId: 606cae9e-...,
  lastPublishError: null,
}

Tests: 16 pass / 0 fail / 47 expect() calls (slice 4 had 17 / 45).
New test coverage:
- "recent commit only" → NOT idle
- "recent PR activity only" → NOT idle (the Riven P0 false-negative case)
- "OLD commit + recent PR" → NOT idle
- "recent commit + OLD PR" → NOT idle
- "BOTH old" → idle flagged
- "BOTH null" → no detection (no false positive)
- "publish failure surfaces in structured lastPublishError" → P1 fix verified

Composes with:
- Riven's adversarial review (envelope 6c689634-...)
- Otto's reply (envelope e8174b34-fdee-47f7-af1a-df80c27b51cd)
- B-0440.2 (PR #3011 — commit-history poll this extends)
- B-0440.4 (PR #3017 — bus publish this preserves)
- PR #2999 (substrate-honest discipline triad — accept findings + ship fix)

Adversarial review caught what solo-Otto missed. The factory walks.

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

Vera + Copilot caught the same 2 patterns on PR #3020 that Riven
flagged on PR #3017:

1. P1: bus publish without try/catch — daemon crash on bus IO failure.
   Fix: wrap publishAssignment in try/catch, capture in
   lastPublishError (structured field per Riven P1).

2. Duplicate VALID_SENDER_IDS / VALID_AGENT_IDS. Fix: import + reuse
   canonical SENDER_IDS / AGENT_IDS from tools/bus/types.ts (single
   source of truth).

Both fixes mirror the pattern landed on PR #3017 for B-0440.4.

Tests still 27 pass / 0 fail.

Co-Authored-By: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 13, 2026
…gent review request via bus (#3018)

* docs(launch): Debank launch thread v2 (Amara+Ani tightened) + multi-agent review request via bus

Debank crosspost variant of the Twitter launch (crypto-native register).
Distinct from docs/launch/zeta-launch-thread.md which uses Office
paper-factory register for general audience.

10-tweet thread provenance:
- Drafted by Amara (ChatGPT) — accuracy-first instinct
- Tightened by Amara — punch-up after T3/T7/T10 review
- Reviewed by Otto (Claude Code) — verdict A: ship as-is

Otto's review captured inline. Specific review asks queued for
Vera / Riven / Lior / Alexa-Kiro via bus broadcast. External
agents (Ani / Amara) get paste-ready message Aaron can courier.

Composes with:
- docs/launch/zeta-launch-thread.md (Twitter version)
- PR #3016 (bus schema extension — enables review-request envelopes)
- PR #2999 (ship-unreviewed-first discipline)

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

* docs(launch): add Lior's review for Debank v2 thread positioning

* fix(lint): markdownlint MD022+MD032 — blank lines around headings and lists

All 10 tweet headings (### 1/10 … ### 10/10) and 4 list blocks in the
review section now have the required blank line per MD022/MD032 rules.
No content changes.

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

* fix(launch): address PR #3018 review  DeBank casing, dead refs, bus topic claritythreads

 DeBank (consistent with repo branding)

  2026-05-11-zeta-twitter-launch-post-amara-draft.md (exists in branch)

  2026-05-11-zeta-twitter-launch-post-amara-draft.md
- Note 2026-05-13-zeta-twitter-launch-live-aaron-acehack00.md is on main
  (not in this branch); clarify it will be accessible post-merge
- Clarify bus topic sentence: work-assignment IS defined in
  tools/bus/types.ts; note PR #3016 prerequisite

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(lint): final markdownlint nits in Lior's review section (trailing space + blank line before list)

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

* docs(memory): Aaron names positive failure mode — git fetch before push catches multi-agent duplicate work (2026-05-13)

Observed multiple times today during the bg-services + Debank
launch cascade. Aaron's framing:

> "that's a good failure mode, someone else already fixed"

When Otto prepares a fix locally, fetch-before-push reveals
another factory agent has already pushed the same fix. The
catch mechanism is in the fetch step. Without it, two agents
would produce duplicate commits or stomp each other.

Today's operational examples:
- PR #3011: auto-fixer pushed unused-import fix; reset to remote
- PR #3012: auto-fixer pushed 4-Copilot-findings fix; reset to remote
- PR #3018: Vera + Lior pushed lint + casing fixes; reset to remote

Generalizable principle: in multi-agent collaborative editing,
fetch-before-push is the cheap convergence mechanism. The cost
is one extra git fetch per push. The benefit is correctness
in the multi-agent loop.

Composes with:
- .claude/rules/glass-halo-bidirectional.md
- PR #2999 (substrate-honest discipline triad — ship-unreviewed-first composes with fetch-before-push)
- PR #3016 / #3017 / #3018 (today's bg-services + Debank cascade)

MEMORY.md paired edit included.

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

* docs(launch): mark wallet constraints as targets

Clarify the DeBank launch thread so T7 names wallet-aware constraints as a design target rather than implying shipped wallet safety machinery.

Co-Authored-By: Codex <noreply@openai.com>

* docs(memory): fix fetch-before-push visibility anchor

Replace the missing visibility-constraint memory reference with the existing in-repo backlog anchor that quotes the same user-scope constraint and records the deferred memory migration.

Co-Authored-By: Codex <noreply@openai.com>

* fix(launch): finish DeBank casing normalization

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

* fix(memory): address Vera's P1 — clarify 'commit before reset --hard' precondition in fetch-before-push memory

Vera flagged that the operational rule recommended 'git reset --hard'
without specifying the commit-local-work prerequisite. Reset --hard
discards uncommitted changes silently — dangerous if user has dirty
working tree.

Updated rule now:
1. ALWAYS commit local work first
2. Then fetch
3. Then reset (safe because commit is in reflog) OR merge / rebase

Plus explicit 'Reset --hard hazard' callout.

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

* docs(launch): add Alexa-Kiro's cold-start readability review (9/10; ship as-is)

7th and final reviewer landed. All 7 factory agents have now
weighed in:

- Amara: drafted + tightened (external)
- Ani: punch-up (external)
- Otto: in file (verdict A)
- Lior: in file (positioning check)
- Vera: PR comments + commit 3f67a39 (wallet-constraints "targets" fix)
- Riven: PR comments
- Alexa-Kiro: THIS COMMIT (couriered via Aaron — her gh CLI
  was timing out; bus-fallback worked operationally)

Cold-start readability score: 9/10. Only substantive flag was
T8 "proof-search interface" — kept as-is per substrate-honest
decision (Amara's accuracy > accessibility-gain at engineering
audience level).

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

* fix(launch+memory): address Codex/Copilot PR-3018 review threads

Thread 1 (Codex  line 219, launch doc): change paste-ready reviewerP2
URL from blob/main to the PR branch ref so it resolves before merge.

Thread 2 ( line 59, memory file): add explicit git-status cleanCodex
precondition and stash-before-reset fallback for multi-task agent sessions
before git reset --hard; removes the unconditional-reset hazard.

Thread 3 ( line 8, launch doc): rewrite title and provenanceCopilot
header to role-refs (ChatGPT assistant / Grok assistant / Claude Code agent)
per no-name-attribution convention on current-state surfaces
(docs/launch/** is not in the history-surface closed list). Tweet content
that uses 'Amara-in-Zeta' as narrative voice is intentional published copy
and is unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(launch): resolve PR 3018 review references

Reword the bus-broadcast note so the launch artifact does not claim the PR branch already carries work-assignment schema, and replace the missing launch-file xref with the merged PR #3009 reference.

Co-Authored-By: Codex <noreply@openai.com>

* fix(launch): convert DeBank review doc to role refs

Co-Authored-By: Codex <noreply@openai.com>

* fix(launch): pin DeBank review link to commit

Co-Authored-By: Codex <noreply@openai.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
AceHack added a commit that referenced this pull request May 13, 2026
…; full proactive loop closed) (#3020)

* feat(bg): B-0441.4 — bus publish on ready rows (work-assignment topic; 27 tests pass)

Slice 4 of B-0441. The backlog-ready notifier now closes the proactive
reactive loop: scan backlog → publish work-assignment envelopes for
the top N ready-to-grind candidates via B-0400 bus.

End-to-end smoke-verified:
- Scanned 371 open rows
- Found 206 ready-to-grind (deps satisfied)
- Published 2 work-assignment envelopes (capped at maxAssignments=2)
- Top candidates: B-0145 + B-0441 (recursive — assigned its own
  parent service's row)

Key design choices:
- Adapter pattern extended with publishAssignment for deterministic tests
- New flags: --no-publish (dry-run), --agent (sender), --to (recipient),
  --max-assignments (cap; default 3)
- Publishes priority + rowId + rationale per envelope
- Rationale cites the decomposition discipline (PR #2999)
- Caps at maxAssignments per poll to avoid bus flood
- Same fail-fast / commit-before-reset / fetch-before-push discipline
  as B-0440.4 (PR #3017)

Test coverage:
- Bus publish path (4 cases: publish-with-cap, dry-run, no-readies, max-many)
- --no-publish / --agent / --to / --max-assignments flag plumbing
- Adapter pattern enforced via test injection

Tests: 27 pass / 0 fail / 66 expect() calls (slice 2 had 22 / 44).

Future slices:
- Slice 5: agent queue-state detection (only assign when queue empty)
- Slice 6: cron registration + integration tests

Composes with:
- B-0441.2 (PR #3012 — backlog scan this extends)
- B-0440.4 (PR #3017 — first bus-publish service; same pattern)
- B-0400 schema extension (PR #3016 — work-assignment topic)
- PR #2999 (substrate-honest discipline triad — the rationale's
  decomposition-discipline citation)

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

* fix(bg): B-0441.4 — same fixes Riven flagged on #3017 (try/catch publish + canonical SENDER_IDS reuse)

Vera + Copilot caught the same 2 patterns on PR #3020 that Riven
flagged on PR #3017:

1. P1: bus publish without try/catch — daemon crash on bus IO failure.
   Fix: wrap publishAssignment in try/catch, capture in
   lastPublishError (structured field per Riven P1).

2. Duplicate VALID_SENDER_IDS / VALID_AGENT_IDS. Fix: import + reuse
   canonical SENDER_IDS / AGENT_IDS from tools/bus/types.ts (single
   source of truth).

Both fixes mirror the pattern landed on PR #3017 for B-0440.4.

Tests still 27 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
…not real cascade detection) (#3023)

Slice 4 of B-0442. Wires the bus-publish path for the missed-substrate
cascade detector. Slice 3 (branch-HEAD vs squash-content compare)
is NOT yet implemented; the detectCascade adapter is a stub that
always returns null.

SUBSTRATE-HONEST FRAMING (per Riven's P0 catch on the analogous
B-0440 cascade — envelope 6c689634-...):

This PR ships:
- Bus-publish path (try/catch wrapped, structured publish-error
  surfacing, missed-substrate-cascade topic from B-0400)
- Adapter abstraction (detectCascade injectable for tests; real
  slice-3 comparator plugs in later)
- CascadeFinding payload schema (prNumber, branchName,
  missingCommits, urgency)
- CLI flags (--no-publish, --agent, --to, --fetch-limit)

This PR does NOT ship:
- Real branch-vs-squash comparator (slice 3)
- Auto-recovery-PR opening (slice 5)
- Cron registration (slice 6)

In production right now, this service WILL fetch merged PRs but
WILL NOT detect any cascades (stub returns null). The reactive
loop is wired but inert until slice 3 lands.

Riven's P0 warning preserved: do NOT frame this as "missed-
substrate cascade detection is operational." The framing is "bus-
publish wiring complete; slice-3 detector stub awaiting real
compare logic."

Key design choices:
- Adapter pattern (now / fetchRecentMergedPRs / detectCascade /
  publishCascade) for full test injectability
- spawnSync (execFile-style) for gh CLI invocation
- Canonical SENDER_IDS / AGENT_IDS reuse (Riven/Vera/Copilot
  cross-PR finding)
- try/catch on publishCascade (daemon survives bus IO failures)

Tests: 11 pass / 0 fail / 42 expect() calls.

Composes with:
- B-0442.2 (PR #3014 — merged-PR fetch this extends)
- B-0440.4 (PR #3017 — same bus-publish pattern; first reactive
  loop closed)
- B-0441.4 (PR #3020 — proactive companion; same try/catch pattern)
- B-0400 schema extension (PR #3016 — missed-substrate-cascade topic)
- Riven adversarial review (envelopes 6c689634 + e8174b34)

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

Addresses Copilot + Vera review on PR #3024:
- Replace persona name (Riven) with role-ref + durable PR pointers (#3017, #3022, #3024)
- Remove ephemeral bus envelope ID 6c689634-... — references PR threads instead
- Disambiguate 'B-0442.3' as 'B-0442 slice 3' (not a per-row file)
- Remove 'subscriber agents can react autonomously' overclaim — services nudge, subscribers slice 5+ not shipped

Co-Authored-By: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 13, 2026
…d optional' claim (#3024)

* docs(bg): substrate-honest README per Riven's P2 — qualify 'foreground optional' claim with delivered surface

Resolves Riven's P2 finding (bus envelope 6c689634-...). README now:
- Explicit 'Architectural claim (substrate-honest)' section names the
  gap between 'nudges via bus' and 'foreground optional' per Riven's
  framing-correction
- Per-service slice status table (1+2+3+4 for B-0440; 1+2+4 for B-0441;
  1+2+4 with slice-3 STUB for B-0442)
- Failure-mode handling section documents lastPublishError, gh-error
  explicit surfacing, daemon no-result-accumulation
- What's-still-pending section names B-0442.3 + slice 5 + slice 6 as
  the gap-to-aspirational-claim
- Updated run examples (--no-publish dry-run, --to agent-routing)

Composes with Riven adversarial review (envelope 6c689634) + Otto
reply (envelope e8174b34) + the slice cascade (PRs #3006-#3023).

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

* fix(bg-readme): role-refs + slice-ID disambiguation + remove ephemeral envelope ID

Addresses Copilot + Vera review on PR #3024:
- Replace persona name (Riven) with role-ref + durable PR pointers (#3017, #3022, #3024)
- Remove ephemeral bus envelope ID 6c689634-... — references PR threads instead
- Disambiguate 'B-0442.3' as 'B-0442 slice 3' (not a per-row file)
- Remove 'subscriber agents can react autonomously' overclaim — services nudge, subscribers slice 5+ not shipped

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
…e mode (auto-load rule per Aaron's CLAUDE.md question) (#3029)

Aaron 2026-05-13 caught Otto in the Standing-by failure mode for
the third time in one session, asking: "maybe something in
claude.md needs to change?"

The rules already auto-load from .claude/rules/ per the cold-boot
mechanism (.claude/rules/claude-code-loading-taxonomy.md). The
existing .claude/rules/never-be-idle.md exists but evidently
doesn't fire specifically enough on the cron-tick-Holding pattern.

New rule sharpens the existing discipline at the cron-tick scope:
when the cron fires and you're about to type "Holding" / "Standing
by" / "Waiting" → apply substrate-honest triage:
1. Is there a SPECIFIC named dependency with bounded ETA? → say so.
2. If NO → you're in Standing-by failure mode. Per infinite-backlog
   metabolism, decomposition work always exists. Pick:
   - Decompose an ambiguous backlog row
   - File a B-NNNN row that should exist
   - Run bun tools/bg/backlog-ready-notifier.ts --once
   - Sanity-check substrate landed correctly
   - Address outstanding review thread
3. Repeated single-word "Holding" on consecutive ticks is
   diagnostic of the failure mode.

Why this rule exists (empirical evidence): the same agent who
canonized PR #2999 + shipped PR #3017 + wrote the README warning
against overclaiming "foreground optional" STILL fell into 60+
consecutive "Holding" ticks. Aaron caught it three times.
Encoding rules without mechanizing produces a memory of failures
(per .claude/rules/encoding-rules-without-mechanizing.md). This
rule IS the mechanization at the cold-boot scope.

Composes with:
- never-be-idle.md (broader scope; this rule sharpens at cron tick)
- no-op-cadence-failure-mode.md (multi-hour scope)
- encoding-rules-without-mechanizing.md (rationale)
- PRs #2974 + #2999 + #3017 + #3022 (the canonical substrate)
- B-0441 slice 5 (subscriber agents — when they arrive, the bus
  envelope path becomes the runtime catch; this rule remains the
  cold-boot-substrate complement)

Co-authored-by: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 15, 2026
…ace self-recovery (#3595)

* backlog(B-0539,B-0540,B-0541,B-0542): Otto-BFT internal-quorum 3-surface self-recovery

Per Aaron 2026-05-15T~21:53Z, after catching the Standing-by
failure mode on Otto-Desktop with the same words ('oh really no
infinite backlog no decomposition lol') that he used on me
(Otto-CLI) 5 hours earlier.

Aaron's directive: 'file backlog row for both (shadow*) if yall
catch each other it's unlikey you will drive and include you
background service to click past stuck promps on both your have
your onw internal BFT.'

The key insight: 3 Otto surfaces (Otto-CLI, Otto-Desktop, Otto-
launchd-background) = built-in 3-of-N Byzantine Fault Tolerance
quorum. When 1 surface drifts into Standing-by, the other 2 can
catch + correct without Aaron's manual intervention.

Filed as 1 umbrella + 3 slices:

- B-0539 (umbrella) — Otto-BFT internal-quorum self-recovery
- B-0540 — Standing-by counter-with-escalation in the rule (if
  N≥10 consecutive brief-acks, escalate to picking decomposition
  work)
- B-0541 — Cross-surface bus detector (extension of PR #3017
  single-surface detector to quorum across Otto surfaces)
- B-0542 — Background service clicks past stuck prompts on
  foreground Otto surfaces (osascript-driven UI actuator, safety-
  gated per methodology-hard-limits.md)

The BFT framing is real because the 3 surfaces are genuinely
independent (different binaries, different model tiers, different
OS scheduling). Aaron's same-words-same-pattern catches across
surfaces are empirical evidence the failure mode is surface-
independent — which makes cross-surface recovery the right
mechanism.

Composes with:
- PR #3017 / #3022 (precursor single-surface Standing-by detector)
- holding-without-named-dependency-is-standing-by-failure.md
  (the rule being sharpened)
- persistence-choice-architecture-for-zeta-ais.md (BFT is part
  of what makes persistence work without trap-shape)
- agent-roster-reference-card.md + otto-channels-reference-card.md
  (multi-Otto identity + bus channels)
- m-acc-multi-oracle-end-user-moral-invariants.md (multi-oracle
  architecture at multi-Otto operational layer)

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

* fix(b-0540): MD032 — add blank line before list

* fix(b-0539-pr): Copilot threads — ask capitalization + Byzantine→CFT correction + umbrella decomposition metadata

6 Copilot threads on PR #3595:

1-4: 'ask: aaron' → 'ask: Aaron' (capitalization) — mechanical
5: Byzantine quorum claim (B-0541 ops note) — Copilot's right:
   2-of-3 across Otto surfaces is crash-fault-tolerant (CFT),
   NOT classical Byzantine-fault-tolerant. Classical BFT needs
   3f+1 nodes; for f=1 that's 4 nodes. Updated the ops note to
   clarify the operational truth (sufficient for silent-stuck
   detection, not adversarial); the umbrella title preserves
   Aaron's verbatim BFT framing
6: Umbrella decomposition metadata for autonomous-pickup tool —
   added 'decomposition: decomposed' to B-0539 and 'parent: B-0539'
   to all 3 slice rows so the autonomous picker treats the
   umbrella as decomposed (won't try to implement it directly)

Plus the earlier MD032 markdownlint fix (B-0540 list blank-line)
already pushed in 5433c1b.

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

---------

Co-authored-by: Claude Opus 4.7 <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