[AAASM-3500] ✨ (node-sdk): Wire OpControlSubscriber into withAssembly tool path#172
Conversation
Consult the live OpControlSubscriber before the pre-exec gateway check in
the withAssembly tool wrapper (AAASM-3491). A terminated op fast-fails the
call before the gateway is queried (short-circuit); a paused op blocks
cooperatively in waitForOp until the gateway resumes it. The subscriber is
an optional `opControl` dependency threaded through WithAssemblyOptions via
the narrow OpControl seam, mirroring the Python companion's
build_governance_interceptor(op_control=...). op_id resolves from an explicit
opId or composes {traceId}:{spanId}; absent a trace identity op control is
skipped. Closes the gap where an operator terminate/pause never reached a
running tool through the SDK path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The OpControlSubscriber (and OpTerminatedError / OpControl seam) shipped in src/op-control.ts but were unreachable from `@agent-assembly/sdk` — callers could not construct a subscriber to pass to withAssembly. Re-export them from the public entrypoint so the AAASM-3491 kill switch is wireable (AAASM-3500). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…embly
Cover the AAASM-3491 wiring: a terminate denies the tool BEFORE the gateway
is queried (short-circuit asserted via gateway.check not called), a paused op
blocks then proceeds on resume, a call without trace identity skips op control,
and op_id resolution (explicit opId wins, else {traceId}:{spanId}). Mirrors the
Python companion's test_runtime_interceptor suite.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
🔎 Review (Claude Code) — ready for approvalCI: ✅ All green — 16/16 checks pass, 0 failures (Analyze/CodeQL/SonarCloud, build ESM+CJS, vitest, typecheck, lint). Scope vs AAASM-3500 ("Export + wire OpControlSubscriber in node-sdk withAssembly tool path"): ✅ Fully covers it. The previously-dead Additive & safe: Verdict: Scope complete, CI green, regression coverage present. Ready to approve & merge. Follow-up AAASM-3500 stays open until merge + re-verification. |



Target
Task summary:
Follow-up to Bug AAASM-3491 (live kill switch never reached a running agent). The authoritative runtime fix merged in agent-assembly PR #1176 and the python-sdk companion in python-sdk PR [AAASM-3177] ✅ (node-sdk): Raise test coverage toward 90% #156 (the reference pattern). The node-sdk already shipped a complete
OpControlSubscriberinsrc/op-control.ts, but it was dead code: not exported fromindex.tsand never consulted by thewithAssemblytool wrapper, which only did pre-execgateway.check()+waitForApproval. This PR exports the subscriber and wires it into thewithAssemblytool path so an operator terminate/pause reaches a running tool through the SDK layer.Task tickets:
Key point change (optional):
waitForOpuntil the gateway resumes it.op_idresolves from an explicitopIdon the call's first argument, otherwise composes{traceId}:{spanId}; absent a trace identity, op control is skipped.opControldependency onWithAssemblyOptionsvia a narrowOpControlseam, mirroring the Python companion'sbuild_governance_interceptor(op_control=...). Without it, the tool path behaves exactly as before.Effecting Scope
Purely additive.
opControlis optional; existingwithAssemblycallers are unaffected.Description
src/wrappers/with-assembly.ts: add theOpControlseam + optionalopControloption; consult op-control before the gateway check in both theexecuteandinvoketool paths (terminate →PolicyViolationError, pause → cooperative block); addextractOpId(opIdelse{traceId}:{spanId}).src/wrappers/index.ts: re-export theOpControltype.src/index.ts: exportOpControlSubscriber,OpControlClient,OpControlSubscriberOptions, andOpTerminatedErrorfrom the package entrypoint so the kill switch is wireable.tests/with-assembly-op-control.test.ts: regression tests — terminate denies BEFORE the gateway is queried (short-circuit), pause blocks then proceeds on resume, no-trace-identity skips op control, op_id resolution, no-opControl path unchanged, invoke path.How to verify
pnpm test(320 passed / 2 skipped),pnpm typecheck,pnpm lint,pnpm build— all green locally.Closes AAASM-3500.
🤖 Generated with Claude Code