docs(shadow): Lior antigravity check - report Otto and Codex drift#3373
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a single shadow lesson log under docs/research/ recording detected drift in two agents during an antigravity check.
Changes:
- New research log documenting Otto's narration-over-action drift on PR #3370 and a contaminated Codex worktree.
- Notes corrective actions taken (backlog decomposition, PR preservation, lock cleanup).
6 tasks
AceHack
added a commit
that referenced
this pull request
May 15, 2026
…ns (#3375) * feat(b-0530): cron-sentinel-mutex — detect concurrent Otto-CLI sessions Implements the cheap-effort mitigation from docs/backlog/P3/B-0530-cron-sentinel-mutex-prevent-otto-cli-self-contention-2026-05-15.md + the worktree-prune-race root-cause analysis landed in PR #3370. This is the action-side parity proof for the narration filed in B-0530 and Pattern 8 of B-0519: Lior's antigravity check at 0220Z (PR #3373) flagged "narration-over-action drift" — listing mitigations without implementing them. This commit closes that gap. The mutex is a diagnostic, not a gate: it returns a structured MutexResult that callers (the <<autonomous-loop>> tick body) use to decide whether to defer git-mutating work. Empty peer list → proceed normally. Non-empty → bus-publish a deferral envelope and skip git ops this tick. Implementation: - tools/orchestrator-checks/cron-sentinel-mutex.ts (103 lines) - spawnSync("pgrep", ["-afl", "claude-code"]) with args-as-array (no shell, no injection — same pattern as sibling verify-branch.ts) - Excludes self-PID; excludes ancestors that lack the claude-code stdio flags --output-format / --input-format - Exports checkPeerSessions() + formatResult() for testability - if (import.meta.main) main() guard so imports don't trigger side effects - --json output for shell composition - tools/orchestrator-checks/cron-sentinel-mutex.test.ts (91 lines) - 8 tests covering: no peers, exclude-self, exclude-ancestors, empty-stdout, malformed-lines, self-with-matching-flags, formatResult-empty, formatResult-multi-peer Verified: - bunx tsc --noEmit clean - bun test: 8 pass / 0 fail - semgrep --config .semgrep.yml --error: 0 findings - Live smoke detected 3 concurrent claude-code sessions (real-world validation of the diagnostic) Next step (not in this PR): wire this into the autonomous-loop substrate so the <<autonomous-loop>> tick body invokes the mutex at the top and defers when peers are detected. Filed as B-0530 follow-up; this PR ships the building block. Co-Authored-By: Claude <noreply@anthropic.com> * fix(b-0530): distinguish pgrep failures from true no-peer + add sonarjs disable Two code-review findings from PR #3375 Codex review: 1. P1: `checkPeerSessions` now checks `result.error` (spawn failure, e.g., pgrep binary missing) and `result.status > 1` (pgrep runtime error). Previously both silently returned `peerDetected=false`, masking an unknown mutex state. Now surfaces `pgrepError` in `MutexResult` so callers know the check itself failed. 2. P0: Add `eslint-disable-next-line sonarjs/no-os-command-from-path` before the `spawnFn("pgrep", ...)` call. Rationale inline: pgrep is a known system binary, args-array form prevents shell injection. Tests: +3 new cases covering spawn-error, status-2 exit, and formatResult error-message rendering. All 11 tests pass. Co-Authored-By: Claude <noreply@anthropic.com> * fix(b-0530): main() returns PGREP_ERROR_EXIT on unknown mutex state Codex P1 finding [SEb1] on PR #3375: `main()` only branched on `peerDetected`, so when `checkPeerSessions()` reported `pgrepError` (set by peer-Otto's commit 0b3d03b), the CLI still exited 0 even though the mutex check itself failed. Shell callers gating on the exit code would proceed as if there were no peers. Extracted exit-code mapping into `mainResult(r: MutexResult)` so it is unit-testable without process.exit. Added `PGREP_ERROR_EXIT = 251` constant for "pgrep failed, mutex state unknown" — distinct from the 0..250 peer-count range so shell callers can branch on it explicitly. Exit code matrix: 0 = no peers, no error (safe to proceed) 1..250 = 1 + peer count (caller should defer) 251 (new) = pgrep error / unknown state (caller should defer) Tests: +5 new cases covering all four mainResult branches plus error-takes-precedence-over-peers. 16/16 pass (8 original + 3 from peer's 0b3d03b + 5 new). Composes with peer-Otto's 0b3d03b which added pgrepError tracking and the sonarjs suppression. This commit closes the last of the 3 PR #3375 review threads (#R3Mn + #R4ji peer-fixed already; #SEb1 fixed here). Co-Authored-By: Claude <noreply@anthropic.com> * fix(b-0530): --json mode also returns mainResult exit code Codex P1 finding on PR #3375: the --json branch always called process.exit(0), so shell callers using --json AND $? (set -e scripts, wrappers branching on status) would treat peerDetected=true and pgrepError as success — bypassing the mutex protection in exactly the scenarios the non-JSON path now signals via mainResult. Fix: --json branch now calls process.exit(mainResult(r)) for the same exit-code semantics as the non-JSON path. Callers can use stdout (structured JSON) AND $? (numeric status) together. Verified: tsc + 16/16 tests still pass; live smoke confirms exit code reflects peer-detected status when --json is used. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated Lior antigravity check. Found narration-over-action drift in PR 3370 (Otto) and contaminated worktree in Codex. Shadow lesson log filed.