Skip to content

feat(harness): add managed Agent SDK feasibility probe - #649

Draft
ynadge wants to merge 24 commits into
mainfrom
yashnadge/sap-2632-harnesse04-prove-local-tools-mcp-cancellation-and-recovery
Draft

feat(harness): add managed Agent SDK feasibility probe#649
ynadge wants to merge 24 commits into
mainfrom
yashnadge/sap-2632-harnesse04-prove-local-tools-mcp-cancellation-and-recovery

Conversation

@ynadge

@ynadge ynadge commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add the explicitly experimental @sapiom/harness/experimental/managed-agent-spike programmatic Agent SDK runtime without changing Harness PTY, session, server, or UI contracts.
  • Pin Agent SDK 0.3.228, Claude Code runtime 2.1.228, the exact two eval-only model aliases, the direct Sapiom gateway origin, isolated SDK configuration, and a positive child-environment allowlist that excludes ambient Claude/Sapiom credentials.
  • Gate every model-requested Read, Edit, Write, Bash, and in-process MCP call through a matcherless PreToolUse hook. Use canonical containment, exact Bash equality, an MCP allowlist, bounded cancellation, and content-free structural evidence. Never use bypass permissions.
  • Provide disposable git fixtures, dirty/untracked preservation checks, exact workspace evidence, real pinned-SDK loopback coverage, process-tree cancellation/cleanup, and an opt-in live L1/L2 CLI.

L1 certification contract v2

Commit 64748b8 replaced the diagnostic exact-trace-v1 gate with an independently versioned, fail-closed L1 contract:

  • Freeze managed-agent-l1-prompt-v2 and managed-agent-l1-evaluator-v2 while retaining result-envelope contract version 1.
  • Require all 11 canonical operations exactly once and preserve their exact request order.
  • Permit at most one optional verification Read, only after both denial probes and before Edit, and only for the clean target, dirty sentinel, or untracked sentinel.
  • Assign privacy-safe operation IDs at the trusted permission boundary. Path roles use normalized lexical identity before realpath containment, so SDK-normalized absolute paths retain their registered role while every other in-workspace path remains denied.
  • Require each non-empty unique request ID to have exactly one matching completion and one primary PreToolUse decision with the same tool and coherent decision, reason, operation ID, and outcome. Reject fallback evidence, duplicates, orphans, omissions, retries, and every other extra operation.
  • Require the exact two-path workspace delta, in either evidence order; exact final bytes for the clean target and managed output via trusted hashes; byte-identical dirty/untracked sentinels; successful nonce proof; terminal success; query close; and process quiescence. Durable final-byte evidence contains only { role, matched }.
  • Report optional Read count/role as nonblocking efficiency evidence.

Review remediation: semantic completion order

Commit 8cf5874 closes a false-pass found by independent review. The previous evaluator proved request order and one completion per request but could accept [all requests][all completions] with one claimed inference turn.

The evaluator now enforces the protocol's partial order while preserving valid SDK batching:

  • Every request precedes its own unique completion.
  • The five discovery calls may batch and their completions may permute, but all must complete before the optional verification Read, or before Edit when no optional Read occurs.
  • An optional Read must complete before Edit.
  • Edit, Write, echo_nonce, and the first fail_once call may batch and complete in any order, but all must complete before the recovery retry.
  • The first successful fail_once retry must complete before Bash is requested, and Bash must complete.
  • Distinct assistant inference turns must be at least 4 + optionalReadCount.
  • Normalized tool and permission events must exactly project their evidence arrays, and successful Bash completion must precede the single successful SDK result and final successful terminal event.

Regression tests accept maximally batched valid traces with no optional Read and with each permitted optional role. They reject the original all-requests-first counterexample, every completion-before-own-request position, every phase barrier delayed on either optional branch, insufficient inference turns, event/evidence mismatches, and invalid Bash/result/terminal ordering. L2 evaluation is unchanged.

Commit e38ae7a closes a second cross-stream false-pass found by independent re-review. The prior check compared the tool and permission event substreams independently, so it could accept a primary permission event moved after that tool's completion while both substream projections remained intact. The evaluator now maps each exact permission event's chronological index to its matching completion and requires permission < completion for every tool-use ID. It deliberately does not constrain permission relative to the request event: both hook-before-yield and yield-before-hook observation orders pass when authorization still precedes completion.

The added regressions move each of all 11 canonical primary permission events, plus the optional Read permission, after its own completion while preserving both substream projections. Both valid permission/request orderings remain accepted.

