Skip to content

fix: harden handoff execution integrity - #130

Open
stanleyrprose wants to merge 9 commits into
rebel0789:mainfrom
stanleyrprose:fix/handoff-execution-integrity
Open

stanleyrprose wants to merge 9 commits into
rebel0789:mainfrom
stanleyrprose:fix/handoff-execution-integrity

Conversation

@stanleyrprose

@stanleyrprose stanleyrprose commented Sep 10, 2026 •

Copy link
Copy Markdown

Harden long/cross-agent handoff execution around two concrete failure modes observed in a real SignalForge run: stale in-flight receipts after executor termination and unintended remote Git/GitHub mutation before review.

What changes:

  • execute-handoff now publishes parent/child PIDs and records non-terminal interrupting while SIGINT/SIGTERM child termination is in progress; terminal interrupted is written only after the child has actually exited.
  • child termination no longer treats Node's child.killed flag as proof of process exit; stubborn children that ignore SIGTERM escalate to SIGKILL.
  • non-completed terminal runs explicitly separate process state from semantic side-effect outcome with execution_outcome=unknown and reconcile_required=true.
  • wait_for_handoff keeps reporting an in-flight state if the recorded child executor is still alive even when the parent is gone; only when both recorded parent and child are gone does it derive orphaned and require reconciliation.
  • orphaned receipts do not automatically reuse stale status/diff/log artifacts unless those artifact paths were explicitly recorded by that run.
  • local handoff executors default to a lightweight remote-mutation guard: standard git push/send-pack push paths and gh are blocked; common GitHub token env vars are not inherited. --allow-remote-mutations explicitly restores the previous behavior.
  • the remote-mutation guard is an accidental-side-effect guard, not a security sandbox; absolute alternate executables/direct network APIs are intentionally outside its guarantee.

Scope intentionally excluded: no persistent PTY/job management, workflow service, DB, queue, new MCP, npm release, or publish.

Verification on macOS from baseline 587f7fd3a4644a847bba13aeb49336056052e1f6, final head 77b56d4512a5aa8cc081db67aa7cb94ce140f0da:

  • npm ci — success (registry currently reports 2 moderate + 1 high dependency advisories; not introduced by this change)
  • npm run build — PASS
  • node scripts/execute-handoff-smoke.mjs — PASS
  • node scripts/smoke.mjs — PASS
  • npm run smoke — PASS
  • npm run stress — PASS
  • git diff --check — PASS

New regression coverage includes:

  • default git push blocked and explicit opt-in allowed against a local bare remote;
  • SIGTERM first produces non-terminal interrupting, then terminal interrupted only after a stubborn child is actually terminated;
  • dead parent + live child remains in-flight;
  • dead parent + dead child is surfaced as orphaned and reconciliation-required;
  • orphaned stale receipts do not expose prior-run artifacts.

@stanleyrprose

Copy link
Copy Markdown
Author

Implementation/review update for exact head 77b56d4512a5aa8cc081db67aa7cb94ce140f0da:

  • Spec Fidelity: PASS
  • Engineering Standards: PASS after two review fixes: (1) live child executor is never derived as orphaned merely because the parent is gone; (2) SIGINT/SIGTERM now uses non-terminal interrupting until the child actually exits, with stubborn-child SIGKILL escalation based on actual exit/signal state rather than Node's child.killed flag.
  • Local verification: npm run build, targeted execute-handoff smoke, MCP smoke, full npm run smoke, npm run stress, and git diff --check all PASS.
  • GitHub currently reports 0 check runs for both this upstream fork PR and a CI-only mirror PR in the fork, despite the repository workflow declaring pull_request; CI therefore appears not to have started/been approved yet. No upstream merge or npm publish is being requested automatically.

@stanleyrprose

Copy link
Copy Markdown
Author

Cross-platform CI update for exact head 77b56d4512a5aa8cc081db67aa7cb94ce140f0da:

A CI-only mirror PR in the fork was used because upstream fork checks remained unstarted. After re-registering the fork's existing CI workflow (no code/workflow-content change), run 34510223428 completed successfully on both matrix targets:

  • Ubuntu: PASS — Install, Build, Smoke Test, Stress Test, Check Package Contents
  • Windows: PASS — Install, Build, Smoke Test, Stress Test, Check Package Contents

The CI-only fork PR has now been closed without merge. Upstream PR #130 remains the canonical integration PR; no upstream merge or npm publish was performed.

stanleyrprose and others added 7 commits September 22, 2026 07:48
Add a read-only resolved revision, branch, dirty-state, and stable workspace fingerprint projection without changing permissions or execution behavior.
Bind generated handoff plans to plan hash, Git revision, stable workspace identity, and non-.ai-bridge worktree state. Reject stale baselines before launching the local agent and expose reconcile-required evidence without changing legacy handoffs or bounded loop semantics.
fix: preserve workspace ids across rotated MCP sessions
fix: make workspace handles restart-stable

This branch has not been deployed

No deployments
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