Skip to content

ORB-136: report structured worker status - #652

Closed
thomasluizon wants to merge 16 commits into
mainfrom
feature/orb-136-have-workers-report-status-instead-of
Closed

ORB-136: report structured worker status#652
thomasluizon wants to merge 16 commits into
mainfrom
feature/orb-136-have-workers-report-status-instead-of

Conversation

@thomasluizon

@thomasluizon thomasluizon commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add a worktree-local Stop hook that appends one structured JSONL record per worker turn.
  • Provision a shared external reports file and install Claude reporting plus a concurrency-safe Codex primary-root dispatcher during worker launch.
  • Make worker-status combine report liveness with hard git, PR, review, and Linear artifact checks.
  • Update orchestration guidance so structured reports are the normal status path and terminal reads are diagnostic only.

Root cause

Worker supervision treated terminal state as status. That made healthy runs expensive to scrape and allowed silent workers, staged merge state, or unpushed commits to look complete when PR and Linear state appeared healthy.

Decisions taken unattended

  • Make --reports-file required for launches so every worker has an explicit shared reporting destination.
  • Keep worker-status report flags optional for compatibility with direct completion checks outside an orchestrated reporting run, while labeling omitted liveness as NOT-CHECKED.
  • Keep Claude reporting worktree-local. Install one stable Codex dispatcher at the primary project root and route each Stop event by normalized cwd through a lock-protected registry under Git's common directory.
  • Preserve pre-existing primary Codex hooks and effective excludes byte for byte. Use a primary-worktree-scoped excludes file so generated dispatcher state does not dirty the checkout or mutate shared .git/info/exclude.
  • Roll back Codex registration after a late launch failure and deregister only after teardown verifies worktree removal. The final deregistration restores prior hook and excludes state.
  • Keep real Codex end-to-end hook execution explicitly unverified until the primary-root dispatcher is exercised by the shipped interactive TUI; the dispatcher lifecycle and runtime routing are executed directly by the tools harness.
  • Preserve the ORB-135 worker-owned review contract while adding report liveness and hard git-state failures.

Real Stop hook verification

  • Claude bare engine and installed settings hook: VERIFIED on 2026-07-29 with Windows 11, Orca 1.4.156, and Claude Code 2.1.220. A bounded Orca TUI ran the launcher's exact bare command, claude --permission-mode bypassPermissions --model opus, with the exact generated .claude/settings.local.json Stop hook. One turn appended a complete 265-byte worker report. The full launcher could not cross quota preflight because ai-quota could not read the Claude quota, so passage through that launcher gate is not verified.
  • Codex worktree-local discovery measurement: VERIFIED as unsupported on the measured linked-worktree path on 2026-07-29 with Windows 11, Orca 1.4.156, and codex-cli 0.145.0. The launched TUI displayed Running Stop hook, but the worktree-local report file remained empty because Codex loaded project hooks from the primary root.
  • Codex primary-root dispatcher lifecycle and routing: VERIFIED by executed Windows harness cases on commit 9b86a2f58d8c3352e1563eda682e8d4bc732d156. The primary hook invokes the stable dispatcher, registered worktree cwd values route to separate JSONL files, unrelated roots exit cleanly without a record, simultaneous workers retain independent routes, one deregistration preserves the other route, launch rollback removes its route, and the final deregistration restores the original primary hooks, config, and generated excludes state byte for byte. A separate direct lifecycle run returned {ok:true,statusUnchanged:true,firstExit:0,secondExit:0,unrelatedExit:0,routesAfterFirst:1,hooksRestored:true,configRestored:true,excludeRestored:true,stateRemoved:true,runtimeRemoved:true}.
  • Codex shipped interactive TUI invoking the new primary-root dispatcher: UNVERIFIED. No claim beyond the executed dispatcher lifecycle and the prior hook-discovery measurement is made.

Verification

npm run lint
Tasks: 3 successful, 3 total
exit 0

npm run type-check
Tasks: 3 successful, 3 total
exit 0

npm run test
Tasks: 4 successful, 4 total
247 mobile test files passed, 1611 mobile tests passed
exit 0

node tools/test-tools.mjs
ORBIT TOOLS GATE OK
exit 0

node .claude/hooks/test-hooks.mjs
ORBIT HOOK PARITY OK
exit 0

node tools/arch-map.mjs
wrote architecture.json + architecture.html
no artifact drift
exit 0

node tools/check-dashes.mjs --files tools/README.md tools/launch-worker.mjs tools/teardown-worktree.mjs tools/test-tools.mjs tools/lib/codex-worker-dispatcher.mjs tools/lib/dispatch-worker-report.mjs
exit 0

node tools/check-dashes.mjs --check-baseline
exit 0

node tools/check-copy.mjs --check
exit 0

node --check tools/launch-worker.mjs
node --check tools/teardown-worktree.mjs
node --check tools/test-tools.mjs
node --check tools/lib/codex-worker-dispatcher.mjs
node --check tools/lib/dispatch-worker-report.mjs
all exit 0

git diff --check
exit 0

Linear: ORB-136

@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jul 29, 2026 1:29pm

Request Review

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: Vercel reports an intentionally skipped deployment and no review finding. Evidence: 009f02a. Review item: IC_kwDOR5Siws8AAAABMLTM3g

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: SonarQube reports a passing quality gate with zero new issues. Evidence: 009f02a. Review item: IC_kwDOR5Siws8AAAABMLT9Zw

@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: 009f02a40f

ℹ️ 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 .claude/skills/orchestrate/SKILL.md Outdated
@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: Vercel reports an intentionally skipped deployment and no review finding. Evidence: eaebb84. Review item: IC_kwDOR5Siws8AAAABMLTM3g

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: SonarQube reports a passing quality gate with zero new issues. Evidence: eaebb84. Review item: IC_kwDOR5Siws8AAAABMLXgDQ

@claude claude 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.

Code Review: PR #652 — ORB-136: report structured worker status

Scope: PR #652 in thomasluizon/orbit-ui-mobile (base main, head feature/orb-136-have-workers-report-status-instead-of)
Recommendation: NEEDS WORK

Summary

The PR adds a Claude+Codex Stop hook (.claude/hooks/report-worker-turn.mjs) that appends a structured JSONL record per worker turn to a shared reports.jsonl, wires tools/launch-worker.mjs to provision that file and install the worktree-local hooks, extends tools/worker-status.mjs with hard git-state checks (staged-but-uncommitted, merge-in-progress, unpushed commits) plus a report-freshness liveness check, and rewrites the orchestrate skill's babysitting procedure around tailing that shared file. The diff is entirely tooling/orchestration (.claude/hooks/**, tools/**, .claude/skills/orchestrate/SKILL.md) — no apps/*, orbit-api, packages/shared, or i18n surface is touched, so the five review subagents and the backward-compat guard are all N/A. The new hard-git-state checks and the concurrency-safe append logic are solid and well tested (8-concurrent-writer race test, staged/merge/unpushed fixtures). Two High findings survive adversarial verification: the babysitting procedure this PR writes has no trigger that would ever surface the "suspect" verdict for the exact failure mode (a worker that goes fully silent) the feature exists to catch, and the Codex-side hook wiring (.codex/hooks.json shape, the last_assistant_message/cwd payload fields, and --dangerously-bypass-hook-trust) is asserted by direct analogy to Claude Code's hook schema with no citation and no execution against a real codex process.

Findings

Critical

None.

High

[HIGH] The babysitting procedure has no trigger that ever surfaces a fully-silent worker's "suspect" verdict
· dimension: 1 (Correctness) / process correctness in a skill doc
· location: .claude/skills/orchestrate/SKILL.md (section "## 3. Babysit")
· issue: The only described invocation of worker-status.mjs --reports-file is "On each new record, run the artifact check for that ticket." The paragraph right after it, "A missing report is the diagnostic trigger... worker-status.mjs marks a worker suspect when it has not reported within the expected window," implies staleness detection is reachable in practice, but no periodic/timeout re-check is described anywhere in the file (confirmed by an independent re-read of the whole "Babysit" section and the unrelated "Waiting is foreground work" polling paragraph, which governs a different actor — a worker polling CI/review, not the orchestrator tailing reports.jsonl).
· risk: The PR's own stated root cause is "Worker supervision treated terminal state as status... allowed silent workers... to look complete." A worker that crashes, hangs, or whose Stop hook itself fails to fire produces, by definition, no new record — so per the literal text there is no trigger that would ever cause the orchestrator to invoke worker-status.mjs --reports-file for that ticket again and see the "suspect" verdict. The exact failure mode this feature was built to catch is unreachable through the documented procedure, silently reverting to the old behavior (nobody checks until a human happens to notice).
· fix: Add an explicit periodic re-check to the babysitting loop, independent of new records — e.g. "every time the loop wakes (poll every N seconds/minutes, per the standing foreground-waiting rule), also run worker-status.mjs --reports-file for every ticket that has NOT produced a record within --expected-window-minutes," not only on new-record arrival.
· reference: CLAUDE.md rule 1 (root cause) / the PR body's own stated root cause; verified by an independent adversarial re-read of .claude/skills/orchestrate/SKILL.md finding no periodic mechanism.