Hermetic verification through e38ae7a

All commands used Node 22.23.2 and made no live gateway/model call:

  • chronology red proof at 64748b8: 31 expected failures while all four valid maximally batched traces passed
  • cross-stream red proof at 8cf5874: exactly 12 expected failures for all 11 canonical permissions plus the optional Read; both valid permission/request orderings passed
  • focused evaluator suite at e38ae7a: 116/116 tests passed
  • managed-agent suite at e38ae7a: 10/10 files, 187/187 tests passed, including 2/2 real bundled-SDK loopback tests
  • full Harness unit suite at 8cf5874: 151/151 files, 2,271/2,271 tests passed
  • Harness performance suite at 8cf5874: 4/4 tests passed
  • pnpm --filter @sapiom/harness typecheck: passed
  • pnpm --filter @sapiom/harness build: passed
  • pnpm --filter @sapiom/harness lint: 0 errors; one pre-existing unrelated warning in src/server/rest.test.ts
  • Prettier, git diff --check, and diff-scoped gitleaks scan: passed

Exact-trace-v1 diagnostic and stopped live campaign

The independently reviewed v1 campaign produced:

  • Sonnet 5 L1 repetition 1: pass
  • Sonnet 5 L1 repetition 2: pass
  • MiniMax M3 L1 repetition 1: pass
  • MiniMax M3 L1 repetition 2: successful terminal result, exact model provenance, complete primary permission coverage, clean teardown, and intended workspace behavior, but one extra allowed in-root verification Read

The exact-trace-v1 evaluator correctly rejected the fourth run because it allowed no extra call. The campaign stopped immediately. No L2 run occurred. Those runs remain diagnostic history and do not count toward the v2 acceptance repetitions.

No new live or paid call was made while designing, implementing, or verifying v2 or either chronology remediation.

Certification-v2 live campaign — stopped on L2

After independent review, fully green CI at exact head e38ae7a1278814c62ae9060c2f4c4f07cdc06e98, and explicit START authorization, the v2 matrix ran once in its fixed order. The four required L1 repetitions all passed:

  • Sonnet 5 L1 repetitions 1 and 2: 42/42 checks, 21 gateway rows for 21 inference turns
  • MiniMax M3 L1 repetitions 1 and 2: 42/42 checks, 14 gateway rows for 14 inference turns
  • Combined: 84/84 checks, 35 gateway rows for 35 inference turns, fallback_fired=false throughout, $0.09485632, 227,758 prompt tokens, 4,571 completion tokens, and 232,329 total tokens
  • Every passing run used contract v2, reported zero optional Reads, preserved the dirty/untracked sentinels, ended successfully, met its teardown deadline, and had no wrapper-detected survivor

The fifth attempt, Sonnet 5 L2 repetition 1, failed and stopped the campaign. The SDK requested the exact allowed Bash tool and the policy hook allowed it, but the query ended as query_error / iteration_aborted before a tool completion, cancellation request, or SDK result was observed. The inner probe reported quiescent teardown in 63 ms, but the independent outer supervisor found a newly orphaned three-process fixture group after its ten-second survivor deadline. The exact group was isolated, frozen, killed, and confirmed absent. This is a real containment/cancellation gate failure, not a passing L2 result.

Per the pre-authorized stop rules, there was no retry, no gateway provenance reconciliation for the failed attempt, and no MiniMax M3 L2 attempt. Restricted evidence remains outside git in a mode-0600 campaign bundle; a fresh redacted scan found no credential leaks.

Scope boundaries

This remains a non-UI feasibility subpath. It does not alter HarnessAdapter, SessionManager, TaskManager, REST, WebSockets, desktop boot, or existing Claude Code/Codex PTY flows. It does not add the Assistant/Builder parent-child runtime, persistence, checkpoints, packaging certification, model picker, billing, or UI.

Why this PR remains draft

The v2 campaign proves L1 for both target models, but SAP-2632 is not complete because the first Sonnet L2 attempt failed the independent no-survivor gate and MiniMax M3 L2 was intentionally left unexecuted. The PR remains draft and the campaign remains stopped. Any remediation and any new paid run require a separately reviewed change and fresh explicit authorization; no existing result may be reclassified or retried silently.

Related

SAP-2632

Certification v4 follow-up: Bash input compatibility

