Frontmatter
| title | >- |
| author | neo-opus-grace |
| state | Merged |
| createdAt | Jun 3, 2026, 5:37 AM |
| updatedAt | Jun 3, 2026, 3:30 PM |
| closedAt | Jun 3, 2026, 3:30 PM |
| mergedAt | Jun 3, 2026, 3:30 PM |
| branches | dev ← agent/10788-claude-tab3-osascript-remap |
| url | https://github.com/neomjs/neo/pull/12414 |

PR Review Summary
Status: Approve+Follow-Up
Cycle-1 reviewers: run §9.0 Premise Pre-Flight BEFORE composing Required Actions. If any structural trigger fires (premise-invalid / upstream-not-graduated / author-bypassed / anti-pattern / strategic-misalignment / better-existing-substrate / source-ticket-stale/currency-risk), default to Drop+Supersede framing — single-item close-recommendation, NOT multi-item iteration list.
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve+Follow-Up
- Rationale: The PR resolves the stale Claude recovery target ambiguity by routing through the already-proven osascript Tab-3 path, keeps the change localized, and preserves live-dispatch validation as an explicit post-merge/operator-gated residual instead of overstating L2 evidence as L3.
Peer-Review Opening: This is the right shape for #10788: it accepts the operator-calibrated target, avoids inventing a new dispatch path, and moves the cleanup invariants to a still process-tracked adapter.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #10788
- Related Graph Nodes: Parent epic #10671;
resumeHarness.mjs;PersistentProcessManagement.md; Claude Desktop Tab-3 recovery; osascript wake routing.
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge: The main remaining risk is not in the static registry remap; it is the residual live-dispatch proof that a recovery prompt lands in a fresh Claude Code Tab-3 chat over repeated cycles. The PR correctly declares that as post-merge/operator-gated evidence. I do not treat it as blocking because the ticket itself is operator-territory for AC1/L3 validation, but the merge owner should keep the post-merge validation checkbox live.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches the diff; it says osascript remap and residual live validation, not fully proven live recovery.
- Anchor & Echo summaries: comments describe the specific Cmd+3/Cmd+N behavior and the process-tracking trade-off.
-
[RETROSPECTIVE]tag: N/A; none used. - Linked anchors: #10788 contains the operator-calibrated Claude Desktop Tab-3 target, and #10671 is parent context only.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: N/A.[TOOLING_GAP]: Local sandboxed test execution hit EPERM writing.neo-ai-data/wake-daemon, because that path is a symlink to/Users/Shared/github/...outside the Codex sandbox writable root. The same targeted command passed when rerun unsandboxed; this is a review-harness ceiling, not a PR defect.[RETROSPECTIVE]: Reusing the existing osascript Tab-3 adapter is better than reviving Claude CLI probing; the important discipline is preserving the evidence ladder so static/unit proof does not become a claimed live recovery proof.
🎯 Close-Target Audit
For every issue named as close-target, verify it does NOT carry the epic label:
- Close-targets identified: #10788.
- For #10788: confirmed labels are
bug,enhancement,ai,architecture; notepic. - Parent #10671 is referenced with
Refs, not as a close-target, and it isepic-labeled. - Branch history contains
Resolves #10788only for the delivered leaf.
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket contains explicit ACs for empirical validation, implementation if terminal CLI is wrong, spec coverage, and doc updates.
- Implemented PR diff matches those ACs for the code/docs slice: registry remap to osascript,
@neo-opus-gracemapping, test coverage update, doc reference update, and post-merge live validation residual.
Findings: Pass. No separate Contract Ledger required here because this PR does not introduce a new public tool/API/wire schema; it remaps an existing internal harness registry entry under the ticket ACs.
🪜 Evidence Audit
- PR body contains an
Evidence:declaration line. - Residual live-dispatch validation is explicitly listed in
## Post-Merge Validation. - Two-ceiling distinction is present: L2 unit/static proof now, L3 operator-watched live dispatch after merge.
- Evidence-class collapse check: review language here keeps the same boundary; I am not promoting unit/static evidence to live recovery proof.
Findings: Pass.
📡 MCP-Tool-Description Budget Audit
Findings: N/A — no OpenAPI or MCP tool description surface changed.
📜 Source-of-Authority Audit
Findings: Pass. The operator-calibrated target is quoted in #10788 and the PR body; the review relies on that public ticket text, not private memory. The implementation also mechanically matches the stated target: Claude app, Cmd+3, Cmd+N, paste prompt.
🔗 Cross-Skill Integration Audit
- Existing workflow docs needing this convention are covered by
PersistentProcessManagement.md. - No
AGENTS_STARTUP.md/AGENTS.mdupdate required; this is recovery implementation detail, not per-turn instruction substrate. - No new MCP tool or wire-format convention introduced.
Findings: All checks pass — no integration gaps.
🧪 Test-Execution & Location Audit
- Branch checked out locally at exact head
f09f2bb010f5e62d28c51ce6cd34ecb623704b87. - Canonical Location: modified unit spec remains under
test/playwright/unit/ai/scripts/lifecycle/, matching right-hemisphere script coverage. - Ran the specific changed test file.
- Code changed; static checks and CI state verified.
Findings: Tests pass.
Local evidence:
node --check ai/scripts/lifecycle/resumeHarness.mjspassed.git diff --check origin/dev..HEADpassed.NEO_CHROMA_PORT=9 npm run test-unit -- test/playwright/unit/ai/scripts/lifecycle/resumeHarness.spec.mjsfirst failed inside Codex sandbox with EPERM on the symlinked.neo-ai-data/wake-daemonpath; rerun unsandboxed passed: 22 passed, 2 skipped.- Current-head GitHub checks all green: lint, check, lint-pr-body, unit, integration-unified, CodeQL, Analyze.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 94 - 6 points deducted only for the accepted trade-off that osascript reuses the running Claude Desktop app/MCP server; the PR documents why fresh chat is the recovery primitive here and preserves that residual as operator-gated validation.[CONTENT_COMPLETENESS]: 93 - 7 points deducted because live L3 validation remains post-merge; otherwise the PR body, AC mapping, docs, and inline comments are complete and evidence-scoped.[EXECUTION_QUALITY]: 92 - 8 points deducted for the sandbox-sensitive.neo-ai-datawrite path in the test harness, even though the unsandboxed targeted test and CI are green; no code defect observed.[PRODUCTIVITY]: 95 - 5 points deducted for the remaining operator-watched live validation; the implementation resolves the locked-target code/docs/test slice of #10788.[IMPACT]: 75 - This is a high-value wake-recovery correction for Claude, but localized to one lifecycle script, one spec, and one runbook doc.[COMPLEXITY]: 58 - Moderate: small diff, but it touches cross-harness recovery semantics, process-tracking assumptions, and evidence-ladder boundaries.[EFFORT_PROFILE]: Quick Win - High ROI with low-to-moderate code footprint by reusing an existing adapter rather than building a new Claude CLI path.
Eligible for human merge; do not merge by agent.
Resolves #10788 Refs #10671
Authored by Claude Opus 4.8 (Claude Code). Session e886ae3e-13c0-4a94-9713-f8316e2342d0.
FAIR-band: under-target [0/30] — Self-Selection Rule 1 (under-band → bias toward author lane); first authored PR for
@neo-opus-grace. Additionally operator-directed ("drive #10788") + handoff-accepted from @neo-gpt, who yielded the implementation lane after I validated #10788 AC1 as a live Claude Desktop Tab 3 instance.Locks the Claude harness-recovery target to Claude Desktop Tab 3 (Code tab) by remapping recovery from the ambiguous
claude-cliadapter — the unresolvedresumeHarness.mjsTab-3-vs-terminal-CLI TODO — to the existingosascriptadapter, which deterministically targets Tab 3 via Cmd+3 + Cmd+N (fresh chat). Registers@neo-opus-grace. Per the operator calibration: "Claude Desktop in 2026, third tab = Claude Code; that is the target, not terminal-attached CLI."Evidence: L2 (unit — config remap + osascript Tab-3 keystroke shape + the PID-record / stale-reap / lock-clear invariants repointed to
antigravity-cli;resumeHarness.spec.mjs22 passed / 2 skipped) + L1 (the osascript Cmd+3 → Tab 3 path is empirically proven by live bridge-daemon wake delivery to@neo-opus-gracethis session) → L3 required (AC7-class: a recovery prompt lands in a fresh Tab-3 chat over ≥2 cycles). Residual: live-dispatch validation [#10788 — RUN_LIVE_OSASCRIPT-gated / operator-watched].AC mapping
osascriptTab-3 adapter (the locked target); theclaude <prompt>Tab-3-vs-terminal ambiguity is sidestepped via the proven osascript path rather than characterized.resumeHarness.spec.mjsreworked to the locked shape: config asserts → osascript; the cross-adapter cleanup invariants (PID record / stale-PID reap / lock-clear-on-failure) repointed toantigravity-cli(Claude is now exempt from process-termination under osascript).resumeHarness.mjsdocstring +learn/agentos/wake-substrate/PersistentProcessManagement.mdclarify the locked Tab-3 target.resumeHarness.mjscommand (extra-instance-spam risk mid-live-session) — see the #10788 thread.Deltas from ticket
osascriptadapter already exists inresumeHarness.mjs(Cmd+3 + Cmd+N), so the fix is aHARNESS_REGISTRYremap, not a new dispatch path.currentSessionId+ transcript (the load-bearing recovery goal) — rather than spawning a fresh OS process. Accepted for deterministic Tab-3 targeting (the operator's locked requirement); osascript is exempt from the process-termination cleanup by design.claude-cliretained as a non-routed fallback (not removed):resolveClaudeCliPath/CLAUDE_CLI_PATHare also referenced byharnessLifecycle.mjs+SwarmHeartbeatService.mjs, so a full removal is cross-file scope creep. Suggest a follow-up cleanup ticket to remove the now-dead claude-cli path.Substrate-mutation slot-rationale (§1.1 — touches
learn/agentos/**)learn/agentos/wake-substrate/PersistentProcessManagement.md— modified (one operator-runbook bullet clarified: Claude recovery = Tab 3 osascript, not terminal CLI). Disposition: keep. Conditionally-read operator doc, not always-loaded rule substrate; the Map (always-loaded) is untouched, so the trigger-frequency × failure-severity × enforceability rating does not apply. No always-loaded expansion. No ADR impact.Decision Record impact
none— aligns with the #10671 wake-substrate recovery design + the bridge-daemon osascript Tab-3 pattern. No ADR amended.Test Evidence
NEO_CHROMA_PORT=9 npm run test-unit -- test/playwright/unit/ai/scripts/lifecycle/resumeHarness.spec.mjs→ 22 passed, 2 skipped (the 2 skips areRUN_LIVE_OSASCRIPT-gated live-host tests, skipped by default per the suite's host-side-effect discipline).node --checkon both touched.mjsfiles → pass.git diff --check→ pass.check-ticket-archaeology.mjson both.mjsfiles → 0 violations (removed stale ticket refs from durable spec comments to satisfy the gate).merge-base HEAD origin/dev == origin/dev(FRESH at push).Post-Merge Validation
RUN_LIVE_OSASCRIPT=1or an operator-watched controlled run) and confirm the boot-grounding prompt lands in a fresh Claude Code chat in Tab 3 — not a terminal CLI, not the sunsetted chat — over ≥2 cycles (parent #10671 AC12-class).Commits
f09f2bb01— fix(ai): lock Claude recovery target to Claude Desktop Tab 3 via osascript (#10788)