[HIGH] Codex-side hook wiring is unverified against Codex CLI's real behavior
· dimension: 15 (Harness changes need EXECUTED evidence) / 1 (Correctness)
· location: tools/launch-worker.mjs:684-731 (the .codex/hooks.json installation and the codexReportCommand construction) and tools/launch-worker.mjs:609-611 (--dangerously-bypass-hook-trust)
· issue: The Codex Stop-hook config is written in the exact same shape as Claude Code's .claude/settings.local.json hooks ({"hooks":{"Stop":[{"hooks":[{"type":"command",...}]}]}}), and it points at the SAME report-worker-turn.mjs script, which unconditionally reads hookInput.last_assistant_message and hookInput.cwd from stdin with no engine branch. --dangerously-bypass-hook-trust is appended to every codex launch with no comment or citation. None of these three claims (the hooks.json shape/event name, the payload field names, the flag's existence) is demonstrated by a test that runs the real codex binary — every test-tools.mjs case stubs the terminal/orca layer, so command is only ever asserted as a string. Notably, .claude/orchestrator.json's codex entry is an exceptionally detailed, dated log of codex's real measured quirks (exact trust-prompt keystroke, sandbox flags, -p meaning --profile not --print) — and it never once mentions hooks, corroborating that this integration was never actually run against real codex.
· risk: If Codex CLI's real hook system uses a different config file, event name, payload field, or doesn't support this flag, every Codex-engine worker's structured report silently degrades forever to the "missing or malformed WORKER_REPORT marker" fallback (needsHuman: true), defeating this PR's purpose for that half of the fleet, or the codex launch command could fail outright on an unrecognized flag.
· fix: Verify against an installed codex binary (codex --help, or a real launch) before merge, and once confirmed, record the measured behavior in .claude/orchestrator.json's codex entry the same way every other codex quirk in that file is documented, with a date and citation. If the hook mechanism doesn't exist for Codex, gate the hook installation to Claude only until it does.
· reference: CLAUDE.md rule 1 (root cause / no unverified assumptions) and rubric dimension 15 ("Verified" without an execution is itself a finding).

Medium

[MEDIUM] report-worker-turn.mjs's own argument-validation failure paths are untested
· dimension: 15 (Harness changes need EXECUTED evidence)
· location: .claude/hooks/report-worker-turn.mjs:30-31 (the --reports-file-must-be-absolute and --ticket-must-match-ORB-\d+ checks) and lines 98-106 (the fail() on an unwritable reports file)
· issue: .claude/hooks/test-hooks.mjs's new suite covers the complete-turn, missing-marker fallback, and 8-way-concurrent-write paths, but never exercises the hook's own fail() branches for a missing/relative --reports-file, a malformed --ticket, or a reports file that cannot be opened for append.
· risk: A regression in argument validation (e.g. the absolute-path check silently dropped) would not be caught by the harness gate that exists precisely to certify this file by execution, not by reading it.
· fix: Add three spawnSync cases to the new suite: relative --reports-file exits 1 with the expected stderr, malformed --ticket exits 1, and an unwritable path (e.g. inside a nonexistent, uncreatable directory) exits 1 via the could not append branch.
· reference: rubric dimension 15, "A new decision path added to a tool that already has coverage... needs its own case."

[MEDIUM] worker-status.mjs's new unknown-flag rejection is untested
· dimension: 15 (Harness changes need EXECUTED evidence)
· location: tools/worker-status.mjs:69-71 (KNOWN_FLAGS / unknown option(s))
· issue: The new KNOWN_FLAGS allowlist and its rejection of any unrecognized --prefixed token is a new decision path added in this PR, but tools/test-tools.mjs's workerStatusCases() (also new in this PR) never asserts it — only the three existing required-argument checks are re-verified.
· fix: Add a check(...) case passing an unrecognized flag (e.g. --bogus) and asserting exit 2 with /unknown option\(s\)/.
· reference: rubric dimension 15, same bullet as above.

Low / Info

None posted (signal gate).

Subagents