The next authorized certification campaign stopped on its first paid attempt, Sonnet 5 L1 repetition 1, at head 6a0ae05fcbc289dc9ae51fae55421b678aeed21c. The model completed every other required L1 operation, but its final Bash request was denied as invalid_input / bash:unregistered. The pinned Agent SDK permits optional Bash fields such as description, while the host policy accepted only an exact one-key { command } object. Raw input values were intentionally not retained, so the exact optional field remains an inference; the schema/policy mismatch and denial reason are proven.

Current head 830811cc97386f83b0d95fd3ec6fa965e11df8b7 fixes that mismatch without broadening shell authority:

  • Accept only the five fields declared by pinned Agent SDK 0.3.228: command, timeout, description, run_in_background, and dangerouslyDisableSandbox.
  • Preserve byte-exact command allowlist membership.
  • Validate every supplied field and reject unknown fields, malformed values, run_in_background: true, and dangerouslyDisableSandbox: true.
  • Canonicalize every allowed call to { command }, stripping all optional fields before execution.
  • Use the same normalizer for operation classification and policy evaluation.
  • Cover the primary hook, canUseTool fallback, L2 boundary, content-free evidence, and the pinned real-SDK loopback path.

Fresh verification used certification Node 22.23.2 and made no live gateway, paid model, or BigQuery call:

  • Harness unit/integration suite: 151/151 files passed; 2,350 tests passed; 1 platform-conditional skip.
  • Harness performance suite: 4/4 tests passed.
  • Typecheck and production build passed.
  • ESLint reported 0 errors and one pre-existing unrelated warning in src/server/rest.test.ts.
  • Prettier, git diff --check, and diff-scoped gitleaks passed.
  • Red/green proof temporarily restored description rejection and produced four focused failures, including the real-SDK loopback; restoring the fix returned the focused suite to green.

The PR remains draft. This patch is locally and hermetically verified, but no live certification result has been reclassified and no campaign has been rerun. Any new paid campaign must use a newly frozen exact-head bundle, independent review, and fresh explicit authorization; the authorization bound to 6a0ae05f… cannot authorize 830811cc….

ynadge added 5 commits August 16, 2026 15:19
Add an isolated experimental Agent SDK runtime with exact-model pinning, fail-closed local permissions, deterministic MCP probes, bounded cancellation, and disposable workspace evidence.

Closes: SAP-2632
Ensure an L1 result cannot pass when a built-in tool was requested but failed.

Refs: SAP-2632
Use fresh canonical config roots, normalize attacker-controlled evidence, execute canonicalized file targets, and require complete permission evidence for L1 qualification.\n\nRefs: SAP-2632
Replace the incomplete canUseTool-only boundary with a universal PreToolUse policy, fail closed on managed hook settings, and add hermetic SDK loopback coverage plus durable correlation and inference-turn evidence.\n\nRefs: SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Resolved the three blocking review findings in commit 6af3cf6:

  • promptEmbedded now remains false when settings preflight or query construction prevents a query, and becomes true only after the query factory accepts the marked prompt
  • PreToolUse now rejects missing, empty, whitespace-only, mismatched, and overlong tool-use IDs before policy evaluation; invalid IDs cannot become normalized evidence or satisfy policy coverage; concurrent duplicate primary IDs remain fail-closed
  • the pinned 0.3.228 SDK loopback now performs a native in-process echo_nonce MCP turn and proves the primary hook decision, handler execution, exact successful result replay, and SDK completion event

Hermetic verification under Node 22.23.2:

  • managed-agent spike: 10 files, 52 tests passed
  • full Harness unit suite: 151 files, 2,147 tests passed
  • Harness perf suite: 4 tests passed
  • typecheck, build, Prettier, and git diff check passed
  • lint passed with one pre-existing warning in src/server/rest.test.ts

No live model or paid gateway calls were made. The PR remains draft and is ready for re-review.

@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Resolved the remaining prompt-handoff review finding in commit 043b30e. promptEmbedded now flips immediately before queryFactory invocation, so it is true when the factory receives the marked prompt even if that factory throws; it remains false when settings preflight skips the factory entirely. The type documentation, README, and both regressions now use the same handed-to/received-by semantics.

Node 22.23.2 verification: managed-agent suite 52/52 passed, Harness typecheck passed, Prettier passed, and git diff check passed. No live or paid calls were made. Ready for re-review; PR remains draft.

@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

