Skip to content

fix(pointer): adopt the worker's attested session so factory PRs stop emitting session_ref=missing - #494

Open
khaliqgant wants to merge 2 commits into
mainfrom
fix/pr-pointer-real-session-ref
Open

fix(pointer): adopt the worker's attested session so factory PRs stop emitting session_ref=missing#494
khaliqgant wants to merge 2 commits into
mainfrom
fix/pr-pointer-real-session-ref

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Sep 8, 2026

Copy link
Copy Markdown
Member

Every factory-opened PR carries session_ref=missing. Measured across this repo
on 2026-09-08: #493, #465, #464, #461, #457 all missing; #469, #460, #444, #430
carry no pointer at all. Zero PRs carry a resolvable session UUID, which leaves
the github lens that relayhistory-cloud PR #41 specified with nothing to key
session_links rows on.

The seam, with the captured spawn output

I placed a real spawn:claude through messaging.placement.spawn({confirm:true})
against a live node, exactly as RelayFleetClient.#spawn does. This is the
RelayActionInvocation that spawnResultFromInvocation reads — invocation
inv_223040291642302464, verbatim:

{
  "invocationId": "inv_223040291642302464",
  "actionName": "spawn",
  "input": {
    "name": "ws10-placement-probe",
    "agent": "ws10-placement-probe",
    "clone_path": "/tmp",
    "cwd": "/tmp",
    "spawn_mode": "task_exit",
    "exit_after_task": true,
    "capability": "spawn:claude",
    "node": "chief-broker",
    "target_node": "chief-broker",
    "cli": "claude"
  },
  "output": {
    "agent_id": "223040362062057472",
    "name": "ws10-placement-probe",
    "invocation_id": "inv_223040291642302464",
    "session_ref": null
  },
  "status": "completed",
  "error": null,
  "createdAt": "2026-09-08T11:22:29.000Z",
  "completedAt": "2026-09-08T11:23:10.000Z"
}

At that same moment, the node's own broker reported that agent as:

"name": "ws10-placement-probe",  "sessionId": "0190f75d-2915-4c9c-a31b-6354234eee29"

So the id exists and the payload Factory reads reports it as null. Factory's
parsing is not at fault: spawnResultFromInvocation already reads all four key
variants off both output and output.agent, and there is simply nothing in the
output to read. name is present, which is exactly why a spawn that lost its
session still looks completely healthy — nothing anywhere reports a problem.

