feat: add symmetric peer-conductor mesh substrate - #1265
Conversation
…esh-20260718 # Conflicts: # cli/src/limen/dispatch.py # cli/tests/test_current_session_fanout.py # cli/tests/test_dispatch.py # cli/tests/test_substrate_repo_product_fanout.py # cli/tests/test_tabularius.py # cli/tests/test_workstream_command.py # docs/tabularius-writer-audit.md # docs/workstream-kickstart.md # mcp/src/limen_mcp/server.py # scripts/check-main-green.py # scripts/claim-task.py # scripts/current-session-fanout.py # scripts/dispatch-continuity-check.py # scripts/heal-dispatch.py # scripts/jules-land.py # scripts/lib/workstream-capsule.sh # scripts/quicken.py # scripts/reclassify-needs-human.py # scripts/recover.py # scripts/routine-freshness-audit.py # scripts/start-worktree-session.sh # scripts/task-writer-audit.py # web/worker/src/index.js
|
Important Review skippedToo many files! This PR contains 164 files, which is 64 over the limit of 100. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (164)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…esh-20260718 # Conflicts: # CLAUDE.md # cli/src/limen/tabularius.py # cli/tests/test_mcp_server.py # cli/tests/test_tabularius.py # docs/agent-instruction-standard.md # docs/tabularius-record-keeper.md # docs/tabularius-writer-audit.md # mcp/src/limen_mcp/server.py # scripts/check-agent-docs.py # scripts/self-heal.py # scripts/tabularius-organ.py # web/api/main.py # web/api/tests/test_main.py # web/worker/src/index.js
|
Exact-head integration repair receipt —
The isolated worktree is clean and matches the pushed branch. Fresh exact-head remote CI is now the PR-owned heavy gate; no production deploy or campaign execution is authorized until the draft gates in the PR body close. |
|
Exact-head closeout receipt for
The PR deliberately remains draft: production auth/capability delivery, the live 5x5 matrix, and the whole-PR action campaign remain authority-gated and are durably owned by the continuation capsule and the owners named in the PR body. |
Closeout receipt — 2026-07-19
Closeout boundary: this PR deliberately remains draft. Anthony owns any merge or deployment; none was performed here. |
Bootstrap correction — 2026-07-19The prior closeout command incorrectly invoked the installed Head This comment supersedes the bootstrap command in the earlier closeout relay. Exact-head CI is pending on the correction. |
… dumps
The three 2026-07-18-pass-{1,2,3}.json files (~1.45MB / ~34k lines each)
are machine-generated census receipts. They inflated PR #1265 to +121k lines
across 169 files, making the ~18k-line peer-conductor-mesh feature unreviewable.
Their findings (denominators, key deltas, digests, zero_growth verdicts) already
live in reviewable prose in README.md; the raw leaf dumps are regenerable via
scripts/conduct-pr-campaign.py. Untrack them and gitignore the pattern so the
generator never re-commits them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record correction — premature closeout retracted (2026-07-19)The earlier "CLOSEOUT COMPLETE" claim on this PR was not accurate at the time it was made: the PR was (and remained) a draft with checks still running, so it could not have been merged. Per this repo's charter ( What was actually wrong, and now fixed (head
Correct done-state for this PR: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f9e47578d8
ℹ️ 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".
| max_depth=2, | ||
| ), | ||
| effect="read", | ||
| task_id=root_task_id, |
There was a problem hiding this comment.
Do not attach synthetic task IDs to unseeded fanout runs
When --conduct uses the Worker-backed broker, every non-compatibility packet with a task_id emits a task.dispatched projection, and that projection rejects task IDs that are absent from the canonical board. This root ID is synthetic, live --conduct explicitly forbids seed-task creation, and the seed specs do not create a ROOT row, so the first client.submit(root_packet) fails before any fanout can be reserved. Leave task_id unset for these non-board runs or create/project the task before reserving.
Useful? React with 👍 / 👎.
| f" FENCE {selection.task_id}: Jules claim changed while PR work ran; left {pr_url} for reconciliation" | ||
| ) | ||
| return False | ||
| task = _advance_landing_execution(tasks_path, task, selection) |
There was a problem hiding this comment.
Keep landing resume state parseable after advancing
If this in_progress projection succeeds but the following terminal projection fails or the process crashes, the next run cannot resume the landing transaction: _persisted_landing_selection() only accepts post-intent entries whose landing_event is attempt, so the inserted start row makes it report that the owner changed and can leave an already-created PR/held task for manual reconciliation. Either fold the start and terminal receipt into one projection or make the resume parser accept this durable start event.
Useful? React with 👍 / 👎.
| institutio/github/estate.private.yaml | ||
| # whole-PR campaign census receipts (generated locally by scripts/conduct-pr-campaign.py; ~1.5MB | ||
| # each — findings live in README.md, raw leaf dumps are regenerable and must not bloat the diff) | ||
| docs/receipts/pr-campaign/*.json |
There was a problem hiding this comment.
Do not ignore the PR-campaign receipt target
campaign_packets() points both the predicate and receipt_target at docs/receipts/pr-campaign/<digest>.json, and scripts/conduct-pr-campaign.py census --output writes that exact receipt. Ignoring *.json here means the generated campaign receipt cannot be added and committed normally, so the advertised git receipt/predicate is unreachable unless every executor knows to force-add an ignored file.
Useful? React with 👍 / 👎.
| }[match[2]]; | ||
| return json(await this.service.call(operation, { | ||
| run_id: decodeIdentifier(match[1], "run_id"), | ||
| session_id: bodyIdentifier(body, "session_id"), |
There was a problem hiding this comment.
Bind run-control requests to authenticated session identity
For adopt, cancel, and request-stop, the Worker authenticates only the shared conduct bearer token and then trusts this caller-supplied session_id; the keeper only compares that string to the run's conductor. In environments where peers share LIMEN_CONDUCT_TOKEN, any peer can copy another session ID from graph/capabilities and cancel or signal that non-human-protected conductor's work. Derive the requester from per-session auth or require a session capability instead of accepting it from the request body.
Useful? React with 👍 / 👎.
| body: JSON.stringify({ | ||
| message: `limen conduct: ${event.kind} ${event.task_id}`, | ||
| content: encodeBase64(YAML.stringify(board)), | ||
| branch, |
There was a problem hiding this comment.
Route board projections off protected main
With the deployed web/worker/wrangler.toml setting LIMEN_GITHUB_BRANCH = "main", this Contents API payload writes tasks.yaml directly to main. In the repo's no-bypass/protected-main setup, every broker-backed task mutation either gets rejected by branch protection or bypasses the merge-queue policy if the token can write, so the projection receipt is not a safe durable closeout. Publish through the projection PR/merge-queue branch instead.
Useful? React with 👍 / 👎.
| throw new ConductProjectionError(`task ${taskId} already exists`, 409); | ||
| } | ||
| const supplied = clone(intent.task || {}); | ||
| validateTaskShape(supplied, taskId); |
There was a problem hiding this comment.
Validate remote task upserts against the task contract
This is the Worker-backed task.upsert gate immediately before the GitHub projection write, but validateTaskShape() checks only id/title/status. A direct conduct packet can therefore commit a row with invalid canonical fields such as budget_cost: 0, missing predicate/receipt metadata, or malformed labels, whereas the local Python projection runs Task.model_validate() and validate_intake_contract(). That can poison the canonical board for downstream loaders.
Useful? React with 👍 / 👎.
| claims = ( | ||
| () | ||
| if phase == "planner" | ||
| else (ResourceClaimV1(key=f"repo/{repo}/write", mode="exclusive"),) |
There was a problem hiding this comment.
Narrow executor claims so same-repo fanout can reserve
Every executor packet gets an exclusive repo/<owner>/<repo>/write lease, while reserve_fanout() reserves all executor children before exposing any lease token. When two selected executor lanes target the default owner repo — the normal case because owner_packet_for_theme() returns organvm/limen for every theme — the second child conflicts with the first unstarted lease and the entire fanout rolls back. Use path/branch/worktree-scoped claims or group same-repo work serially.
Useful? React with 👍 / 👎.
| this.state.work_key_index[packet.work_key] = duplicateRunId; | ||
| this.mutated = true; | ||
| } | ||
| return this.submitResult(run, true); |
There was a problem hiding this comment.
Return a usable lease token on idempotent submit retries
If a native submit succeeds in the keeper but the HTTP response is lost, the caller's safe retry lands in this duplicate branch and receives only submitResult(), which deliberately omits capability_token even though the lease is still reserved/active. That leaves the executor unable to heartbeat or report the run, so the lease/task sits until expiry. Store/replay a recoverable capability or require a caller-supplied lease token for idempotent retries.
Useful? React with 👍 / 👎.
| fi | ||
| local _ | ||
| while true; do | ||
| if ! limen "${register_args[@]}"; then |
There was a problem hiding this comment.
Do not advertise cell sessions as workers without an executor
The replacement _registration-loop only calls limen conduct register (defaulting to accepting_work=true with the lane's execute/code capabilities) and then sleeps or exits; it no longer starts heartbeat.sh or any native worker in the cell. Once this registration is healthy, the broker can assign work to cell-$slug, but no process consumes the lease, so the run just expires. Mark these registrations --not-accepting-work until an executor loop is launched, or start the actual worker after registering.
Useful? React with 👍 / 👎.
…esh-20260718 # Conflicts: # .gitignore
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bbd684cd49
ℹ️ 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".
| if (!dryRun) { | ||
| const ids = new Set(candidates.map((task) => task.id)); | ||
| for (const task of doc.data.tasks || []) { | ||
| if (ids.has(task.id)) { | ||
| task.status = "open"; | ||
| appendLog(task, "api", "release-stale", "open", `Released stale claim older than ${hours} hours`); | ||
| } | ||
| for (const candidate of candidates) { | ||
| const current = findTask(doc.data, candidate.id); | ||
| const mutation = await submitTaskMutation(env, { | ||
| kind: "task.status", |
There was a problem hiding this comment.
Filter stale releases before broker reopens
Now that this Worker path actually submits broker mutations, dry_run=false applies status: open to every row returned by releaseStaleCandidates(), which includes both stale Jules claims and in_progress rows. In production that can reopen an off-box Jules run solely by age without remote absence proof, while an in_progress candidate hits the keeper's rejected in_progress -> open transition after any earlier rows in the loop may already have been released; route/hold those candidates before calling submitTaskMutation.
Useful? React with 👍 / 👎.
| registered_at: nowIso(), | ||
| heartbeat_at: nowIso(), | ||
| human_protected: false, | ||
| accepting_work: true, |
There was a problem hiding this comment.
Mark relay sessions non-accepting
The Worker compatibility relay registers worker-owner-compatibility as a healthy accepting session, but it only submits board packets and has no executor loop to heartbeat/report arbitrary leases. Fresh evidence beyond the existing cell registration issue is this deployed Worker relay: after any compatibility mutation, a packet whose required_capabilities is empty (the schema default) satisfies this session's capability filter and can be assigned to api, where it will sit until expiry; register relay submitters with accepting_work: false (or otherwise exclude them from executor selection).
Useful? React with 👍 / 👎.
| return ( | ||
| f"path/{match.group('owner').lower()}/{match.group('repo').lower()}/{match.group('base')}/{prefix}" | ||
| ).rstrip("/") |
There was a problem hiding this comment.
Preserve root path claims as path resources
When the local/SQLite broker sees a root path claim such as path/organvm/limen/main/, this normalization strips it to path/organvm/limen/main; because _PATH_RE requires a slash and prefix, later parse_resource() treats the claim as opaque. For read-mode root-scope reservations that means the broker skips the repository/path authority checks and does not conflict with path/organvm/limen/main/cli, so overlapping local work can be reserved concurrently; keep an explicit root prefix or make _PATH_RE accept the normalized root form.
Useful? React with 👍 / 👎.
| finally: | ||
| _clear_result_receipts(tid) | ||
| save_limen_file(tasks_path, fresh) | ||
| apply_limen_file_sync(tasks_path, fresh, agent="dispatch", session_id="serial-results") |
There was a problem hiding this comment.
Claim before launching serial dispatch
In the serial live path, this is the first broker-backed write, but it runs only after call_agent_dispatch() has already launched the provider. When the local projection is stale or another conductor claimed the task, the keeper rejects this later expected_revision/status transition while the external run or PR already exists, creating duplicate unleased work; reserve the task through the broker before invoking the agent.
Useful? React with 👍 / 👎.
| reservation = apply_limen_file_sync( | ||
| tasks_path, | ||
| fresh, | ||
| agent="dispatch-parallel", | ||
| session_id="reserve", | ||
| ) |
There was a problem hiding this comment.
Avoid partial parallel reservations
This reservation call now expands the selected batch into multiple broker task packets, and apply_limen_file_sync() relays them sequentially. If a later claim is rejected because the remote row or budget moved, the exception path rethrows before launching agents, but any earlier projected claims are already dispatched with budget debited and no worker will run them; make the reservation all-or-nothing or explicitly cancel/refund the accepted claims before aborting.
Useful? React with 👍 / 👎.
| def _submit_task_event(packet: WorkPacketV1) -> dict[str, Any]: | ||
| client = _conduct_client() | ||
| _register_submitter(client, packet.conductor) | ||
| return client.submit(packet) |
There was a problem hiding this comment.
Reject busy MCP task mutations
When a task/resource is already leased, client.submit() returns a normal {status: "busy"} result rather than raising, but this helper passes that through and callers such as agent_claim return a “submitted …” message without any projection receipt. In a two-client claim race the loser therefore appears to have claimed the task even though the board did not change; require an applied/projection receipt before reporting success.
Useful? React with 👍 / 👎.
| native_session_id=os.environ.get("LIMEN_NATIVE_SESSION_ID"), | ||
| native_run_id=identity.native_run_id, | ||
| worktree=os.environ.get("LIMEN_WORKTREE"), | ||
| capabilities=frozenset({"task-submit"}), |
There was a problem hiding this comment.
Use a dedicated MCP relay session
When the MCP server inherits a real LIMEN_SESSION_ID, _mcp_identity() reuses that registered conductor identity and this registration overwrites the broker's stored capabilities with only task-submit. After any MCP task update from such a session, the same conductor may no longer satisfy conduct/execute packets; register task-submit relays under a separate session id or merge with the existing capabilities.
Useful? React with 👍 / 👎.
| for (const event of kernel.projectionEvents) { | ||
| projectionReceipts.push(await this.projectTaskEvent(event)); | ||
| } | ||
| if (projectionReceipts.length && result && typeof result === "object") { | ||
| result.projection_receipts = projectionReceipts; | ||
| const run = kernel.state.runs[result.run_id]; | ||
| if (run) run.projection_receipts = clone(projectionReceipts); | ||
| } else if (result?.run_id) { | ||
| const stored = kernel.state.runs[result.run_id]?.projection_receipts || []; | ||
| if (stored.length) result.projection_receipts = clone(stored); | ||
| } | ||
| if (kernel.mutated) await this.store.save(kernel.state); |
There was a problem hiding this comment.
Persist keeper state before external projections
For broker mutations that emit task projections, the Worker commits the GitHub/inline board projection before storing the updated Durable Object state. If ctx.storage.put() fails or the isolate crashes after a successful projection write, tasks.yaml can show a task as dispatched/done with a conduct run id that the keeper no longer knows about, so executors cannot heartbeat/report and later reconciliation has no authoritative lease; make the state/projection handshake recoverable before acknowledging the external projection.
Useful? React with 👍 / 👎.
| ok, output = run_dispatch_command(command) | ||
| if ok: | ||
| task["status"] = "dispatched" | ||
| append_log(task, req.agent, req.session_id, "dispatched", output or "Dispatched via Limen API") | ||
| spend_budget(data, req.agent, int(task.get("budget_cost", 1))) | ||
| dispatched.append(task) | ||
| claimed_cost += cost | ||
| dispatched.append(claim.task) |
There was a problem hiding this comment.
Record provider output after API dispatch
After a successful live API launch, the command output is discarded and the board keeps only the earlier generic claim log. For Jules or other adapters whose CLI output contains the native session/PR/run URL, stale recovery and harvest will later see only req.session_id instead of the actual provider receipt, making the dispatched task hard to verify or recover; append a broker mutation with the successful output or include it in the claim once the launch succeeds.
Useful? React with 👍 / 👎.
| throw new ConductError("conductor absence has not been proven"); | ||
| } | ||
| } | ||
| if (this.now - asDate(adopter.heartbeat_at) > this.sessionTtlMs || !adopter.accepting_work) { |
There was a problem hiding this comment.
Require conduct capability to adopt runs
When the prior conductor is absent, any healthy accepting_work session can adopt a run even if it registered only executor/review/relay capabilities and lacks conduct. Such a session becomes the recorded conductor and can cancel or stop reserved work while being unable to create valid child packets; require the adopter to advertise the conduct capability before transferring conductor ownership.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 91445b1a7c
ℹ️ 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".
| if (this.now - asDate(conductor.heartbeat_at) > this.sessionTtlMs) { | ||
| throw new ConductError("packet conductor session is not healthy"); | ||
| } | ||
| const neededCapability = packet.execution?.adapter === "tabularius" ? "task-submit" : "conduct"; |
There was a problem hiding this comment.
Require conduct for non-compat tabularius packets
When a relay session has only task-submit, it can still submit any root packet by setting execution.adapter to tabularius; if the packet is not a strict task-compatibility packet, the code continues down the normal reservation path and can reserve executor work or emit task dispatch projections without the conduct capability. Gate task-submit on isTaskCompatibilityPacket(packet) and require conduct for every other packet.
Useful? React with 👍 / 👎.
| or getattr(entry, "landing_terminal", False) is not False | ||
| or getattr(entry, "landing_attempt", None) != attempt_count | ||
| or entry.status != "failed" | ||
| or entry.status != prior_status |
There was a problem hiding this comment.
Keep landing attempts parseable after failures
For the common case where the original Jules claim was dispatched, the first transient landing failure is written with status="failed" in commit_landing_failure(), but resume validation now rejects every post-intent attempt unless its status equals the original prior_status. After one provider failure, the next landing run reports the durable intent as owner-changed instead of retrying toward the finite cap, leaving the held task stuck for manual recovery.
Useful? React with 👍 / 👎.
|
|
||
| if [[ "$launch_codex" -eq 1 ]]; then | ||
| if [[ "$launch_agent" -eq 1 ]]; then | ||
| exec bash "$kickstart" |
There was a problem hiding this comment.
Launch the generated kickstart by its actual path
When scripts/start-worktree-session.sh --agent ... is used, this branch runs after render_workstream_capsule, but kickstart is only a local variable inside that helper and is never set in this script. With set -u, the launch path aborts with an unbound-variable error instead of starting the selected agent; invoke $wt/.limen-workstream/kickstart.sh or have the helper return/export the path.
Useful? React with 👍 / 👎.
| if re.match(r"^\d{4}-\d{2}-\d{2}T", rendered): | ||
| try: | ||
| parsed = datetime.fromisoformat(rendered.replace("Z", "+00:00")) | ||
| return parsed.astimezone(timezone.utc).isoformat().replace("+00:00", "Z") |
There was a problem hiding this comment.
Match Worker revision timestamps exactly
When this API targets the Worker-backed broker, this revision guard serializes exact-second timestamps as ...00Z, while the Worker's canonicalRevision() uses Date.toISOString() and serializes the same value as ...00.000Z. A task that has not changed can therefore be rejected as revision-moved on assign/archive/verify paths just because the caller and broker format UTC differently; emit the same millisecond form or compare parsed timestamps consistently.
Useful? React with 👍 / 👎.
| if (this.state.sessions[requesterSessionId]?.human_protected) { | ||
| throw new ConductError("protected human session cannot be cancelled or signalled through autonomous conduct"); | ||
| } | ||
| if (run.status !== "reserved") throw new ConductError("only reserved, not-started work may be cancelled"); |
There was a problem hiding this comment.
Reject cancelling parents that still own children
When a reserved root or cohort run has already been split, it can still satisfy this reserved check while run.children contains active child leases; cancelling only this row releases the parent lease and marks it cancelled, but leaves descendants reserved under a cancelled parent. In conduct graphs where a conductor cancels after fanout reservation, reject parent cancellation until children are terminal or cascade the cancellation to the descendants.
Useful? React with 👍 / 👎.
|
|
||
| if updated: | ||
| save_limen_file(tasks_path, limen) | ||
| apply_limen_file_sync(tasks_path, limen, agent=agent or "harvest", session_id="harvest") |
There was a problem hiding this comment.
Advance Jules harvest before terminal receipts
Now that harvest results are submitted through the compatibility broker here, legacy Jules harvest still changes tasks directly from dispatched to done or failed when a diff/result file appears. The canonical projection only allows dispatched -> open/dispatched/in_progress, so common completed Jules runs that never logged an in_progress transition will be rejected and remain unharvested; insert the start transition or an authorized repair before submitting the terminal receipt.
Useful? React with 👍 / 👎.
| if not tickets: | ||
| return DrainResult(note="no task transition; budget-window metadata is derived by the remote keeper") |
There was a problem hiding this comment.
Persist budget-only reset events
When the only change is a cadence budget reset, diff_boards() yields only board metadata events, this loop skips them, and the function returns without sending any broker event. Callers such as dispatch explicitly rely on _reset_budget_if_needed() being persisted even when no task is reserved; with no task transition for the remote keeper to derive from, stale nonzero counters remain in tasks.yaml and can keep later budget/readiness views gated until some unrelated task mutation occurs.
Useful? React with 👍 / 👎.
Outcome
Introduces one symmetric conduct protocol for every native Limen lane: validated session/work/lease/receipt records, bounded DAG delegation, atomic resource leases, fencing/adoption, CLI and MCP parity, Worker/Durable Object projection, agent-neutral fanout/workstreams, ianva wiring, Copilot organization-profile source, and a complete exact-head PR-estate census.
Deliberate draft gates
Receipts
docs/receipts/peer-conductor-mesh-2026-07-18.mddocs/receipts/pr-campaign/docs/continuations/peer-conductor-live-cutover-2026-07-18.mdVerification
Exact head
fa63e5754db0032d6e862232200622f2ba93e1b6is green in CI run 29676568535: Python, Python 3.11, Worker, web, and the serializedverify-whole.shintegration job all passed. PR gate, validation, CodeQL, and every other reported exact-head check also passed.The final correction focused on the brokerless runtime probe: seven focused probe tests passed, the real local runtime probe passed, Ruff, shell syntax, ShellCheck, and
git diff --checkpassed. The PR three-dot diff contains notasks.yamlchange; live board updates on advancingmainremain untouched. The worktree is clean and the pushed branch is exact at this head.