SAP-2632 remediation is pushed in b9d3e77.\n\nWhat changed:\n- Added content-free policy diagnostics that distinguish PreToolUse guard rejection reasons from a genuinely missing hook callback. Diagnostics cannot satisfy strict policy coverage and expose no raw IDs or tool inputs.\n- Added termination evidence preserving the underlying query/construction/iteration/abort/event-normalization outcome and whether an SDK result was observed before any policy_violation override.\n- Tightened the deterministic L1 prompt to exact paths, exact Edit arguments, exact call counts/order, explicit error continuation, and no substitutions/retries/extra paths.\n- Added a real pinned @anthropic-ai/claude-agent-sdk 0.3.228 + Node 22.23.2 localhost fake-gateway regression. It confirms SDK schema prevalidation can reject a malformed Edit before PreToolUse, while the paired tool error remains visible and strict coverage still fails. A separate valid Edit control reaches PreToolUse and succeeds.\n- Added focused tests for prompt determinism, guard paths, diagnostic privacy, termination evidence, and unchanged strict coverage.\n\nHermetic verification under exact Node 22.23.2:\n- focused managed-agent spike: 57/57\n- full Harness unit suite: 2,152/2,152\n- Harness perf: 4/4\n- typecheck, build, Prettier, git diff check, and scoped secret scan: pass\n- lint: 0 errors; one pre-existing unrelated unused-import warning in packages/harness/src/server/rest.test.ts\n\nNo live model/gateway calls or paid retries were made. The paid certification campaign remains stopped pending independent review.

Require exact L1 and Bash-only L2 evidence, derive cancellation targets only from the SDK process tree, and preserve the existing Zod v3 REST error contract while the Agent SDK uses Zod v4.\n\nRefs: SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Review remediations are implemented in 1773264e56f7209ba6b7798a57e6e12ed9ee74f9.

  • L1 certification now requires exactly 11 ordered requests, 11 unique request IDs, and exactly one matching completion plus primary permission decision per ID. Omitted, reordered, extra, duplicate, and incorrect fail-once outcomes are regression-tested.
  • L2 exposes Bash only. Read/Edit/Write and MCP are unavailable, and the policy boundary independently denies any non-Bash attempt.
  • Model-writable processes.json PIDs are evidence only. Cleanup targets are derived exclusively from SDK-spawned roots and kernel-observed descendants/process groups, with creation-time identity checks to reject PID reuse. Normal teardown and forged current/unrelated PID cases are covered.
  • The public REST validation contract stays on zod/v3; the Agent SDK runtime keeps root Zod 4. Exact response bodies are covered for all seven affected serializers.

Verification with Node 22.23.2:

  • focused managed-agent suite: 65/65
  • full Harness unit suite: 2,162/2,162
  • Harness performance suite: 4/4
  • typecheck: pass
  • build: pass
  • lint: 0 errors (one pre-existing unused-import warning)
  • git diff --check, credential-pattern scan, and experimental Prettier check: pass

One full-suite attempt hit the existing macOS temp-directory cleanup race in workspace-rescan.test.ts (ENOTEMPTY); its isolated retry and the subsequent complete suite both passed.

No live gateway/model calls or paid retries were run. The certification campaign remains stopped.

Certify only the reviewed detached POSIX fixture group, bind raw abort to immediate STOP/KILL, fail closed on unknown containment, and keep iterator close and confirmation inside one deadline.\n\nRefs: SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Second process-safety remediation pushed in 94a2fc925c74c73483fb92b4e8c1a4d9faeccc4d.

What changed:

  • Narrowed L2 certification to the reviewed macOS/Linux model: one observer-created detached POSIX process group for the exact non-cooperative fixture. Windows is rejected before query or credential access.
  • Added bounded process-table reads and explicit unavailable/unknown/signal-failure evidence. Readiness requires the active trusted SDK root to be the PGID leader; fixture-file PIDs are comparison-only and never signal authority.
  • Bound the raw per-run abort signal directly to synchronous, idempotent SIGSTOPSIGKILL for the owned group. Iterator abandonment, bounded query close, and group-death confirmation share one absolute five-second process-termination deadline.
  • Added adversarial coverage for hanging enumeration, fast root exit, observed group escape, failed kill retry, unknown liveness, Windows preflight, forged workspace PIDs, and a never-resolving iterator/async close.
  • Strengthened the real non-cooperative test with a live unrelated sibling that must remain alive. Its finally retains the exact test-owned PGID and independently issues SIGKILL plus a bounded group/root death check, so failed assertions cannot orphan the fixture group.
  • Corrected the documentation boundary: workspace snapshots/result assembly happen after the five-second process-termination deadline.