Agent Verdict
parity-checker N/A — no apps/web/** or apps/mobile/** file changed
i18n-syncer N/A — no user-facing strings or i18n JSON changed
contract-aligner N/A — no packages/shared/src/types/* or orbit-api DTO changed
security-reviewer N/A — no orbit-api code changed
design-reviewer N/A — no apps/* or orbit-landing-page UI file changed

Validation

Check Result
Lint PASS (CI, latest commit eaebb844)
Type check PASS (CI, latest commit eaebb844)
Tests (Unit Tests) PASS (CI, latest commit eaebb844)
Harness Execution (test-tools.mjs + test-hooks.mjs) PASS on the code-bearing commit 009f02a4 (all six changed files); IN PROGRESS on the latest commit at review time, which touches only .claude/skills/orchestrate/SKILL.md prose (no tools/** or .claude/hooks/** code)
Build PASS (CI, latest commit eaebb844)

Local execution of node tools/test-tools.mjs / node .claude/hooks/test-hooks.mjs was not independently reproduced in this review session: the sandbox's git-write operations (worktree add, clone, checkout) require an interactive approval this session cannot grant itself, so CI's own job runs are cited above instead of a locally-run trace.

Deferred — N/A dimensions & files not verdicted

  • Dimension 8 (DESIGN.md/AI-slop), 9 (Parity), 10 (i18n), 11 (Contract drift), 12 (Security, frontend categories), 13 (Backend hard rules), 14 (FEATURES.md parity): all N/A, the diff touches no apps/*, orbit-api, packages/shared, or i18n surface.
  • Every one of the 6 changed files (.claude/hooks/report-worker-turn.mjs, .claude/hooks/test-hooks.mjs, .claude/skills/orchestrate/SKILL.md, tools/launch-worker.mjs, tools/test-tools.mjs, tools/worker-status.mjs) received a verdict above; nothing was left unexamined.
  • The PR branch received a live push (eaebb844, "fix: start report monitor before workers") during this review session, a .claude/skills/orchestrate/SKILL.md-only diff fixing a separate race (the monitor's read-offset being captured before vs. after the first worker launch). That fix does not touch the trigger gap described in the first High finding above; both were re-checked against the latest diff before this report was written.
  • Local harness re-execution: deferred to CI (see Validation table) for the sandbox reason stated there.

What's good

  • The 8-concurrent-writer test for report-worker-turn.mjs (worker-report: eight concurrent hooks all exit successfully / ...lose no records / ...every concurrent line is well formed) is exactly the kind of race-condition proof dimension 15 exists to demand, and it is a real fixture (real git init/commit/push), not a mock.
  • The new worker-status.mjs hard-git-state checks (staged-uncommitted, merge-in-progress, unpushed-commits) each ship with a dedicated real-git fixture (stageWorkerStatus) proving the exact scenario measured in the PR body, not just a unit-level assertion.
  • Rolling the worktree-local .claude/hooks/report-worker-turn.mjs, .claude/settings.local.json, and .codex/hooks.json into info/exclude rather than the tracked .gitignore is the right call — these are per-launch generated artifacts, and the worker contract's "stage explicitly" clause (clause 8) benefits from a clean git status.
  • The comment policy is respected throughout the new code (no narration comments; the one block comment in report-worker-turn.mjs's surrounding file is pre-existing JSDoc-style WHY prose, not new).

Recommendation

Fix the two High findings before merge: (1) close the trigger gap so a fully-silent worker actually gets checked by the babysitting procedure this PR writes, and (2) verify the Codex hook wiring against a real codex binary (or gate hook installation to Claude only until verified) and record the measured result in .claude/orchestrator.json the way every other codex quirk in that file already is. The two Medium test-coverage gaps are worth closing in the same PR since they're each a few lines, but are not blocking.

@claude claude 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.

Code Review: PR #652

Scope: PR #652 in thomasluizon/orbit-ui-mobile (base main, head feature/orb-136-have-workers-report-status-instead-of @ eaebb844)
Recommendation: REQUEST CHANGES

Summary

The diff is entirely orchestration tooling (.claude/hooks/**, tools/**, .claude/skills/orchestrate/SKILL.md) — no apps/*, orbit-api, packages/shared, or i18n surface changed, so all five review subagents and the backward-compat guard are N/A. This is a re-review of a PR that already carries an open CHANGES_REQUESTED review from a prior automated pass; I independently re-verified its findings against git show HEAD: content and ran an additional adversarial check on each before posting.

Correction from the prior pass: the prior review's finding that report-worker-turn.mjs was wrong to trust hookInput.last_assistant_message without a transcript-parsing fallback does not survive verification. Official Claude Code hooks documentation confirms last_assistant_message is the documented, intended field for Stop hooks, and explicitly recommends against reading transcript_path as a fallback because the transcript file is written asynchronously and may lag the in-memory conversation. The sibling hook's (forbid-raw-repo-tool-surfacing.mjs) transcript fallback is defensive belt-and-suspenders coding, not evidence the field is unreliable. That finding is dropped from this review.

Two other High findings from the prior pass were independently re-verified and still stand.

Findings

Critical

None.

High

[HIGH] (re-confirmed) The babysitting procedure has no trigger for a fully-silent worker's "suspect" verdict
· dimension: 1 (Correctness)
· location: .claude/skills/orchestrate/SKILL.md §"## 3. Babysit"
· issue: The described loop is "Use the monitor... surface each complete line appended after its captured offset... On each new record, run the artifact check for that ticket." The very next paragraph, "A missing report is the diagnostic trigger... worker-status.mjs marks a worker suspect when it has not reported within the expected window," presupposes the artifact check gets run for that ticket — but the only documented trigger for running it is a new monitor line. worker-status.mjs does implement the time-based check (--expected-window-minutes, default 30, verified at tools/worker-status.mjs:111,185,402), but nothing in the babysit procedure calls it independent of new-record arrival. A worker that goes fully silent (crash, hang, Stop hook fails to install or fire) produces zero records by definition, so the monitor never fires for it and the procedure as written never re-examines it.
· risk: This is the PR's own stated root cause reappearing through the new mechanism instead of the old one — a silent worker looks unremarkable because nothing ever polls for its absence.
· fix: Add an explicit periodic re-check to the babysit loop, independent of new-record arrival — e.g., on each wake of the standing poll cadence (see "Waiting is foreground work"), also run worker-status.mjs --reports-file for every launched ticket with no record inside --expected-window-minutes, not only tickets that just produced one.
· reference: CLAUDE.md rule 1; PR body's own stated root cause.

[HIGH] (re-confirmed) Codex-side hook wiring is unverified against the real codex CLI
· dimension: 15 (Harness changes need EXECUTED evidence) / 1 (Correctness)
· location: tools/launch-worker.mjs:684-731 (the .codex/hooks.json shape and codexReportCommand), :609-611 (--dangerously-bypass-hook-trust)
· issue: The .codex/hooks.json shape, event name, and payload fields are asserted by direct analogy to Claude Code's own hook schema, with no citation and no execution against a real codex binary — every test-tools.mjs case stubs the terminal/orca layer, so command is only ever asserted as a string. I independently confirmed .claude/orchestrator.json's codex entry contains zero mentions of "hook" anywhere (grep -i hook returns nothing), despite being this repo's own established practice of logging every measured codex CLI quirk in detail (exact trust-prompt keystroke, sandbox flags, -p semantics) down to the CLI version tested. That corroborates this specific integration was never actually run against real codex, breaking the file's own standing convention of measuring before relying.
· risk: If Codex's real hook mechanism uses a different config path, event name, or payload shape, or the flag doesn't exist, every Codex-engine worker's structured report silently and permanently degrades to the "missing marker" fallback, or the launch command fails outright on an unrecognized flag.
· fix: Verify against an installed codex binary before merge; once confirmed, record the measured result in .claude/orchestrator.json's codex entry with a date, the same way every other codex quirk there already is. Until verified, gate hook installation to the Claude engine only.
· reference: CLAUDE.md rule 1; rubric dimension 15.

Medium

[MEDIUM] The generated-file info/exclude entry for .claude/hooks/report-worker-turn.mjs is a no-op once the file is git-tracked
· dimension: 1 (Correctness) / documentation accuracy
· location: tools/launch-worker.mjs:684-701; .claude/skills/orchestrate/SKILL.md ("The launcher excludes these generated runtime files from the target repo's local git status")
· issue: .claude/hooks/report-worker-turn.mjs is itself a new file this PR commits to the repo (tracked at HEAD). git info/exclude only ever suppresses untracked paths from git status; it has no effect on a tracked file's modified/clean state. Once this PR merges to main, every future worktree already carries this file tracked, so the exclude entry for it does nothing (harmless today only because copyFileSync writes byte-identical content back over itself).
· risk: If the orchestrator's own copy of the hook script ever drifts from what a given worktree's base-branch commit carries, the re-copy would leave a tracked file locally modified, and worker-status.mjs's worktree-clean check would report a false "uncommitted work" failure the exclude entry cannot suppress — right at launch, before the worker does anything.
· fix: Drop .claude/hooks/report-worker-turn.mjs from generatedWorktreePaths (it needs no exclusion once tracked), or stop unconditionally re-copying it when the worktree's checked-out copy already matches the source by content.
· reference: CLAUDE.md rule 1 (root cause) — the claim in SKILL.md overstates what git exclude actually does for this one path.

Low / Info

None posted (signal gate).

Subagents

Agent Verdict
parity-checker N/A — no apps/web/** or apps/mobile/** file changed
i18n-syncer N/A — no user-facing strings or i18n JSON changed
contract-aligner N/A — no packages/shared/src/types/* or orbit-api DTO changed
security-reviewer N/A — no orbit-api code changed
design-reviewer N/A — no apps/* or orbit-landing-page UI file changed

Validation

Check Result
Lint PASS (CI, head eaebb844)
Type check PASS (CI, head eaebb844)
Tests (Unit Tests) PASS (CI, head eaebb844)
Harness Execution (test-tools.mjs + test-hooks.mjs) PASS (CI, head eaebb844)
Build PASS (CI, head eaebb844)

Phase 6 (/validate) and Phase 7 (posting) skipped per this workflow's CI-wrapper contract; CI's own job results are cited above.

What's good

  • The 8-concurrent-writer test for report-worker-turn.mjs is a real git fixture proving append-atomicity under concurrency, not a mock.
  • The new worker-status.mjs hard-git-state checks (staged-uncommitted, merge-in-progress, unpushed-commits) each ship with a dedicated real-git fixture reproducing the exact scenario named in the PR body's root-cause section.
  • Comment policy is respected throughout the new code — no narration comments in any added block.
  • The --reports-file absolute-path and inside-a-repo/worktree refusals in launch-worker.mjs mirror the existing --prompt-file guards precisely.
  • report-worker-turn.mjs correctly relies on last_assistant_message per Claude Code's documented Stop-hook contract, rather than the async-lagging transcript file.

Recommendation

Not ready to merge. Two High findings need fixing: (1) add a periodic liveness re-check to the babysit loop, independent of new-record arrival, so a fully-silent worker is ever actually inspected; (2) verify the Codex hook wiring against a real codex binary (or gate to Claude-only until verified) and record the result in .claude/orchestrator.json per this repo's own established practice. The Medium finding (drop or fix the now-inert exclude entry for the tracked hook file) is a few lines and worth folding into the same pass.

@thomasluizon

thomasluizon commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

Fixed in 81f6e9d: the monitor now checks every active ticket every 60 to 120 seconds even without new JSONL lines; installed codex-cli 0.145.0 executed a real Stop hook and delivered cwd plus last_assistant_message, with the dated official contract recorded in orchestrator.json; reporter failure paths and worker-status unknown-option handling now have executable coverage. Evidence: ORBIT TOOLS GATE OK, ORBIT HOOK PARITY OK, and current-head push 81f6e9d. Review item: PRR_kwDOR5Siws8AAAABHlBUrA

@thomasluizon

Copy link
Copy Markdown
Owner Author

Fixed in 2ec2bd0: periodic silent-worker checks, real Codex Stop-hook verification, and negative-path coverage remain in place; the delayed exclusion finding is now fixed by keeping report-worker-turn.mjs tracked and ignoring only generated settings files. The full fixture proves the tracked reporter and ends with ORBIT TOOLS GATE OK. Review items: PRR_kwDOR5Siws8AAAABHlBUrA, PRR_kwDOR5Siws8AAAABHlDwHw

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: Vercel reports an intentionally skipped deployment and no review finding. Evidence: 2ec2bd0. Review item: IC_kwDOR5Siws8AAAABMLTM3g

@thomasluizon
thomasluizon force-pushed the feature/orb-136-have-workers-report-status-instead-of branch 2 times, most recently from 6c0faca to 049a938 Compare July 29, 2026 04:14
@thomasluizon

Copy link
Copy Markdown
Owner Author

Current-history acknowledgement for automated review activity after the rebase.

Fixed in 049a938: periodic silent-worker checks, real Codex Stop-hook verification, negative-path coverage, tracked reporter handling, and the ORB-131 concurrent budget-reservation integration all pass in the rebased history. ORBIT TOOLS GATE OK and ORBIT HOOK PARITY OK.

Review items: PRR_kwDOR5Siws8AAAABHlBUrA, PRR_kwDOR5Siws8AAAABHlDwHw.

No code finding from Vercel item IC_kwDOR5Siws8AAAABMLTM3g on this head; it is deployment status only.

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: SonarQube reports a passing quality gate with zero new issues on current head 049a938. Review item: IC_kwDOR5Siws8AAAABMLXgDQ

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: SonarQube reports a passing quality gate with zero new issues on current head 049a938. Review item: IC_kwDOR5Siws8AAAABMMGubg

@claude claude 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.

Code Review: PR #652

Scope: PR #652 in thomasluizon/orbit-ui-mobile (base main, head feature/orb-136-have-workers-report-status-instead-of @ 049a938a)
Recommendation: APPROVE

Summary

This is a re-review focused on the diff since the last automated review (two prior claude
CHANGES_REQUESTED reviews, both at commit eaebb844). The four commits since then
(6af61f30 "start report monitor before workers", bb142b19 "close worker review gaps",
dad0175b "keep reporter tracked", 049a938a "keep concurrent launch coverage") were read in
full and cross-checked against the actual committed source, not just their commit messages.
Every High and Medium finding from both prior reviews is now closed by an executable test or a
verifiable documentation fix, not by prose alone. No new Critical/High issue surfaced in the
delta. The diff remains entirely orchestration tooling (.claude/hooks/**, tools/**,
.claude/skills/orchestrate/SKILL.md) — no apps/*, orbit-api, packages/shared, or i18n
surface changed, so the five review subagents and the backward-compat guard stay N/A, as in both
prior passes.

Findings

Critical

None.

High

None. Both High findings from the prior reviews are resolved:

  • Babysit loop had no trigger for a fully-silent worker. bb142b19 adds to
    .claude/skills/orchestrate/SKILL.md §"Babysit": "The monitor loop also wakes every 60 to 120
    seconds, following the foreground-waiting rule below. On every wake, run that same artifact
    check for EVERY active ticket, including when no line was appended." Combined with 6af61f30
    (start the monitor before the first worker launch), this ties the babysit loop explicitly to
    the pre-existing "Waiting is foreground work" standing rule (poll 60-120s per loop, in the
    foreground) and makes the periodic re-check independent of new-record arrival — the exact gap
    both prior reviews identified. tools/worker-status.mjs's expectedWindowMinutes /
    reportFresh logic (confirmed unchanged and already correct) now has a documented trigger that
    reaches it for a worker that produces zero records.
  • Codex-side hook wiring unverified against real codex. bb142b19 adds a
    hookVerification field to the codex entry in .claude/orchestrator.json, dated 2026-07-28,
    naming the exact CLI version (codex-cli 0.145.0), the exact flag tested
    (--dangerously-bypass-hook-trust), the payload fields observed (hook_event_name, cwd,
    last_assistant_message), and a citation to the official Codex Hooks contract — matching this
    file's own established convention for recording every other measured codex quirk (already
    verified by the prior review to otherwise be spotless on this point). This is a documentation
    claim that cannot be re-executed in this sandbox (no codex binary available), so it is taken
    as good faith per the repo's own standing practice, consistent with how every other dated codex
    measurement in this file is treated; see Deferred.

Medium

None. All three Medium findings are resolved with real, executed coverage, verified by reading
the actual code paths they exercise:

  • bb142b19 adds four new cases to .claude/hooks/test-hooks.mjs that spawnSync the real
    report-worker-turn.mjs hook: relative --reports-file (rejected, matches
    report-worker-turn.mjs:25), missing --reports-file, malformed --ticket (orb-136 fails
    /^ORB-\d+$/ at report-worker-turn.mjs:26), and an unwritable target (a directory passed as
    the reports path, exercising the catch around openSync/writeSync at
    report-worker-turn.mjs:93-99). All four assert both the exit code and the exact stderr
    contract.
  • bb142b19 adds a worker-status.mjs case for an unknown flag (--bogus), exercising the
    pre-existing KNOWN_FLAGS allowlist at tools/worker-status.mjs:69-71 (confirmed unchanged
    and already correct — the finding was purely a coverage gap).
  • dad0175b fixes the info/exclude no-op: report-worker-turn.mjs is removed from
    generatedWorktreePaths in tools/launch-worker.mjs:908-911 (so it is no longer excluded) and
    tools/test-tools.mjs's stageCheckout now pre-commits the hook file into the fixture repo, with
    a new assertion (git ls-files --error-unmatch) proving the installed hook stays a tracked
    worktree file. This does not eliminate future drift between the launcher's source copy and a
    worktree's base-branch commit, but it correctly converts that drift from silently masked (the
    original bug) to visible in git status, which is what the finding actually asked for.
  • 049a938a fixes a real regression introduced by the PR's own "make --reports-file required"
    decision: the concurrent-launch race test in tools/test-tools.mjs spawns launch-worker.mjs
    through a bespoke standalone runner script that bypasses the suite's shared run() helper (the
    helper auto-injects --reports-file at tools/test-tools.mjs:410-411, but this runner does
    not use it). Without this fix both concurrent invocations would fail at the new
    --reports-file is required usage check (tools/launch-worker.mjs:645) before ever reaching
    the budget-lock scenario the test exists to prove. Confirmed this is a legitimate, necessary
    fix and not decorative.

Low / Info

None posted (signal gate).

Subagents

Agent Verdict
parity-checker N/A — no apps/web/** or apps/mobile/** file changed
i18n-syncer N/A — no user-facing strings or i18n JSON changed
contract-aligner N/A — no packages/shared/src/types/* or orbit-api DTO changed
security-reviewer N/A — no orbit-api code changed
design-reviewer N/A — no apps/* or orbit-landing-page UI file changed

Validation

Check Result
Lint PASS (CI, head 049a938a)
Type check PASS (CI, head 049a938a)
Tests (Unit Tests) PASS (CI, head 049a938a)
Harness Execution (test-tools.mjs + test-hooks.mjs) PASS (CI, head 049a938a, completed after this review's first pass) — the specific new/changed cases were also independently traced by hand above against the committed source and found to exercise real code paths, not stubs
Build PASS (CI, head 049a938a)

Phase 6 (/validate) and Phase 7 (posting) skipped per this workflow's CI-wrapper contract; CI's
own job results are cited above via gh pr view --json statusCheckRollup.

Deferred — N/A dimensions & files not verdicted

  • Dimensions 8-14 (DESIGN.md/AI-slop, Parity, i18n, Contract drift, Security frontend/backend,
    FEATURES.md parity): all N/A, the diff touches no apps/*, orbit-api, packages/shared, or
    i18n surface — unchanged from both prior passes.
  • All 7 changed files in the PR (report-worker-turn.mjs, test-hooks.mjs, orchestrator.json,
    orchestrate/SKILL.md, launch-worker.mjs, test-tools.mjs, worker-status.mjs) received a
    verdict: two (report-worker-turn.mjs, worker-status.mjs) are byte-identical to the
    already-reviewed eaebb844 content (confirmed via diff), the other five carry this session's
    reviewed delta.
  • The hookVerification claim in .claude/orchestrator.json (real codex-cli 0.145.0 Stop-hook
    behavior) is a documentation assertion this sandbox cannot re-execute — no codex binary is
    available here. Accepted on the same basis the repo already accepts every other dated,
    cited codex-quirk entry in that file; not independently re-verified against a live process.
  • The sibling orbit-api repo is not checked out in this job, but no dimension in this PR needs
    it (no cross-repo surface changed).

What's good

  • Both High findings and all three Medium findings from the two prior reviews are closed with
    real, traceable fixes rather than reworded prose — each one checked against the actual
    committed source above, not taken on the commit message's word.
  • The concurrent-launch coverage fix (049a938a) shows real attentiveness: it is a one-line-root
    fix for a regression the PR's own --reports-file-required decision silently caused in a test
    that bypasses the suite's shared helper, exactly the kind of thing that is easy to miss.
  • The hookVerification field's format (dated, CLI-versioned, cited) matches this repo's own
    established convention for recording measured CLI quirks in orchestrator.json, rather than
    inventing a new documentation style for this one claim.
  • Comment policy is respected throughout the delta — no narration comments in any added code.

Recommendation

Approve. Both High findings and all Medium findings from the two prior CHANGES_REQUESTED
reviews are resolved with executable coverage or a verifiable, convention-consistent
documentation fix, and no new Critical/High issue surfaced in the diff since the last review.
The one residual soft spot — the Codex hook-wiring claim cannot be independently re-executed in
this sandbox — is a sandbox limitation, not a defect in the fix, and is handled the same way the
repo already handles every other codex measurement of this kind.

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: the current-head automated review approved 049a938 with no Critical, High, or Medium findings. Review item: PRR_kwDOR5Siws8AAAABHlZt-w

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: Vercel reports an intentionally skipped deployment and no review finding on current head 7283e7c. Review item: IC_kwDOR5Siws8AAAABMLTM3g

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: SonarQube reports a passing quality gate with zero new issues on current head 7283e7c. Review item: IC_kwDOR5Siws8AAAABMMcrvg

Comment thread tools/launch-worker.mjs

@claude claude 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.

Code Review: ORB-136 report structured worker status (PR #652)

Scope: PR #652 in thomasluizon/orbit-ui-mobile
Recommendation: REQUEST CHANGES

Summary

This PR replaces terminal-scraping worker supervision with structured JSONL reports: a new worktree-local Stop hook (report-worker-turn.mjs) appends one record per worker turn, launch-worker.mjs provisions the shared reports file and installs the hook for both Claude and Codex, worker-status.mjs folds report liveness into its existing hard git/PR/Linear checks, and orchestrate/SKILL.md documents the new babysitting loop. The new hook and the new worker-status.mjs checks (staged-uncommitted, merge-in-progress, unpushed-commits, report-fresh) are well designed and thoroughly tested, including a concurrency test proving 8 simultaneous appends lose no records. One real defect survives review: a design decision made in dad0175b ("fix: keep reporter tracked") removes the copied hook script from the worktree's git-status exclusion list so that source drift stays visible for the ui repo — but the same unconditional copy also runs for worktrees opened against orbit-api and orbit-landing-page, which are separate git histories that have never seen this file. That leaves it permanently untracked (and therefore permanently "dirty") there, which structurally breaks the new worktree-clean check this very PR introduces for two of the three configured repos.

Findings

Critical

None.

High

[HIGH] Copied worker-report hook is left untracked in orbit-api/orbit-landing-page worktrees, permanently failing the new worktree-clean check
· dimension: 1. Correctness
· location: tools/launch-worker.mjs:908-911, 926-937
· issue: launch-worker.mjs copies orbit-ui-mobile's own .claude/hooks/report-worker-turn.mjs into
  every launched worktree unconditionally (line 937: `copyFileSync(hookSource, hookTarget)`) for
  whichever repo the ticket's repo:* label resolves to (line 731-734: `repoPath =
  config.repos[repoKey]`, where repoKey is "ui", "api", or "landing" per
  .claude/orchestrator.json). `generatedWorktreePaths` (lines 908-911) only excludes
  `/.claude/settings.local.json` and `/.codex/hooks.json` from the worktree's git status —
  commit dad0175b ("fix: keep reporter tracked") deliberately dropped the hook script from this
  list so drift stays visible for the ui-mobile repo's own history. But
  report-worker-turn.mjs is brand-new to this PR and lives only in orbit-ui-mobile's own git
  history (root CLAUDE.md: orbit-api and orbit-landing-page are separate histories), so it cannot
  already be tracked in either sibling repo.
· risk: Any ticket launched with `--repo api` or `--repo landing` (a routine, first-class scenario
  per root CLAUDE.md's cross-repo workflow, not an edge case) leaves an untracked
  `.claude/hooks/report-worker-turn.mjs` sitting in the worktree. The worker's own contract
  forbids blanket-staging (`git add -A`/`git add .`), so nothing ever commits or clears this file.
  tools/worker-status.mjs's new `worktree-clean` check (`dirty = git(["status","--porcelain"])`,
  `ok: dirty.length === 0` at worker-status.mjs:145,319) then reports UNMET forever for that
  ticket, even once the worker's real work is committed, pushed, reviewed, and merge-ready. This
  breaks the exact done-detection contract this PR exists to add, for 2 of the 3
  orchestrator-tracked repos. Verified directly: config.repos supports ui/api/landing keys
  (launch-worker.mjs:710,733), the hook-copy path has no repoKey branching, and git status
  --porcelain includes untracked files by default.
· fix: Before copying, check whether the target repo already tracks the hook path
  (e.g. `git -C worktreePath ls-files --error-unmatch .claude/hooks/report-worker-turn.mjs`,
  allowing failure). When it is NOT already tracked (the api/landing case), add
  `/.claude/hooks/report-worker-turn.mjs` back to `generatedWorktreePaths` before writing the
  exclude file. Keep it un-excluded for orbit-ui-mobile itself, since SKILL.md states the
  reporter "stays tracked, so any source drift remains visible" — that drift-detection benefit
  should be preserved for the repo that actually owns the file, without breaking the check for
  the other two.
· reference: CLAUDE.md rule 1 (root cause over workarounds — the hook-installation step should
  handle all three configured repos, not just the one it was tested against); root CLAUDE.md
  "cross-repo work uses an API ticket blocking a UI ticket" (cross-repo is a designed, routine
  path, not exotic).

Medium

[MEDIUM] Hook-copy test fixture always pre-tracks the file, masking the untracked-file gap
· dimension: 15. Harness changes need EXECUTED evidence
· location: tools/test-tools.mjs:792-812 (stageCheckout)
· issue: stageCheckout pre-creates and commits .claude/hooks/report-worker-turn.mjs into the
  fixture repo (path literally `repos/ui`) BEFORE `worktree add` runs, and every test that
  exercises the hook-install path (pointerDeliveryCases, launchWorkerCases) uses this one
  fixture. No fixture simulates a target repo where the copied file starts out untracked, which
  is exactly the orbit-api/orbit-landing-page scenario above.
· risk: The harness stays green even though the hook-installation step is broken for 2 of 3
  configured repos — a new decision path (repo already tracks the hook vs. does not) shipped with
  no case of its own, so a regression here would not be caught either.
· fix: Add a second fixture (or parameterize stageCheckout) that creates the worktree's target
  repo WITHOUT pre-committing report-worker-turn.mjs, then assert after a real launch that (a) the
  copied file exists, and (b) `git status --porcelain` in that worktree is clean immediately
  after installation (i.e., the file is either tracked-and-clean or properly excluded).
· reference: rubric dimension 15 — a new decision path added to a tool that already has coverage
  needs its own case, not an extension of an existing assertion.

Low / Info

None (signal gate: Low/Info are not surfaced on a PR review).

Subagents

Agent Verdict
parity-checker N/A — no apps/web/** or apps/mobile/** file changed
i18n-syncer N/A — no user-facing strings or i18n JSON changed
contract-aligner N/A — diff touches neither packages/shared/src/types/* nor orbit-api
security-reviewer N/A — no orbit-api code changed
design-reviewer N/A — no apps/web/**, apps/mobile/**, or orbit-landing-page/src/** UI file changed

Validation

Phase 6 (/validate) skipped per this workflow's CI adaptation — Build / Unit Tests / SonarCloud run as separate required checks on this PR.

Prior reviews on this PR

Earlier rounds on this PR requested changes twice and were then approved at 049a938a. That approval predates this finding's root cause: commit dad0175b ("fix: keep reporter tracked"), which removed the hook script from the git-status exclusion list, landed before 049a938a and was not flagged by the prior review. This is not a re-flag of an already-resolved concern — it is a defect that has been present since before the last approval and was missed.

What's good

  • The Stop hook (report-worker-turn.mjs) is small, defensive, and correctly validates its own inputs (--reports-file absolute, --ticket matches ORB-\d+, gate values whitelisted, contractItems type-checked) before trusting anything from the model's own output.
  • Genuinely excellent test coverage for the new pieces: a real concurrency test proves 8 simultaneous hook invocations append exactly 8 well-formed records with no interleaving corruption; the fallback path (missing/malformed WORKER_REPORT: marker) is tested and correctly marks needsHuman: true.
  • worker-status.mjs's new checks (staged-uncommitted, merge-in-progress via MERGE_HEAD, unpushed-commits via a fresh ls-remote + targeted fetch) are all individually correct and each has a dedicated git fixture reproducing the exact failure mode.
  • The Codex --dangerously-bypass-hook-trust flag is deduplicated correctly and documented with genuine measured evidence plus an official-docs URL in orchestrator.json.
  • launch-worker.mjs correctly refuses a --reports-file living inside any configured repo or inside the new worktree itself, mirroring the existing --prompt-file protection.

Recommendation

Fix the High finding (make the hook-exclude decision conditional on whether the target repo already tracks the file, so the copy doesn't pollute git status in non-ui-mobile worktrees) before merge — it silently breaks the PR's own headline feature for orbit-api and orbit-landing-page tickets. Add the Medium's fixture case in the same pass so the gap can't regress silently. Everything else in the diff is solid and well-tested; re-review should be fast once those two related items land.

@thomasluizon

Copy link
Copy Markdown
Owner Author

Fixed in 6e87ceb8522861562482a5ce85d8c919173ea801: target repositories that do not track the worker report hook now exclude the generated copy, while orbit-ui-mobile keeps its tracked reporter visible for drift. The new real-launch fixture proves installation and a clean worktree for the untracked case. Review item: PRR_kwDOR5Siws8AAAABHliv9g

@thomasluizon

Copy link
Copy Markdown
Owner Author

Fixed in 6e87ceb: target repositories that do not track the worker report hook now exclude the generated copy, while orbit-ui-mobile keeps its tracked reporter visible for drift. The new real-launch fixture proves installation and a clean worktree for the untracked case. Review item: PRR_kwDOR5Siws8AAAABHliv9g

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required: Vercel reports an intentionally skipped deployment and no review finding on current head 6e87ceb. Review item: IC_kwDOR5Siws8AAAABMLTM3g

@thomasluizon

Copy link
Copy Markdown
Owner Author

Acknowledged automated activity IC_kwDOR5Siws8AAAABMLTM3g on current PR head 258a832. The skipped Vercel deployment is expected because this tools-only change does not affect the web deployment.

@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: 258a832231

ℹ️ 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/worker-status.mjs Outdated
@thomasluizon

Copy link
Copy Markdown
Owner Author

@codex review

@thomasluizon

Copy link
Copy Markdown
Owner Author

Acknowledged automated activity IC_kwDOR5Siws8AAAABMLTM3g on current PR head 40c942c: the skipped Vercel deployment is expected for this tools-only change. Acknowledged automated activity IC_kwDOR5Siws8AAAABMN6V9g on the same head: SonarCloud passed with zero new issues.

@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: 40c942ce54

ℹ️ 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/worker-status.mjs
@thomasluizon

Copy link
Copy Markdown
Owner Author

Escalation for ORB-136

Current PR head: 40c942ce540b5edc4569fa25824a8ad014d36f08.

Thread PRRT_kwDOR5Siws6Urhox, comment PRRC_kwDOR5Siws7a5M26, is the second consecutive Codex cycle on the same gate-completeness finding. The first cycle identified empty and not-run gate sets; commit 40c942ce540b5edc4569fa25824a8ad014d36f08 rejects both and adds regression coverage. The next cycle shows the remaining case: a partial set such as lint alone can still pass. Per standing contract clause 4, I will not attempt this finding a third time.

A correct remaining fix needs a canonical required-gate schema across every repository this monitor checks. tools/worker-status.mjs monitors the UI, API, and landing worktrees from .claude/orchestrator.json, while WORKER_REPORT.gates currently uses freeform command keys. Hardcoding UI gate names would make API and landing completion incorrect. The repository needs either standardized gate identifiers or a per-repository required-gate manifest before the monitor can safely reject every omitted mandatory gate.

Evidence on this head:

  • node tools/test-tools.mjs: ORBIT TOOLS GATE OK
  • npm run lint: passed
  • npm run type-check: passed
  • npm run test: passed
  • All current-head code CI checks are green. The only failing workflow is review, where Claude could not execute because Anthropic returned HTTP 429 for the weekly quota, with reset at 2026-07-30 07:00:00Z.
  • The branch is clean, pushed, and contains current origin/main.
  • No other review thread is unresolved. This thread remains open intentionally as the escalated finding.

Acknowledged automated activity IC_kwDOR5Siws8AAAABMOEVZA on PR head 40c942ce540b5edc4569fa25824a8ad014d36f08: SonarCloud passed with zero new issues.

@thomasluizon

Copy link
Copy Markdown
Owner Author

@codex review

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required for d68fbcc: Vercel item IC_kwDOR5Siws8AAAABMLTM3g reports an intentionally skipped deployment and no review finding for this tools-only change.

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required for d68fbcc: SonarCloud item IC_kwDOR5Siws8AAAABMPgHVg passed with zero new issues, zero accepted issues, and zero security hotspots.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: d68fbcc61f

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

@thomasluizon

Copy link
Copy Markdown
Owner Author

No code change required for d68fbcc: Codex item IC_kwDOR5Siws8AAAABMPibnA found no major issues and explicitly reviewed current head d68fbcc.

@thomasluizon thomasluizon left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Code Review: PR #652 (ORB-136, report structured worker status)

Scope: PR #652 in thomasluizon/orbit-ui-mobile (head d68fbcc6, 7 files, +978/-59)
Recommendation: NEEDS WORK

Summary

This is a harness-only change: a worktree-local Stop hook that appends one structured JSONL
record per worker turn, launcher wiring that provisions the shared reports file and installs the
hook for both engines, and a worker-status.mjs that now combines report liveness with hard git
state. The design is sound and the test additions are unusually thorough: the concurrency case,
the fallback-marker case, and the new git-state fixtures are real executed coverage, and the
Harness Execution job is green on this head. Two things block: the shared reports file has no
tolerance for a single corrupt line, which takes down status for every ticket in the run at once;
and the installed Stop hook has never been observed firing under either shipped engine
invocation, which is exactly the gap rubric dimension 15 exists to catch.

Findings

Critical

None.

High

[HIGH] One corrupt line in the shared reports.jsonl takes worker-status down for every ticket in the run
· dimension: 1 (Correctness) / 12 (Error handling at boundaries)
· location: orbit-ui-mobile/tools/worker-status.mjs:169-186 (the `if (reportsFile)` parse block;
  the `fail(3, ...)` is at :180)
· issue: the reports file is ONE path shared by every worker in every wave of a run
  (SKILL.md §2: "Create ONE reports.jsonl path ... Reuse that absolute path for every worker in
  every wave"). The parse does `lines.map(line => { try { return JSON.parse(line) } catch {
  fail(3, ...) } })`, and `fail` exits the process. So a line written by worker B kills the status
  check for worker A, C and D as well.
· risk: compounded by the SKILL.md rewrite. §3 now says "Terminal text is never the normal status
  source" and "A missing report is the diagnostic trigger ... worker-status.mjs marks a worker
  suspect ... Only after that verdict may you inspect its terminal". An exit 3 produces no verdict
  at all, so the one documented escape hatch never opens. In a `--sleep` run the whole fleet goes
  dark behind a one-line parse error. Reachable whenever a hook process dies mid-append: the hook
  itself (.claude/hooks/report-worker-turn.mjs:100-106) throws on a short `writeSync` AFTER the
  partial bytes are already on disk, and teardown-worktree.mjs kills terminals while sibling
  workers are still writing.
· repro (red, ran against this PR's head):
    line 1: valid ORB-136 record
    line 2: '{"reportedAt":"...","ticket":"ORB-999","headSh'   <- truncated, no newline
    line 3: valid ORB-136 record
    $ node tools/worker-status.mjs --worktree <wt> --issue ORB-136 --reports-file reports.jsonl --json
    reports file line 2 is not valid JSON
    EXIT=3
  ORB-136's own two records are intact and it still gets nothing.
· fix: the JSONL file is a multi-writer external input, so treat it as a trust boundary and
  degrade instead of aborting: skip unparseable lines, count them, and surface the count as part
  of the `report-fresh` detail (e.g. `2 unreadable line(s) skipped`). A worker whose own latest
  record was the corrupt one then falls through to the existing `no report exists for ORB-N`
  rejection and the `suspect` liveness verdict, which is the behaviour the skill already
  documents and the orchestrator already knows how to act on.
· reference: CLAUDE.md rule 8 (error handling at boundaries; never let a boundary failure take
  down the caller), rubric dimension 1 (boundary conditions)
[HIGH] The installed Stop hook has never been observed firing on either shipped engine invocation
· dimension: 15 (Harness changes need EXECUTED evidence)
· location: orbit-ui-mobile/tools/launch-worker.mjs:951-970 (generated hook commands);
  .claude/orchestrator.json (the new `hookVerification` entry)
· issue: the PR makes structured reports "the normal status path", but nothing in the change set
  executes the path end to end.
  - Codex: the only recorded measurement is `hookVerification`, which states the evidence came
    from "a real codex exec invocation". The launcher launches BARE INTERACTIVE `codex`, and this
    repo refuses `codex exec` outright as a headless token (orchestrator.json codex `notes`:
    "codex exec is the NON-interactive subcommand and lands in the same unsupervisable place as
    claude -p"). The measured invocation is not the shipped invocation.
  - Claude: no measurement, no doc citation, nothing. The Claude Stop hook is the status channel
    for every claude-engine worker and its only evidence is a string assertion.
  - The tests assert the generated command STRINGS (tools/test-tools.mjs, the `reportCommands`
    block) and separately execute the hook script with a synthetic payload
    (.claude/hooks/test-hooks.mjs), but nothing executes the generated command, and nothing
    observes a real engine emitting Stop.
· risk: if either engine does not emit Stop per turn in TUI mode, or the generated command does
  not resolve as written, that engine's workers are silently permanently suspect. The degradation
  is safe (suspect -> terminal diagnosis) but it costs a 30-minute window per worker per check and
  it silently reverts the run to the expensive terminal-scraping this ticket exists to replace.
· fix: run one real launch per engine and paste the appended `reports.jsonl` line into the PR
  body, using the shipped `node tools/launch-worker.mjs --issue ORB-N --prompt-file ... --reports-file
  ...` invocation, bare interactive `codex` for one and `claude` for the other, one worker turn,
  then `cat` the record. Two launches, and both halves of the claim become executed evidence.
  Then correct the `hookVerification` note to name the invocation that was actually measured.
· reference: rubric dimension 15 ("A claim that a tool, hook, skill, or agent works (in the PR
  body, a code comment, or the review) must trace to a command that ran and its output")

Medium

[MEDIUM] The launcher writes exclude entries into the SHARED .git/info/exclude, not the worktree's
· dimension: 5 (No-workaround / root-cause)
· location: orbit-ui-mobile/tools/launch-worker.mjs:932-942
· context: this is not a duplicate of the resolved thread "Copied worker-report hook is left
  untracked in orbit-api/orbit-landing-page worktrees". The exclude write IS that thread's remedy;
  the finding is a side effect of the remedy that the thread did not cover.
· issue: `git rev-parse --git-path info/exclude` inside a linked worktree resolves to the parent
  repo's COMMON exclude file, not a per-worktree one. Verified:
    $ git worktree add --detach ../wt HEAD && cd ../wt && git rev-parse --git-path info/exclude
    .../repo/.git/info/exclude
  So every launch permanently edits the parent repo's exclude file, affecting the main checkout
  and every sibling worktree. `tools/teardown-worktree.mjs` contains no reference to `exclude`,
  `settings.local` or `.codex`, so nothing ever removes them.
· risk: `/.codex/hooks.json` (and, in orbit-api / orbit-landing-page, `/.claude/hooks/
  report-worker-turn.mjs`) become invisible to `git status` and `git add .` in the real repo,
  forever, as a side effect of an unrelated worker launch. The dedupe via the `excludeLines` Set
  keeps the file from growing, so this is silent rather than noisy.
· fix: either commit the two paths to each repo's tracked `.gitignore` (they are generated runtime
  files in all three repos, so this is the honest home for them), or scope the exclusion to the
  worktree with `git config --worktree core.excludesFile <worktree-local file>` after enabling
  `extensions.worktreeConfig`. Whichever is chosen, have `teardown-worktree.mjs` reverse it.
· reference: CLAUDE.md rule 1 (root cause over workarounds); "a permanent machine-enforced fix is
  the deliverable"
[MEDIUM] tools/README.md still documents an invocation that now exits 2
· dimension: 2 (stale) / repo docs-registry convention
· location: orbit-ui-mobile/tools/README.md:51
· issue: the catalog's Invocation column still reads `node tools/launch-worker.mjs --issue ORB-N
  --prompt-file <path>`. `--reports-file` is now required, and this PR's own test asserts it
  (`launch-worker.mjs: requires --reports-file` -> status 2), and that test is green in the
  Harness Execution job. The README row's description also still enumerates "the four measured
  launch gotchas" and says nothing about hook installation or the reports file.
· risk: `tools/README.md` is the tool catalog an agent reads instead of the source. Copy-pasting
  the documented command now fails with exit 2 and the agent has to go read the tool anyway.
· fix: update the row's Invocation to include `--reports-file <absolute path>` and add one clause
  to the description covering the reports-file provisioning and the two Stop hooks, in this PR.
· reference: root CLAUDE.md ("Tools follow tools/CONVENTIONS.md; catalog ... tools/README.md";
  "When you change a doc, update its At a glance header and this registry in the same edit")
[MEDIUM] worker-status's report checks fail OPEN when --reports-file is omitted
· dimension: 6 (gates over prose)
· location: orbit-ui-mobile/tools/worker-status.mjs:462, 498
· issue: `--reports-file` is optional. Omit it and the `report-fresh` / `report-accepted` checks
  are never pushed into `checks`, `liveness` becomes `"not-checked"`, and the tool can print
  CONTRACT MET having verified no liveness at all. The only thing that makes the orchestrator pass
  the flag is a sentence in SKILL.md §3, and that is prose, which decays as context fills.
· risk: the exact failure this ticket exists to remove (a silent worker read as complete) returns
  the first time the flag is dropped from the command, and the verdict looks identical to a
  genuinely healthy one.
· fix: keep the flag optional for the standalone use the PR body describes, but make the
  difference visible rather than silent: when `--reports-file` is absent, print the liveness line
  as `NOT-CHECKED liveness: no reports file supplied; completion is artifact-only` in the text
  output too (today that line is inside `if (reportsFile)`), so a verdict with no liveness can
  never be mistaken for one with liveness. Better still, have `launch-worker.mjs` record the
  reports path in the worktree so `worker-status.mjs` can default to it.
· reference: CLAUDE.md "Gates over prose"; rubric dimension 6
[MEDIUM] New refusal paths and payload branches ship without their own cases
· dimension: 15 (a new decision path needs its own case)
· location: orbit-ui-mobile/tools/worker-status.mjs, tools/launch-worker.mjs
· issue: the diff adds these decision paths, none of which has a test:
  - worker-status: `--reports-file` present with no value -> exit 2 (:117)
  - worker-status: reports file unreadable -> exit 3 (:174)
  - worker-status: malformed JSONL line -> exit 3 (:180), the High above
  - worker-status: `gates` not an object -> "gates payload is invalid" (:227)
  - worker-status: a gate value outside passed/failed/not-run -> "gate results are invalid" (:235)
  - launch-worker: reports file inside the NEW worktree -> exit 3 (:914)
  - launch-worker: reports file cannot be provisioned -> exit 3 (:876)
  - launch-worker: exclude write fails -> exit 3 (:942)
  - launch-worker: Stop hook install fails -> exit 3 (:972)
  - launch-worker: `gitTracksPath` exit > 1 -> exit 3 (:423)
  - launch-worker: the config ALREADY declares `--dangerously-bypass-hook-trust` (the dedupe
    branch at :824); only the not-declared side is asserted
· risk: each is a refusal that merges unexecuted; the rubric's own history is that the
  unexecuted refusal is where harness bugs live (the `orca terminal wait` "not yet" case).
· fix: add a case per path. The three fail(3) install paths are cheap to drive by pointing the
  launcher at a read-only directory; the gates-payload branches are pure fixture edits alongside
  the existing `rejectedReports` table, which is already the right shape for them.
· reference: rubric dimension 15

Subagents

Agent Verdict
parity-checker N/A, no apps/web/** or apps/mobile/** file changed
i18n-syncer N/A, no user-facing string or locale file changed
contract-aligner N/A, single repo; no packages/shared/src/types/* or endpoints.ts change
security-reviewer N/A, no orbit-api code changed
design-reviewer N/A, no UI file changed

Validation

Evidence is the CI run on this PR's head (d68fbcc6), not a local re-run: the working tree is on
an unrelated branch, so a local /validate would have validated the wrong code.

Check Result
Lint PASS (job 90548985744)
Type check PASS (job 90548985793)
Tests PASS, Unit Tests (job 90549235943)
Harness Execution (test-tools.mjs + test-hooks.mjs) PASS (job 90548986504, 5m46s). Rubric dimension 15's required citation
Build (api) N/A, no orbit-api change
review (claude-review.yml) FAIL. Not a code defect: 429 rate_limit_event, rateLimitType: seven_day, "You've hit your weekly limit, resets 7am (UTC)". The reviewer never rendered a verdict; the red check is a quota artefact.

Deferred: N/A dimensions & files not verdicted

Every changed file got a verdict; nothing is deferred on coverage. Dimensions marked N/A, each
because the diff never touches its surface:

  • 8 DESIGN.md / AI-slop: no apps/* UI file changed.
  • 9 Parity: no apps/web/** or apps/mobile/** file changed.
  • 10 i18n: no locale file or user-facing string changed.
  • 11 Contract drift + backward-compat: no packages/shared schema and no orbit-api DTO in
    the diff, so Phase 5's field add/remove/rename scan had no candidates. No
    ⚠️ breaks old mobile clients risk exists in this change.
  • 13 Backend hard rules: no orbit-api change.
  • 14 FEATURES.md parity: harness-only; no screen, route, Astra/MCP tool, gating, platform or
    locale behaviour changed.
  • 6 Type safety: .mjs tooling, no TypeScript surface; no any-class escape hatch exists to
    check.

Checked and clean, listed so "clean" does not read as "not looked at": 2 dead code (one note
below), 3 SOLID (threadHasFix is 54 lines, marginally over the ~50 soft cap and well under
the ~100 hard cap, defensible as one cohesive predicate), 4 comment policy (the new hook
carries zero comments; no narration added anywhere), 5 no-workaround (the
--dangerously-bypass-hook-trust flag is the vendor-sanctioned path for vetted automation and
carries a WHY-with-URL in hookVerification), 7 no console.log (the CLI's stdout contract,
pre-existing), 12 security (the generated hook command interpolates only a resolved absolute
path and an issue already validated against ^[A-Z]+-\d+$).

One sub-Medium note not posted as a finding, per the signal gate: the new staged-uncommitted
check (worker-status.mjs:374) can never fail independently. git status --porcelain, which
already backs the existing worktree-clean check, reports every staged path. The PR's own
staged-merge fixture demonstrates it: both checks go red together.

What's good

  • The concurrency test is the right test. Eight simultaneous hook processes, asserting both
    that all exit 0 and that all eight lines survive and parse, is exactly the property a shared
    append-only channel needs, and it is proved by execution rather than argued from O_APPEND
    semantics.
  • The fallback record is fail-safe by construction. A missing or malformed WORKER_REPORT
    marker still appends a record, with blockedOn set to the explicit reason and needsHuman: true,
    so a worker that forgets the contract escalates instead of vanishing. That is the correct
    default and it is tested.
  • Hard git state now outranks a healthy PR. staged-uncommitted, merge-in-progress and
    unpushed-commits close the exact hole the ticket names, and the two fixtures prove the
    interesting half: a green Linear state and an approved PR no longer mask a wedged worktree.
  • The launcher refuses a reports path inside any repo or the new worktree with the same shape
    as the existing prompt-file refusal, and the consistency means an agent that learned one already
    knows the other.
  • Ordering is right: the hook is installed before createTerminal, so the engine picks it up
    at startup rather than needing a mid-session reload.
  • hookVerification is an honest artefact even though it is incomplete: it names the date, the
    CLI version, the exact payload fields observed and the doc URL. The fix for the High above is to
    extend it, not to write it from scratch.

Recommendation

Two things before merge:

  1. Make the reports-file parse degrade instead of aborting (High #1). This one is small and it is
    what stops a single truncated line from blacking out an unattended run.
  2. Produce the executed evidence for the shipped path (High #2): one real launch per engine, the
    appended reports.jsonl record pasted into the PR body, and hookVerification corrected to
    name the invocation actually measured.

The four Mediums are all cheap and land naturally alongside those two, the README row and the
info/exclude scoping in particular, since both are the kind of silent drift that is much harder
to find later than it is to fix now.

@thomasluizon

Copy link
Copy Markdown
Owner Author

Correction to my review above: withdrawing the second High

My review posted two High findings. The second one is wrong and I am withdrawing it. The
adversarial pass finished after I posted and refuted it by running the two experiments the PR
never ran.

What I claimed

"The installed Stop hook has never been observed firing on either shipped engine invocation"
(rubric dimension 15), on the grounds that hookVerification measured codex exec rather than
the bare interactive codex the launcher actually runs, and that the Claude side had no
measurement at all.

What measurement showed

Both engines were run under a real PTY via winpty. This is why every earlier pass stopped at
reading the diff: bare codex and claude exit stdin is not a terminal under a pipe.

Codex, bare interactive TUI, codex-cli 0.145.0 on Windows 11, exact shipped flag set including
--dangerously-bypass-approvals-and-sandbox --dangerously-bypass-hook-trust. The TUI printed
⚠ --dangerously-bypass-hook-trust is enabled. and • Running 2 Stop hooks. The project-local
.codex/hooks.json Stop hook fired, delivering exactly the fields report-worker-turn.mjs reads:

{"hook_event_name":"Stop","cwd":"C:\\...\\hooktest","last_assistant_message":"pong","turn_id":"019fad99-..."}

codex features list reports hooks stable true, a global feature rather than an exec-scoped
one, and --dangerously-bypass-hook-trust is at root help line 95, valid on the interactive path.

Claude, bare interactive TUI, brand-new untrusted folder, --permission-mode bypassPermissions, with a .claude/settings.local.json written in the exact shape
launch-worker.mjs:962 generates:

{"hook_event_name":"Stop","cwd":"...","last_assistant_message":"pong","permission_mode":"bypassPermissions"}

So on Windows $CLAUDE_PROJECT_DIR expands in the generated command, settings.local.json is an
honored hook source, and there is no hook approval prompt, so a worker does not stall on one.

Why the severity was wrong twice over

Besides being empirically false, the finding also mis-weighted the failure mode, which is
fail-closed. If the hook never fired, worker-status.mjs:462-471 still unshifts report-fresh,
:498 sets liveness: "suspect", :519 exits 1, and the new 60 to 120 second periodic wake runs
the artifact check for every active ticket even when no line was appended. A dead hook pins every
worker at SUSPECT and CONTRACT NOT MET and re-opens terminal diagnosis. It degrades loudly to the
pre-PR behaviour, never to a false "done", which is the opposite of the silent-success class
dimension 15 exists to catch. The shipped wiring is correct as written and needs no code change.

What survives, downgraded to Low and non-blocking

hookVerification does literally say "A real codex exec invocation", which is the subcommand
launch-worker.mjs refuses, and the claude worker entry has no hookVerification at all. Also
true: no test executes the generated command string. tools/test-tools.mjs:1019-1028 asserts the
two commands only contain the reports path and --ticket ORB-75, and
.claude/hooks/test-hooks.mjs:1171-1176 runs the hook script directly with a synthetic payload,
bypassing the shell, the $CLAUDE_PROJECT_DIR expansion and both engines.

That is a documentation gap, not a defect. The fix is to paste the two measurements above into the
respective worker entries in .claude/orchestrator.json, dated 2026-07-29, codex-cli 0.145.0,
Windows 11, both under a PTY.

Net effect on the verdict

Unchanged: still NEEDS WORK, now on one High rather than two. The blocker is the reports-file
parse, which I reproduced red against this PR's head: a truncated line written by one ticket makes
worker-status.mjs exit 3 for a different ticket whose own records are intact, and an exit 3
produces no suspect verdict, so the terminal-diagnosis path the skill gates behind that verdict
never opens. The four Mediums stand.

Copy link
Copy Markdown
Owner Author

Acknowledgement for review activity PRR_kwDOR5Siws8AAAABHowBKA on the prior head.

Fix commit: f8c09db99c5f5c1766a00e5a36c31af6bc829f59.

  • Corrupt shared JSONL records are skipped and counted; a valid ORB-136 record still participates, while no valid target record is reported as suspect.
  • Real engine evidence is now recorded in .claude/orchestrator.json and the PR body. Claude's bare engine and installed settings hook wrote a complete record. Codex linked-worktree hook discovery is explicitly UNVERIFIED after the real launched TUI left the report file empty.
  • Generated hook paths now use a worktree-specific core.excludesFile; the shared .git/info/exclude is unchanged and teardown removes the generated exclude file.
  • tools/README.md now documents the reports file and Stop hooks with the required launcher argument.
  • Text-mode status without a reports file now prints NOT-CHECKED instead of silently omitting liveness.
  • Coverage now exercises the missing reports-file value, unreadable reports target, corrupt neighbor and corrupt-only JSONL, invalid gate payload/value, reports path inside the worktree, exclude and Stop-hook failures, git ls-files errors, Codex hook-trust deduplication, and teardown cleanup.

Verified on the fix commit: exhaustive tools gate, lint, type-check, tests, hook parity, dash baseline, copy baseline, syntax, and diff checks all pass.

Copy link
Copy Markdown
Owner Author

@codex review

@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: f8c09db99c

ℹ️ 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/launch-worker.mjs Outdated
@sonarqubecloud

Copy link
Copy Markdown

Copy link
Copy Markdown
Owner Author

No code change required for automated activity IC_kwDOR5Siws8AAAABMLTM3g: Vercel reports an intentionally skipped deployment and no review finding. No code change required for automated activity IC_kwDOR5Siws8AAAABMQjgjQ: SonarQube reports a passing quality gate with zero new issues. Evidence: 9b86a2f58d8c3352e1563eda682e8d4bc732d156.

Copy link
Copy Markdown
Owner Author

@codex review

Copy link
Copy Markdown
Owner Author

No code change required for automated activity IC_kwDOR5Siws8AAAABMRUL-A: SonarQube reports a passing quality gate with zero new issues on the current head. Evidence: 9b86a2f58d8c3352e1563eda682e8d4bc732d156.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 9b86a2f58d

ℹ️ About Codex in GitHub

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

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

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

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

Copy link
Copy Markdown
Owner Author

No code change required for automated review activity IC_kwDOR5Siws8AAAABMRZMZQ: Codex reviewed current head 9b86a2f58d8c3352e1563eda682e8d4bc732d156 and found no major issues. Evidence: 9b86a2f58d8c3352e1563eda682e8d4bc732d156.

@thomasluizon

Copy link
Copy Markdown
Owner Author

Closing unmerged. This ticket's premise was replacing TUI terminal scraping with structured worker reports. The harness is moving to headless codex exec workers, so there is no terminal left to scrape and the scraping this replaces is being deleted outright.

What remains in this PR is worker-authored status, which repeats the dominant defect class in the 2026-07-28/29 ledger: a report asserting an outcome nothing independently verified. Supervision moves instead to independent reconciliation against git, the forge, process exit and Linear, none of which the worker can author. tools/worker-status.mjs already derives its verdict from commits, push state, pull request and Linear without this change.

The open High on this branch (one corrupt line in the run-wide shared JSONL calls fail(3) and exits, taking the status check down for every worker in the run) is folded into the root-cause ticket for "a tool reports an outcome it never verified" rather than fixed here.

@thomasluizon
thomasluizon deleted the feature/orb-136-have-workers-report-status-instead-of branch July 29, 2026 14:47
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