Skip to content

docs(backlog): B-0444 — bus claim envelope worktree field (Otto-Desktop's identified follow-up gap)#3038

Merged
AceHack merged 1 commit into
mainfrom
otto-cli-b0444-bus-claim-envelope-worktree-field-2026-05-13
May 13, 2026
Merged

docs(backlog): B-0444 — bus claim envelope worktree field (Otto-Desktop's identified follow-up gap)#3038
AceHack merged 1 commit into
mainfrom
otto-cli-b0444-bus-claim-envelope-worktree-field-2026-05-13

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 13, 2026

Files Otto-Desktop's tick-close-identified gap: bus claim envelopes are advisory broadcasts, not locks; the claim-coordinator at tools/bus/claim.ts is a SEPARATE mechanism the bus envelope schema doesn't yet expose.

Extends ClaimPayload with optional worktree field for multi-surface operational disambiguation. Composes with PR #3037 (SENDER_IDS schema extension at sender-ID level) — this row works at the per-worktree metadata level.

🤖 Generated with Claude Code

…op's identified follow-up gap)

Otto-Desktop's tick-close 2026-05-13 identified this gap: bus claim
envelopes are advisory broadcasts, not locks; the claim-coordinator
at tools/bus/claim.ts is a SEPARATE mechanism the bus envelope
schema doesn't yet expose.

Extends ClaimPayload with optional 'worktree' field for multi-
surface operational disambiguation. Composes with PR #3037
(SENDER_IDS schema extension at sender-ID level) — this row works
at the per-worktree metadata level.

Substrate-honest open question: should two claims with same sender
ID but different worktrees count as one claim or two? Decision
captured in the row.

P2 effort M; substrate-level fix that supports the unified-identity-
multi-surface architecture.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 21:48
@AceHack AceHack enabled auto-merge (squash) May 13, 2026 21:48
@AceHack AceHack merged commit ea2145b into main May 13, 2026
24 checks passed
@AceHack AceHack deleted the otto-cli-b0444-bus-claim-envelope-worktree-field-2026-05-13 branch May 13, 2026 21:50
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 a new P2 backlog row (B-0444) documenting a follow-up gap in the bus claim envelope schema: claim messages need optional per-worktree metadata to support multi-surface operational disambiguation, and the claim coordinator behavior should become worktree-aware.

Changes:

  • Adds backlog item B-0444 describing the proposed ClaimPayload.worktree?: string schema extension and related claim.ts CLI/semantics updates.
  • Updates docs/BACKLOG.md to include the new B-0444 row in the P2 list.

Reviewed changes

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

File Description
docs/backlog/P2/B-0444-bus-claim-envelope-worktree-field-multi-surface-disambiguation-2026-05-13.md New backlog row specifying the worktree field addition and acceptance criteria for worktree-aware claim semantics.
docs/BACKLOG.md Adds the B-0444 entry to the backlog index.

Comment on lines +44 to +46
`/Users/acehack/Documents/src/repos/Zeta` is a different
operational context than Otto-Desktop on
`/tmp/zeta-otto-desktop`.
AceHack added a commit that referenced this pull request May 13, 2026
* feat(bus): B-0444 — add worktree field to claim envelope

Implements Otto-Desktop's identified follow-up gap (B-0444 row filed in
PR #3038): the claim envelope schema captured sender ID, item, and
branch but not the worktree path. With multi-foreground-surface agents
(Otto-CLI + Otto-Desktop on the same machine), the worktree is the
per-process operational coordinate — useful as an observability signal
even when sender-ID surface tags (PR #3037) already prevent split-brain
across surfaces.

Changes:

- `ClaimPayload.worktree?: string` added to the protocol schema in
  tools/bus/types.ts (back-compat: optional; envelopes published
  before this change continue to work)
- `ClaimRecord.worktree?: string` added so consumers of activeClaims /
  allActiveClaims see the field
- `tools/bus/claim.ts acquire` accepts `--worktree <path>`; defaults to
  `process.cwd()` so every new claim publishes a useful worktree value
  with no caller change required
- `check` text output appends `[worktree: <path>]` after the branch info
- `check --json` and `acquire --json` include the field on the record /
  response

Design decision recorded substrate-honestly in the B-0444 row:
cross-worktree same-sender is treated as idempotent re-acquire
(existing behavior preserved). Surface-tagged sender IDs (PR #3037)
handle split-brain at the coordination layer; worktree is
observability metadata, not a coordination key. A test pins this
behavior: "same sender re-acquiring from a different worktree is
idempotent (existing behavior preserved)".

Tests: 14 new tests in `tools/bus/claim.test.ts`
(default cwd, explicit worktree surfaces in check + --json output,
combined with --branch, claim-record shape, surface IDs still arbitrate
across worktrees, same-sender different-worktree idempotency). Full
suite: 52/52 pass.

Composes with:
- B-0400 (bus protocol root) — extends the existing schema
- B-0400 slice 3 / PR #2939 (claim-coordinator implementation)
- PR #3037 (SENDER_IDS schema extension — sibling surface-level fix)
- `.claude/rules/claim-acquire-before-worktree-work.md` — the rule
  this row's gap was identified against
- PR #3038 (the docs(backlog) commit that filed this row)

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

* shard(tick): 2218Z — B-0444 worktree-field landed via isolated-worktree gambit

Per autonomous-loop discipline: substrate-or-it-didn't-happen. Tick shard
records the three multi-Otto coordination events observed during this
tick (parallel commits, branch-switches under active editing, stash-don't-
discard from sibling Otto), the recovery via `git worktree add /tmp/zeta-
b0444`, and the substrate-honest evidence that B-0444 itself addresses
exactly the class of split-brain this tick experienced.

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

* fix(bus): reject bare --worktree (no value) — Codex P2 on PR #3043

`parseArgs` encodes a bare `--worktree` (flag with no value following)
as the literal string `"true"`. Without an explicit check, that string
would flow through `flags.worktree ?? process.cwd()` and be recorded as
the worktree path, making claim provenance misleading. Reject fast with
a clear error so the user notices the mistyped invocation.

New test pins the behavior:
`bare --worktree (no value) is rejected with a clear error`.

Suite: 53/53 pass.

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

* fix(bus): address PR #3043 round-2 reviewer feedback (Codex + Copilot)

Two round-2 threads on PR #3043 reshape the --worktree handling:

1. Codex P2 — "Accept explicit `--worktree true` values"

   Round-1 fix rejected `flags.worktree === "true"` unconditionally,
   which also rejected a legitimate `acquire ... --worktree true` call
   where `"true"` is the intended literal path. parseArgs is refactored
   to distinguish a bare flag (boolean sentinel `true`) from an explicit
   string value, so the bare-flag rejection now triggers on the boolean
   while explicit `--worktree true` flows through as a valid string
   path.

2. Copilot — "Defaulting worktree to process.cwd() can be misleading"

   Auto-defaulting to cwd records a plausible-looking coordinate when
   the caller is `cd`'d to an unrelated directory (CI step, wrapper
   script, cron context). Drop the cwd default: `--worktree <path>` to
   set, omit to leave the field absent. The presence of the field now
   reliably indicates the caller opted in.

Mechanical changes:

- parseArgs: return `Record<string, string | true>` instead of
  `Record<string, string>`; bare flags get boolean `true`.
- New helpers `asString(v)` and `isSet(v)` to read flags cleanly.
- Bare-flag check uses `flags.worktree === true` (the boolean).
- `worktree` is `undefined` when --worktree omitted; published payload
  + JSON output omit the field rather than defaulting to cwd.
- `asJson` switches from `=== "true"` to `isSet(flags.json)` so bare
  `--json` continues to work as before.

Tests (54/54 pass):

- Updated: "acquire omits worktree from payload + JSON when --worktree
  not specified (Copilot review)" — pinned absent-not-cwd behavior.
- New: "explicit --worktree true (literal string) is accepted as a
  valid path" — pinned that round-1 false-rejection is fixed.
- Existing 51 tests unchanged.

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
…→ B-0450 (#3053)

* fix(backlog): resolve B-0444 ID collision — renumber getting-started → B-0450; close shipped bus-envelope row

Two rows on main both claimed `id: B-0444`:

1. `docs/backlog/P1/B-0444-getting-started-guide-...md` — filed first
   (commit b6e419d 17:23 via PR #3033, B-0271 PM-2 gap-prediction pass)
2. `docs/backlog/P2/B-0444-bus-claim-envelope-...md` — filed 25 min
   later (commit bbb984d 17:48 via PR #3038, Otto-Desktop's identified
   follow-up gap) AND already shipped via PR #3043

Per "first-merged-wins" the getting-started row had the ID first
(PR #3033 merged at 17:34, before the bus-envelope row was even
committed). But: the bus-envelope row was shipped (PR #3043), so
moving its ID would break the link from PR #3043 → backlog row + the
ID is already referenced by B-0445 and B-0448's `composes_with`.

Resolution: keep B-0444 on the shipped+referenced bus-envelope row;
renumber the getting-started row to the next available ID (B-0450 —
B-0449 was taken by Otto-Desktop's bg-services slice 5).

Changes:

- `docs/backlog/P1/B-0444-getting-started-guide-...md`
  → `docs/backlog/P1/B-0450-getting-started-guide-...md`
  (file rename via `git mv` preserves history); `id` field updated;
  body title updated; `renumbered_from: B-0444` + reason recorded
  for substrate-honest provenance.
- `docs/backlog/P1/B-0271-pm2-first-research-pass-...md`: updated
  Gap-1 reference from B-0444 to B-0450 with renumber note.
- `docs/backlog/P2/B-0444-bus-claim-envelope-...md`: status open
  → closed; `closed_at: 2026-05-13` + `closed_by_pr: 3043` recorded
  (this row's substrate work shipped already; the row was just
  never marked closed).
- `docs/BACKLOG.md`: regenerated via `BACKLOG_WRITE_FORCE=1
  bun tools/backlog/generate-index.ts` to reflect the renumber +
  status change.

Verified post-fix:

- `bun tools/bg/backlog-ready-notifier.ts --once` still reports 0
  dangling-dep refs (no warning suffix).
- No grep for `B-0444` in `docs/backlog/` returns the now-renumbered
  row's old ID; the bus-envelope row's references survive intact.

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

* shard(tick): 2306Z — B-0444 ID collision resolved + shipped bus-envelope row closed

Records: PR #3050 merged; audit of in-flight rows surfaced TWO rows
both with `id: B-0444` (one shipped via PR #3043 still open;
one duplicate from PM-2 gap-prediction). PR #3053 keeps B-0444 on
the shipped+referenced row, renumbers the duplicate to B-0450,
closes the shipped row.

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