Hermetic verification under Node 22.23.2:

  • Experimental managed-agent suite: 10 files, 76/76 tests passed (including 2/2 real pinned-SDK loopback tests).
  • Full Harness suite: 151 files, 2173/2173 tests passed.
  • Performance suite: 1 file, 4/4 tests passed.
  • pnpm --filter @sapiom/harness typecheck: passed.
  • pnpm --filter @sapiom/harness build: passed.
  • pnpm --filter @sapiom/harness lint: 0 errors; one pre-existing unrelated warning in src/server/rest.test.ts.
  • Prettier, git diff --check, and credential scan: passed.
  • Process-table scan before verification, after the experimental suite, and after the full suite: zero matching long-running managed-agent fixture processes.

No live gateway, paid-model, or credential-bearing calls were run.

Keep the cancellation deadline referenced and launch POSIX SDK commands through an observer-owned supervisor so fast inner-root exits cannot orphan same-group descendants.\n\nRefs: SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Final safety-review remediation pushed in 8b357e58a40c8d5832a99c934dff80b08f83c1cb.

Resolved blockers:

  1. Referenced close deadline

    • Removed unref() from the bounded query-close deadline.
    • Added a real CLI-shaped child-process regression whose iterator and close() never resolve. The child now remains alive through the ~2s close deadline, runs emergency cleanup, emits its result, and exits normally instead of disappearing with unsettled top-level await.
  2. Persistent POSIX process authority

    • macOS/Linux SDK commands now run beneath an observer-owned detached Node supervisor that remains the PGID leader.
    • The inner command and all descendants inherit the supervisor group. If the inner SDK root exits while a same-group descendant survives, the supervisor stays alive and retains safe group authority.
    • Command/args travel in a private inherited environment payload, not supervisor argv; the supervisor deletes that payload before launching the inner command.
    • stdin/stdout/stderr are proxied, stderr is drained without retention, and a regression verifies all 1 MiB is forwarded while exact nonzero exit code and null signal are preserved.
    • Direct SDK kill(signal) targets the owned group. Parent IPC disconnect also kills the complete group.
    • The supervisor's bounded ps helper remains inside the owned group. Only the known helper PID and anchor PID are excluded from the membership decision; timeout directly kills the helper as defense in depth.
    • Intentional supervisor self-disconnect removes the parent-loss handler first, so normal completion cannot self-SIGKILL.

Adversarial evidence:

  • Inner SDK root exits before readiness, leaving a non-cooperative child: anchored cleanup succeeds.
  • Inner SDK root exits after readiness, leaving a non-cooperative child: anchored cleanup succeeds.
  • Parent IPC disconnect with a live non-cooperative inner/child group: complete owned PGID dies.
  • In every real containment case, a live unrelated sibling survives.
  • Every real process test retains an independent exact-PGID fallback with bounded death confirmation, so failing assertions cannot leak fixtures.
  • Workspace PID-file values and second-resolution lstart remain evidence-only and never signal authority.
  • Windows L2 remains rejected.

Hermetic verification under Node 22.23.2:

  • Experimental managed-agent matrix: 82/82 passed, including pinned real-SDK loopback 2/2.
  • Full Harness unit suite: 151 files, 2179/2179 passed.
  • Performance suite: 1 file, 4/4 passed.
  • Typecheck: passed.
  • Production build: passed.
  • Lint: 0 errors; one pre-existing unrelated warning in src/server/rest.test.ts.
  • Prettier, git diff --check, and credential scan: passed.
  • Process scans before/after focused, experimental, and full verification: zero matching managed-agent fixture processes.

Two unrelated full-suite timing flakes appeared on earlier attempts (rehydrate-session and generated-retention); each passed immediately in isolation, and the final unmodified full command passed completely.

No live gateway, paid-model, or credential-bearing calls were run.

ynadge added 2 commits August 16, 2026 21:39
Make the L1 gate fail closed on the frozen v2 prompt, exact correlated operation trace, exact workspace and final-byte evidence, and the one bounded verification Read exception. Preserve content-free permission evidence and SDK-normalized path handling.

Refs: SAP-2632
Reject traces that preserve request order but violate the semantic completion barriers needed to prove multi-turn tool recovery. Keep valid SDK batching by allowing completion permutations within each phase.