Why it is null. That output shape is the engine's FleetInventoryAgent
record — {agent_id, name, invocation_id, session_ref} — materialised when the
spawn action completes. The broker delivers the worker's session to the engine
afterwards, on the agent.register / inventory.sync frames (both carry
session_ref in @relaycast/types' fleet wire schema). Re-reading the very same
invocation ten minutes later still returns session_ref: null; it never
backfills.

The two paths differ, and only one is broken

path result
InternalFleetClient (broker /api/spawn direct) works
RelayFleetClient (remote placement) broken

I drove the real InternalFleetClient against a live broker rather than
reasoning about it:

=== SpawnResult from InternalFleetClient ===
{ "name": "ws10-internal-probe-1788867185946",
  "sessionRef": "bb49fadc-bc2d-4f6d-9353-29c23f29e0dd" }

The broker's /api/spawn response carries sessionId at the top level — I
confirmed it is returned even when the caller supplies a full Factory-shaped
harnessConfig, and that it matches the roster entry exactly. So the internal
lane was never the problem, and this change does not alter it.

Repairs I ruled out empirically, not by reasoning

  • Reading it back off the engine. agents.list, agents.get,
    agents.presence and sessionEvents.list carry no session ref for a
    broker-spawned agent — metadata.fleet holds node_id, invocation_id,
    registered_at and nothing else. The node's relay:live-agents:v1 capability
    advertises agent names only and is not invokable as an action.
  • Seeding our own UUID as the spawn input's session_ref. That key means
    resume, not set. The spawn never confirmed: the invocation stuck at status
    dispatched and the placement failed spawn_unconfirmed after 120s.

The fix

The broker stamps RELAY_ATTEST_SESSION_ID into every spawned worker's
environment, and the Relay SDK carries it as metadata.session_ref on the
messages that worker sends. Verified live in this workspace — a running agent's
messages carry {"session_ref":"707f2b00-3cee-41ce-b976-153bc9afdabf"}, matching
its roster sessionId exactly.

RelayFleetClient.#emitAgentMessage was building AgentMessage as
{from, target, body, threadId, eventId} and dropping message.metadata on the
floor. So the one readable copy of the session id was arriving and being
discarded. This change:

  1. adds sessionRef to AgentMessage (src/ports/fleet.ts);
  2. reads metadata.session_ref in RelayFleetClient.#emitAgentMessage;
  3. adopts it into tracked.sessionRef the first time a worker speaks
    (FactoryLoop.#adoptAttestedSessionRef), from which the existing
    canonicalTrajectorySessionRef(implementer.sessionRef) call already feeds
    githubPullRequestBody.

The adoption only fills a gap — a ref already tracked (a resumed lineage, or
a spawn result that did carry one, as the internal path does) is never moved by
a message. It runs as its own task off the inbound-message listener rather than
inside #handleAgentMessage, because that function installs the babysitter
critical-section fence synchronously before its first await and must keep doing
so.

Adoption writes to the in-memory tracked agent and takes no durable write of its
own: cloneTrackedAgent already serialises sessionRef, so the next
#saveDispatchLifecycle — which every phase transition between dispatch and
publish performs — persists it for free, without adding a write per inbound
message or reaching for lifecycle ownership from a listener task.

relay_inbound broker events carry no message metadata, so the internal client
is deliberately left alone: it already gets the ref from the spawn result.

opencode is NOT covered, and this does not pretend otherwise

ws6-nightcto-commitsha (opencode) reports sessionId: null on the broker while
every claude and codex lane reports a UUID. No session is minted, so no
RELAY_ATTEST_SESSION_ID is stamped, so no message can attest one. An
opencode-spawned implementer will still render session_ref=missing after this
change.
That is an engine-side hole, not a Factory one, and closing it belongs
upstream — it is called out here rather than silently fixed only for the engines
that already work.

Contracts left alone

  • canonicalTrajectorySessionRef still rejects the nil UUID as well as an absent
    one; the fleet layer passes the ref through opaquely and does no UUID
    filtering, so the two cases stay distinguishable exactly where they were.
  • Legacy bodies carrying session_ref=missing still parse to undefined via
    trajectoryPointerFromBody. Unchanged.
  • No collision with [garden] Carry the session source in the PR trajectory pointer #493: that PR adds session_source in src/trajectory.ts,
    src/index.ts and docs/pr-session-replay.md. This one touches only the fleet
    seam and the factory adoption. The two compose — [garden] Carry the session source in the PR trajectory pointer #493 supplies the source, this
    supplies the id that makes the source mean something.

Tests

renders the pointer from a worker-attested session when the spawn result carries none fails on today's code and passes after:

AssertionError: expected undefined to be '0190f75d-2915-4c9c-a31b-6354234eee29'
 ❯ src/orchestrator/factory.test.ts:21532

Also added: keeps a tracked session ref when a worker attests a different one
(adoption never displaces), and surfaces a worker-attested session ref from inbound message metadata at the RelayFleetClient seam itself, which also
asserts an unattested message stays absent rather than becoming a blank.

Review round (rebased onto #493)

Four threads, all addressed in code. The P1 was right and it undercut the
original fix, so it is worth restating rather than burying:

The adoption watched the wrong channel for the flow that matters.
lifecycleInstructions tells a worker to complete through invoke_action and
explicitly NOT to DM or post to a shared channel (templates.ts:404/408/409), and
its only other outbound is a DM to the reviewer, which Factory never observes.
The SDK stamps session_ref onto sent messages only
(messaging/relaycast.js:171/186/198/213) and never onto commands.invoke. So a
worker following its own task emitted no attestation and still published
session_ref=missing. The ref is now carried through the lifecycle invocation —
symmetric with the usage record already lifted off that same worker-supplied
input — and the rendered task requires the key.

Also fixed: a stale-generation guard (deterministic names are reused, and a
remote respawn reopens the gap, so a late message from a previous worker could
attach a dead session); per-agent serialization with #handleAgentExit awaiting
the pending adoption; and a durable checkpoint at adoption time rather than at
the next phase transition.

One test does not prove its fix, and says so. The attest-then-exit test stays
green with the exit guard removed — FakeFleetClient dispatches both callbacks
synchronously, so the adoption always wins in-process. It is labelled in the file
as covering the end-to-end shape only; the guard is retained on the reviewer's
reasoning, not on evidence I produced. The other three new tests were each
confirmed failing with their fix disabled.

Suite

After the rebase and the review fixes, the five affected suites
(factory, relay-fleet-client, internal-fleet-client, templates,
trajectory) run 985 passed, 0 failed. tsc -p tsconfig.build.json clean.

Counts across the rebase: trajectory.test.ts 11 -> 33 (all of the +22 is
#493's), factory.test.ts 735 -> 738 (#493's one test plus two of mine here).

Earlier, before the rebase: 2585 passed | 1 skipped on the full suite, then
11 passed for the two files that need a build first.

src/__tests__/dist-entrypoints.test.ts imports dist/, so it fails on a
vitest run that was not preceded by npm run build; after npm run build both
it and src/git/agent-worktree.test.ts pass.

One note for whoever owns the babysitter tests: under machine load, tests in the
FactoryLoop PR babysitter block time out non-deterministically — a different
set each run. I checked this against the unmodified base rather than assuming,
and origin/main with this change reverted fails four of them on the same
machine and the same command, two of which (retries internal babysitter wakes at a confirmed safe boundary, restarts an unreachable babysitter and delivers the preserved wake) fail on every loaded run with or without this change. They all
pass unloaded. Pre-existing and unrelated to this PR, but it is a wider flake
than the src/cli/teammate-mcp.test.ts one that is already known.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LPR3Wioz9nUmoPPWem5JUN

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 1b215211-8281-4560-97ca-4821d98352ce

📥 Commits

Reviewing files that changed from the base of the PR and between 081d512 and a465f65.

📒 Files selected for processing (5)
  • src/fleet/relay-fleet-client.test.ts
  • src/fleet/relay-fleet-client.ts
  • src/orchestrator/factory.test.ts
  • src/orchestrator/factory.ts
  • src/ports/fleet.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change adds optional attested session references to Relay agent messages. Factory uses these references to fill missing remote-worker session data, preserves existing values, records adoption metrics, and includes regression tests.

Changes

Session reference propagation

Layer / File(s) Summary
Relay message session metadata
src/ports/fleet.ts, src/fleet/relay-fleet-client.ts, src/fleet/relay-fleet-client.test.ts
AgentMessage includes optional sessionRef. Relay extracts non-empty session_ref or sessionRef metadata and emits it with agent messages. Tests cover attested and unattested messages.
Factory session adoption
src/orchestrator/factory.ts, src/orchestrator/factory.test.ts
Factory asynchronously adopts an attested reference when the tracked agent has none. Existing references remain unchanged. Tests verify pull-request metadata and adoption metrics.

Priority: ⬇️ Low — Defer this narrow Relay placement fix because it only backfills missing session references for remotely placed workers.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to a465f

Remote Relay workers can now publish their attested session reference in factory-opened PR metadata without overwriting an existing reference. The change is covered by regression tests and is ready to merge.

Sequence Diagram(s)

sequenceDiagram
  participant RelayFleetClient
  participant Factory
  participant TrackedAgent
  participant PullRequest
  RelayFleetClient->>Factory: Emit AgentMessage with sessionRef
  Factory->>TrackedAgent: Look up message.from
  Factory->>TrackedAgent: Set sessionRef when absent
  Factory->>PullRequest: Publish tracked sessionRef
Loading

Suggested reviewers: kjgbot, miyaontherelay

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the primary change: adopting the worker's attested session to prevent factory pull requests from emitting session_ref=missing.
Description check ✅ Passed The description directly explains the session-reference defect, the RelayFleetClient and FactoryLoop changes, scope limitations, and test results.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pr-pointer-real-session-ref

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.

❤️ Share

A rabbit carries a session bright
Through Relay fields into the night
Factory fills the missing trace
Existing refs stay in place
Tests guard each hopping case

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-08T12:14:03.462139Z 9a36057 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai review

Requested for exact head 9a36057033da6f7e94f390d19f426ecd4496d822.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/orchestrator/factory.ts Outdated
Comment thread src/fleet/relay-fleet-client.ts Outdated

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

Copy link
Copy Markdown

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: 9a36057033

ℹ️ 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 src/orchestrator/factory.ts Outdated
// installs the babysitter critical-section fence synchronously before
// its first await, and an adoption read ahead of it would open a gap
// the fence exists to close.
void this.#adoptAttestedSessionRef(message)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Capture session refs from the required lifecycle action

A standard worker can follow the generated instructions without ever triggering this callback: src/dispatch/templates.ts tells it to report completion through invoke_action and explicitly not through a DM or shared channel, and that event is routed through onAgentLifecycleSignal, not onAgentMessage. If the worker sends no incidental Factory-visible message, its attested ref is never adopted and the completion handler still publishes the PR with session_ref=missing; carry the ref through the lifecycle invocation or otherwise make attestation part of the required flow.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Confirmed, and this was the most important of the four — thank you.

I verified the claim rather than taking it on faith: src/dispatch/templates.ts line 404 says Do not send completion to a named control agent or shared channel, 408 dictates the exact invoke_action input, and 409 says Do not replace it with a DM or shared-channel post, including #general. The implementer’s only other outbound is a DM to the reviewer (line 178), which Factory’s own client never observes. I also checked the SDK: replayMessageMetadata is applied in messaging/relaycast.js at lines 171/186/198/213 — the send/reply/dm paths — and not to commands.invoke. So a compliant worker completes with no Factory-visible message and no attestation, exactly as you describe.

Fixed by carrying the ref through the lifecycle invocation, which is symmetric with how lifecycleUsageFromInvocation already lifts an optional usage record out of the same worker-supplied input:

  • lifecycleSignalFromInvocation now reads sessionRef/session_ref from invocation.input; AgentLifecycleSignal carries it.
  • #handleAgentLifecycleSignal adopts it before any branch that can end in a publish.
  • lifecycleInstructions now requires the key, sourced from the worker’s RELAY_ATTEST_SESSION_ID, with an explicit instruction to omit it rather than invent one.

Tests: carries a worker-attested session ref off the lifecycle invocation input (relay client) and adopts the attested session from the lifecycle completion signal (factory) — I confirmed both fail with the fix disabled (expected undefined to be 0190f75d-…), so neither is vacuous. Plus a templates assertion so the instruction cannot be dropped silently.

const record = (await this.#batch()).getIssueByAgent(message.from)
const tracked = record?.agents.get(message.from)
if (!tracked || tracked.sessionRef) return
tracked.sessionRef = sessionRef

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 Persist the adopted session before acknowledging it

When the daemon crashes after this in-memory assignment but before the next lifecycle phase save, the durable lifecycle still contains the original missing ref. Startup reconstructs the tracked agent from that row, so if the worker exited during the outage or does not repeat a message after reconnect, reconciliation publishes its branch with session_ref=missing despite the attestation having already arrived. Checkpoint this mutation through the serialized lifecycle persistence path so restart recovery cannot discard it.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed, and fair to call out — I had flagged the same window in the PR body and then argued myself out of it on the grounds that the next phase transition persists the mutation for free. Your failure case is the one that argument does not cover: a crash inside the window, with the worker exiting during the outage, leaves startup rebuilding the tracked agent from a row that still says missing.

#applyAttestedSessionRef now checkpoints through the same serialized path the rest of the lifecycle uses (#saveDispatchLifecycle with the record’s current phase), so the adopted ref is durable at adoption time rather than at the next transition.

Two deliberate bounds:

  • It is skipped for terminal phases (isTerminalDispatchPhase), since re-saving there would drag in #drainAgentUsage and the run-cost finalisation for what is only a field update.
  • A failed checkpoint is logged and swallowed, not thrown. Adoption already happened in memory and the publish path reads the in-memory record, so losing a race for lifecycle ownership must not turn a successful adoption into a failed one. That is a deliberate trade: the durable write is best-effort, the in-memory one is not.

One write per agent, not per message — it is gated behind the tracked.sessionRef gap check, so it fires once per generation at most.

…g session_ref=missing

Every factory-opened PR carries `session_ref=missing`. The cause is not
Factory's parsing: a real placement spawn's completed invocation
(inv_223040291642302464) reports

  "output": { "agent_id": "223040362062057472", "name": "ws10-placement-probe",
              "invocation_id": "inv_223040291642302464", "session_ref": null }

while the node's own broker reported that same agent as
sessionId 0190f75d-2915-4c9c-a31b-6354234eee29 at that moment.

That output is the engine's FleetInventoryAgent record, materialised when the
spawn action completes — before the broker's `agent.register`/`inventory.sync`
frame delivers the worker's session to the engine. Re-reading the same
invocation ten minutes later still returns null; it never backfills. `name` is
present, so a spawn that lost its session looks entirely healthy.

The internal broker path is unaffected: driving the real InternalFleetClient
against a live broker returns { name, sessionRef: "bb49fadc-…" }, because
/api/spawn carries sessionId at the top level.

No engine read surfaces the ref (agents.list/get/presence, sessionEvents,
relay:live-agents:v1 all lack it), and seeding our own UUID as the spawn input's
`session_ref` means *resume* — that spawn never confirms.

What does reach us is the worker itself: the broker stamps
RELAY_ATTEST_SESSION_ID into its environment and the Relay SDK carries it as
`metadata.session_ref` on the worker's messages. `#emitAgentMessage` was
discarding `message.metadata`. Carry it through and adopt it into
tracked.sessionRef the first time a worker speaks, which is what already feeds
canonicalTrajectorySessionRef -> githubPullRequestBody.

Adoption only fills a gap — a tracked ref (resumed lineage, or an internal-path
spawn result) is never displaced. It runs off the listener rather than inside
`#handleAgentMessage`, which installs its babysitter fence synchronously before
any await.

opencode is NOT covered: that engine reports no sessionId at all, so no ref is
attested and its implementers still render `missing`. That hole is upstream.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPR3Wioz9nUmoPPWem5JUN

Session-Id: 7ac6ab72-3998-4367-9fcd-4c099c9bc6d6

Session-Id: 7ac6ab72-3998-4367-9fcd-4c099c9bc6d6
@khaliqgant
khaliqgant force-pushed the fix/pr-pointer-real-session-ref branch from 9a36057 to a465f65 Compare September 8, 2026 14:32
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai review

Requested for exact head a465f656cdb0a81397e38295720f3fba3c31ba64.

… messages

Review of #494 found the adoption watched the wrong channel for the flow that
matters. `lifecycleInstructions` tells a worker to report completion through
`invoke_action` and explicitly NOT to DM or post to a shared channel
(templates.ts:404/408/409), and its only other outbound is a DM to the reviewer
that Factory never observes. The Relay SDK stamps `session_ref` onto sent
messages only (messaging/relaycast.js:171/186/198/213), never onto
`commands.invoke`. So a worker that follows its task emitted no attestation at
all and still published `session_ref=missing`.

Carry it through the lifecycle invocation, symmetric with the `usage` record
already lifted off the same worker-supplied input:
  - lifecycleSignalFromInvocation reads sessionRef/session_ref
  - AgentLifecycleSignal carries it; #handleAgentLifecycleSignal adopts it
    before any branch that can end in a publish
  - the rendered task requires the key, sourced from RELAY_ATTEST_SESSION_ID,
    and says to omit rather than invent it

Also from review:

Stale generations. Agent names are deterministic and reused, and a remote
respawn reopens the gap (recordSpawn takes result.sessionRef ?? spec.sessionRef,
both undefined), so a late message from the previous worker could fill it with a
dead session. #emitAgentMessage now drops the attestation when the message
predates the placement holding that name, keyed on the spawnedAtMs the client
already tracks. The message is still delivered; only the claim is dropped.

Exit ordering. Adoptions are serialized per agent and #handleAgentExit awaits
the pending one before branching on tracked.sessionRef.

Durability. #applyAttestedSessionRef checkpoints through #saveDispatchLifecycle
at adoption time instead of waiting for the next phase transition, so a crash in
that window cannot leave the durable row saying `missing`. Skipped on terminal
phases; a failed checkpoint is logged, never thrown, since the in-memory
adoption already succeeded.

Counter renamed to agentSessionRefsAdoptedFromAttestation now that it covers
both routes.

Tests: the lifecycle-invocation read, the factory lifecycle adoption, and the
stale-generation guard were each confirmed failing with their fix disabled. The
attest-then-exit test is NOT proof of the exit guard — the fake dispatches both
callbacks synchronously and it stays green with the guard removed; it is
labelled as covering the end-to-end shape only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPR3Wioz9nUmoPPWem5JUN

Session-Id: 7ac6ab72-3998-4367-9fcd-4c099c9bc6d6
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai review

Requested for exact head 5fcaba4e34cb8fa34ac672a32ebf9bfb8f740070.

@khaliqgant

Copy link
Copy Markdown
Member Author

@coderabbitai review

Context for this pass: the earlier run was rate-limited and never read the code, so this is the first look. The branch has since been rebased onto main (#493 merged) and carries a second commit addressing four review threads from cubic and codex.

Two places where an extra pair of eyes would be most useful:

  1. attestedSessionRef in src/fleet/relay-fleet-client.ts compares an engine-assigned message.createdAt against a locally-assigned spawnedAtMs — deliberately across clocks. The failure mode of skew is dropping a valid attestation rather than accepting a stale one, and I argued the boot-time gap makes that safe, but I would like that reasoning challenged.

  2. #applyAttestedSessionRef in src/orchestrator/factory.ts calls #saveDispatchLifecycle with the record's current phase as a checkpoint, and swallows a failed save on purpose. Please check that re-saving a non-terminal phase mid-flight cannot perturb the lifecycle state machine or its epoch/ownership fencing.

Also flagging honestly: publishes the attested session when the exit follows the message immediately does NOT prove the exit-ordering guard it accompanies — it stays green with the guard removed, because the fake dispatches both callbacks synchronously. It is labelled as such in the file. If you can see a way to force that interleaving through the existing fakes, that would be a genuinely useful review finding.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
gh pr view 494 --repo AgentWorkforce/software-garden --json number,title,headRefName,baseRefName,commits
gh pr diff 494 --repo AgentWorkforce/software-garden > /tmp/pr494.diff
wc -l /tmp/pr494.diff

Length of output: 6334


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '1,705p' /tmp/pr494.diff

Length of output: 33316


🏁 Script executed:

#!/bin/bash
set -euo pipefail
fd '\.ts$' src/orchestrator -x echo {} | grep -i factory | head
echo "---outline `#saveDispatchLifecycle---`"
ast-grep run --pattern 'async `#saveDispatchLifecycle`($$$) {
  $$$
}' --lang typescript src/orchestrator/factory.ts | head -150

Length of output: 1005


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n 'async `#saveDispatchLifecycle`' src/orchestrator/factory.ts
rg -n 'function isTerminalDispatchPhase|isTerminalDispatchPhase' src/orchestrator/factory.ts | head -20
rg -n 'lifecycleEpoch|epoch' src/orchestrator/factory.ts | head -60

Length of output: 4146


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '7980,8120p' src/orchestrator/factory.ts

Length of output: 6394


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n '`#scheduleDispatchLifecycleRetry`' src/orchestrator/factory.ts | head -20
sed -n '/#scheduleDispatchLifecycleRetry(record: InFlightIssue)/,/^  }/p' src/orchestrator/factory.ts | head -80

Length of output: 1925


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n 'spawnedAtMs' src/fleet/relay-fleet-client.ts | head -30
rg -n 'createdAt' src/fleet/relay-fleet-client.ts | head -30

Length of output: 1339


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n 'class FakeFleetClient' -A5 src/orchestrator/factory.test.ts | head -20
rg -n 'emitAgentMessage|emitAgentExit|onAgentMessage|onAgentExit' src/orchestrator/factory.test.ts | sed -n '1,40p'

Length of output: 531


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n 'FakeFleetClient' -l src | head
rg -n 'emitAgentMessage\s*[:(]|emitAgentExit\s*[:(]' src -g '!*.ts.map' | head -30

Length of output: 3589


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n 'emitAgentMessage|emitAgentExit|onAgentMessage|onAgentExit' src/testing/fakes.ts
sed -n '1,50p' src/testing/fakes.ts | head -5

Length of output: 619


(370, 445)

You are interacting with an AI system.

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.

1 participant