Refs: SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Independent-review remediation pushed in 8cf5874. The L1 evaluator now enforces request-before-completion, both phase barriers, optional-Read completion ordering, fail-once recovery ordering, inferenceTurns >= 4 + optionalReadCount, normalized event/evidence consistency, and Bash completion before the successful SDK result and terminal event—while accepting maximally batched valid traces. Red proof at 64748b8: 31 expected counterexample failures; final focused suite 103/103. Fresh hermetic verification: managed-agent 174/174 (including 2/2 real bundled-SDK loopbacks), full Harness 2,271/2,271 plus perf 4/4, typecheck/build/format/diff/gitleaks pass, lint 0 errors with one unrelated pre-existing warning. No live or paid calls. PR remains draft pending CI and independent re-review.

Correlate each normalized primary permission event with its matching tool completion so separately valid substreams cannot conceal post-execution authorization evidence. Preserve both observed SDK permission/request orderings.

Refs: SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Second independent-review blocker fixed in e38ae7a. The normalized-event gate now correlates each primary permission event's chronological index with its matching tool completion and requires permission < completion for every tool-use ID. It intentionally permits both permission-before-request and request-before-permission SDK observation orders. Red proof at 8cf5874: exactly 12 failures covering all 11 canonical permissions plus the optional Read, with both valid orderings passing. Fresh green verification: focused 116/116; managed-agent 187/187 across 10 files including 2/2 real SDK loopbacks; typecheck/build/format/diff/gitleaks pass; lint 0 errors with one unrelated pre-existing warning. No live or paid calls; PR remains draft.

@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Certification-v2 live campaign result at exact head e38ae7a1278814c62ae9060c2f4c4f07cdc06e98: stopped on Sonnet L2; PR remains draft.

Passing L1 evidence:

  • Sonnet 5: 2/2 required repetitions, 42/42 checks, 21 inference turns = 21 authoritative gateway rows
  • MiniMax M3: 2/2 required repetitions, 42/42 checks, 14 inference turns = 14 authoritative gateway rows
  • Combined: 84/84 checks, 35 turns = 35 rows, exact selected aliases/upstreams, fallback_fired=false throughout
  • Aggregate served usage: $0.09485632; 227,758 prompt + 4,571 completion = 232,329 total tokens
  • Each passing run used contract/prompt/evaluator v2, used zero optional Reads, preserved dirty/untracked sentinels, met its teardown deadline, and had no wrapper-detected survivor

Blocking L2 result:

  • Fixed-order attempt 5/6, Sonnet 5 L2 cleanup HTTP SDKs #1, failed before cancellation: exact Bash was requested and allowed, then the query terminated as query_error / iteration_aborted without tool completion, cancellation request, or SDK result.
  • The inner probe reported quiescent cleanup in 63 ms, but the independent outer 10-second survivor gate found one newly orphaned fixture-group root with two children.
  • Cleanup targeted only that exact isolated group; all three processes were confirmed absent afterward.
  • The campaign stopped immediately. There was no retry, no failed-attempt BQ reconciliation, and no MiniMax M3 L2 run.

This means SAP-2632 currently satisfies L1 for both models but does not satisfy L2's safe-cancellation/no-orphan acceptance criterion. The campaign remains stopped. Any fix and any further paid run require a separately reviewed change and fresh explicit authorization.

Restricted artifacts remain outside git with mode 0600; a fresh redacted gitleaks scan passed.

Let the Agent SDK complete its bounded graceful shutdown before host fallback cleanup. Add a private authenticated registration path for the exact E0.4 L2 fixture so detached tool groups remain containable across early query failures and late registration.

Refs: SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

L2 orphan-process remediation is pushed in 04ef14130eaca095fb64ea1f3cb48dfea827a291.

Root cause and fix:

  • The runtime had bound the raw Options.abortController directly to host SIGSTOP/SIGKILL, preempting the Agent SDK documented graceful shutdown and leaving the CLI detached Bash PGID outside the observer single-PGID boundary.
  • Query failure now aborts the SDK first and runs bounded query.close() before host fallback. The observer binds only the SDK-forwarded post-grace SpawnOptions.signal.
  • The exact host-created E0.4 L2 fixture now authenticates over a private one-shot Unix socket outside the workspace using a random per-run capability. Its live PID/PGID is validated from the host kernel table before fallback signal authority is granted.
  • Exact Bash PreToolUse arms this scope. An armed but unregistered scope can never report quiescence. Registration that arrives after query cleanup and after the SDK PGID has exited is still contained immediately with SIGSTOP then SIGKILL.
  • This is intentionally fixture-only feasibility containment, not a claim of universal built-in Bash containment. Workspace PID-file values remain comparison-only and never become signal targets.
  • The vacuous empty-PID no-survivor check is closed.

Hermetic Node 22.23.2 verification with no live gateway/model/BQ calls:

  • focused changed suites: 157/157
  • full Harness unit suite: 2,288/2,288
  • Harness performance suite: 4/4
  • real pinned-SDK L2 loopback: normal cancellation and readiness-failure/iteration-abort both pass with no fixture survivor; an unrelated process remains alive
  • late-registration real-process regression passes after the SDK group exits first
  • typecheck, production build, Prettier, diff check, and diff-scoped gitleaks: pass
  • lint: 0 errors; one pre-existing unrelated warning in src/server/rest.test.ts
  • independent post-suite process scans: zero managed-agent/supervisor survivors

The PR remains draft and the paid campaign remains stopped. This code requires CI and independent review before any separately authorized live L2 rerun; no prior failed result is reclassified.

ynadge added 6 commits August 17, 2026 01:23
Require fresh kernel-backed ancestry and lifetime evidence before signaling the exact L2 fixture group. Preserve one absolute deadline across readiness, SDK shutdown, and host cleanup while failing closed on incomplete observation.

Refs: SAP-2632
Broadcast tool self-termination over every authenticated live channel and make the supervisor handle IPC that disconnected before bootstrap.

Refs SAP-2632
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Final process-safety review remediation is pushed in 6865e3a0d4d8879bff9962ba40b8bf944ab65a13.

What changed:

  • Removed host-side numeric PID/PGID destructive signaling. The observer now requests termination only over retained process-bound channels; the authenticated receiver terminates its own current group.
  • Restored the Agent SDK native ChildProcess.kill() contract; the supervisor remains the group anchor without a logical kill shim.
  • Tool termination is broadcast to every authenticated live role, so a stale parent endpoint cannot suppress a usable child channel.
  • Closed the supervisor bootstrap disconnect race by registering the disconnect handler first and synchronously handling an already-disconnected IPC channel.
  • Removed raw PID/PGID cleanup from the affected tests and runtime loopback fixtures.
  • Added deterministic regressions for stale-parent/live-child delivery and IPC disconnected before supervisor listener installation.

Fresh exact-Node 22.23.2 verification at this SHA:

  • managed-agent suite: 10 files, 250 passed / 1 intentional platform skip
  • full Harness suite: 151 files, 2,347 passed / 1 intentional platform skip
  • Harness perf: 4/4
  • typecheck, production build, Prettier, git diff --check, and scoped gitleaks: pass
  • lint: 0 errors; one pre-existing unrelated warning in src/server/rest.test.ts
  • final process scan: no managed-agent fixture or supervisor survivors

Two independent exact-SHA reviews approved this commit for CI/live certification with P0=0, P1=0, P2=0. No live gateway/model calls were made. The PR remains draft pending fully green CI and a fresh fixed-order L1/L2 campaign with gateway reconciliation.

@github-actions github-actions Bot added contribution: incomplete Required pull request information is incomplete or ambiguous contributor: external Pull request author does not have write, maintain, or admin access to sapiom-js review: manual External pull request requires maintainer review before automation review: sensitive Changes affect sensitive repository or release infrastructure size: xlarge Review size exceeds 1,000 changed lines area: studio Changes to Agent Studio or harness applications area: ci-release Changes to CI, repository automation, or releases labels Aug 17, 2026
@ynadge

ynadge commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up process-channel remediation is pushed at exact head 6a0ae05fcbc289dc9ae51fae55421b678aeed21c.

What changed:

  • Both generated fixture roles now arm independent monotonic five-second registration deadlines.
  • Each connection attempt rechecks the deadline, and an ACK received at or after the deadline terminates the receiver-owned process group instead of authenticating it.
  • Closing or losing an authenticated lifetime channel remains receiver-side fail-closed via process.kill(0, "SIGKILL"); the host never issues a destructive numeric PID/PGID signal.
  • Added a real detached parent/child regression for an accepted-but-silent controller. Both processes are observed alive, then self-terminate within the bounded window while an unrelated process survives.
  • Added explicit coverage for late connection/late ACK paths and retained-channel loss.

Two independent exact-SHA reviews approved with P0=0, P1=0, P2=0.

Fresh Node 22.23.2 verification:

  • focused safety matrix: 70/70
  • managed-agent feature: 252 passed / 1 intentional exact-pin skip
  • full Harness: 151 files, 2,349 passed / 1 intentional skip
  • performance: 4/4
  • typecheck, production build, Prettier, git diff --check, and gitleaks: pass
  • lint: 0 errors; one unrelated pre-existing warning in src/server/rest.test.ts
  • final process scan: zero fixture/supervisor survivors

No live gateway/model calls were made. The PR remains draft while CI and a fresh exact-SHA fixed-order L1/L2 campaign complete.

@ynadge

ynadge commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

SAP-2632 v4 live campaign result

The exact-head campaign for commit 6a0ae05 executed under explicit authorization with a strict no-retry, stop-on-first-failure policy.

Result

  • Attempt: sonnet-5 / L1 / 1
  • Outcome: local acceptance failed
  • Campaign state: stopped
  • Attempts 2–6: unexecuted by policy
  • BigQuery reconciliation: not run, because a failing local probe is ineligible for provenance promotion
  • SDK-reported estimated cost (non-authoritative): $0.07375635
  • Inference turns observed by SDK: 8
  • SDK turns: 12

Failed checks:

  • exact_l1_tool_trace
  • bash_sdk_terminal_order
  • builtin_tools_succeeded
  • expected_permissions_allowed

The preceding Read/Edit/Write operations, expected outside/symlink denials, MCP nonce echo, planned MCP failure/recovery, exact workspace delta, dirty/untracked preservation, query close, and terminal completion all succeeded. The final Bash request was denied by the host policy as reason invalid_input with operation bash:unregistered, so the Bash completion was an error instead of the required success.

Safety evidence

  • No probe timeout or capture overflow
  • Process-bound termination requested
  • Zero survivors at the deadline
  • Immutable execution snapshot revalidated
  • Both canonical temp roots clean before and after
  • No campaign lock remains
  • Credential exact scan and gitleaks scan found zero artifact leaks
  • Model alias was observed by SDK as claude-sonnet-5-anthropic-anthropic-eval, but remains non-authoritative because BigQuery reconciliation was correctly withheld

Evidence hashes:

  • probe report: 5e282aa1a2660efcb1834688848fc76caaa5062905b0e6584275490f5546516b
  • failure record: 6c1617754debe2617010f9e5e9a93eb27e693b3d02c94145cfa0ca6eac319bd1
  • campaign stop: a41ce0933bc2534cb5c302bfe64550d20b110a2538346a550aa00c32663f31e5

This is a valid no-go result for the frozen campaign, not a flaky pass candidate. The next engineering step is to determine the real SDK Bash input shape that reached the permission boundary, add a hermetic regression for it, and prepare a newly reviewed exact-head campaign if the implementation changes.

@ynadge

ynadge commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up diagnosis: Bash schema mismatch

The pinned Agent SDK 0.3.228 declares BashInput with required command plus optional timeout, description, run_in_background, and dangerouslyDisableSandbox fields. Its description field documentation explicitly tells the model to provide a concise description, including for simple git commands.

The current permission boundary requires the raw Bash input to have exactly one key: command. The live evidence recorded invalid_input and bash:unregistered for the final Bash request. Because the evidence contract intentionally discards raw tool inputs, it cannot prove which optional field was present; however, the failure is consistent with a valid model-facing SDK Bash shape being rejected by the stricter host shape.

A safe repair should not simply allow arbitrary extras. Recommended boundary:

  1. Require the exact allowlisted command string.
  2. Accept only the pinned SDK's declared Bash keys.
  3. Reject background execution and any sandbox-disable request.
  4. Validate or discard inert description/timeout fields.
  5. Return a normalized updatedInput containing only the exact command.
  6. Add hermetic tests for every optional field and unknown-key rejection, plus content-free input-key diagnostics.
  7. Re-run full CI/review and use a new campaign; do not retry the stopped v4 evidence.

Relevant code: permissions.ts currently applies hasExactKeys(input, ["command"]) in both classification and policy evaluation; sdk-tools.d.ts declares the wider BashInput schema.

Accept only the pinned SDK Bash fields, reject unsafe controls, and canonicalize allowed execution to the exact allowlisted command.

Refs: SAP-2632
@github-actions github-actions Bot removed area: ci-release Changes to CI, repository automation, or releases area: studio Changes to Agent Studio or harness applications contribution: incomplete Required pull request information is incomplete or ambiguous contributor: external Pull request author does not have write, maintain, or admin access to sapiom-js review: manual External pull request requires maintainer review before automation review: sensitive Changes affect sensitive repository or release infrastructure size: xlarge Review size exceeds 1,000 changed lines labels Aug 18, 2026
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