Skip to content

<objective> Prove TOOL-05 end to end: outcome-equal results through MCP and ACP against one dispatcher, a static no-tool-logic guard over all three surfaces, and taxonomy coverage for the phase.

Purpose: Deliver P5-D12 and P5-D13, the phase's contract proof, depending only on the two Wave 2 surfaces. Output: Two surface test files plus the taxonomy extension. </objective>

<execution_context> @~/.claude/gsd-core/workflows/execute-plan.md @~/.claude/gsd-core/templates/summary.md </execution_context>

<context> @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/05-omp-plugin-mcp-and-acp-surfaces/05-CONTEXT.md </context>

<tasks>

<task type="tdd"> <name>Task 1: MCP-versus-ACP outcome equivalence on one dispatcher (P5-D13)</name> <files>test/surfaces/equivalence.test.ts</files> <read_first> - src/mcp/server.ts (from plan 05-03; the MCP half: envelope shape to strip at the test edge) - src/acp/agent.ts (from plan 05-04; the ACP half: realm/tool envelope shape to strip at the test edge) - src/tools/dispatch.ts lines 77-89 (ToolOutcome: the done-versus-refused shape compared outcome-equal) - test/support/fake-tools.ts lines 153-200 (makeHarness: the ONE dispatcher both surfaces drive) - test/tools/dispatch.test.ts (call-order style proving both surfaces reach the same pipeline) </read_first> <behavior> - Test (TOOL-05): the same ToolCall for each of the six tools through the MCP server and through the ACP adapter against one harness dispatcher returns outcome-equal ToolOutcome payloads after envelope stripping - Test (TOOL-05): one refusal case (a schema-invalid call and a required-mode non-active write) is outcome-equal across both surfaces with the same catalogue code - Test titles cite TOOL-05 </behavior> <action>Write the failing tests first per behavior, then implement test/surfaces/equivalence.test.ts per P5-D13: build one makeHarness dispatcher, wire both surfaces to it over in-memory streams, send the identical ToolCall through each surface, strip only the transport envelope (JSON-RPC ids on the MCP half, realm/tool wrappers on the ACP half) at the test edge without editing either surface, and deep-equal the ToolOutcome payloads. Cover all six tools plus the two refusal cases. A mismatch fails with both payloads shown. (Implements P5-D13; P5-D11 holds because neither surface is edited.)</action> <acceptance_criteria> - test/surfaces/equivalence.test.ts asserts outcome-equal payloads for all six tools plus both refusal cases across the two surfaces - Envelope stripping lives in the test only; src/mcp/ and src/acp/ are untouched </acceptance_criteria> <verify> <automated>npx tsc -p tsconfig.json && node --test dist/test/surfaces/equivalence.test.js</automated> </verify> <done>Equivalence green for six tools plus refusals on one dispatcher.</done> </task>

<task type="auto"> <name>Task 2: No-tool-logic static guard plus taxonomy coverage (P5-D12)</name> <files>test/surfaces/no-logic.test.ts, test/quality/suite-taxonomy.test.ts</files> <read_first> - test/tools/no-bypass.test.ts lines 17-60 (GUARDED_SYMBOLS, SHARED_RUNTIME_MODULES, FILE_FUNCTIONS, violation-collector style to copy) - test/tools/no-bypass.test.ts lines 100-140 (title-cite style for structural assertions) - src/mcp/server.ts and src/acp/agent.ts and src/omp/plugin.ts (the three surfaces the guard scans; read to list their legitimate imports) - test/quality/suite-taxonomy.test.ts lines 12-24 and 222-241 (CATEGORY_DIRS, title-count style, and the Phase 4 ID check to mirror) </read_first> <action>Implement test/surfaces/no-logic.test.ts per P5-D12 by copying the no-bypass.test.ts grep-source method: assert the D-99 symbols (buildExecArgv, lockedWrite, readFileCapped, listDir, spawnOpenShellRunner) are referenced only from their allowlisted modules, that no file under src/mcp/, src/acp/, or src/omp/ references any of them or any dispatcher-internal symbol the surfaces must not touch, that those surface files call the dispatcher only through ToolDispatcher.call, and that spawn( still appears in src/ only in src/runtime/session-execution.ts. Then extend test/quality/suite-taxonomy.test.ts in place: add the realm, mcp, acp, omp, surfaces, and docs category entries and a PHASE_5_REQUIREMENT_IDS check (TOOL-05, OMP-01 to OMP-05) mirroring the Phase 4 check, keeping earlier phase lists intact. Test titles cite TOOL-05. (Implements P5-D12 and the QUAL-02 traceability row.)</action> <acceptance_criteria> - The guard fails on a planted tool-internal reference in any surface and passes on the real tree - The taxonomy cites all six Phase 5 IDs from named test files with earlier phases intact </acceptance_criteria> <verify> <automated>npx tsc -p tsconfig.json && node --test dist/test/surfaces/no-logic.test.js dist/test/quality/suite-taxonomy.test.js</automated> </verify> <done>Guard and taxonomy green with surfaces proven logic-free.</done> </task>

</tasks>

<threat_model>

Trust Boundaries ​

BoundaryDescription
MCP envelope -> comparison edgeTransport framing crosses into the comparison; only the ToolOutcome payload is compared, never ids or wrappers
source tree -> static guardSource text crosses into assertions; the guard reads files but executes nothing

STRIDE Threat Register ​

Threat IDCategoryComponentSeverityDispositionMitigation Plan
T-05-12T (Tampering)src/mcp/ plus src/acp/ plus src/omp/highmitigateThe static guard proves no surface references tool internals or spawns processes, so tool logic cannot hide outside the dispatcher pipeline (P5-D12); the guard self-tests with a planted violation
T-05-13R (Repudiation)test/surfaces/equivalence.test.tslowacceptEquivalence compares outcome payloads only after envelope stripping at the test edge; rationale: envelope shape is covered by the 05-03 and 05-04 tests, and stripping code never ships
</threat_model>

<verification> npx tsc -p tsconfig.json && node --test dist/test/surfaces/equivalence.test.js dist/test/surfaces/no-logic.test.js dist/test/quality/suite-taxonomy.test.js; grep the surface test files for TOOL-05 in test titles. </verification>

<success_criteria> Same-call outcome equivalence for six tools plus refusals, a self-testing no-logic guard over all three surfaces, and taxonomy coverage for all six Phase 5 IDs. </success_criteria>

Artifacts this phase produces (contribution of this plan) ​

  • test/surfaces/equivalence.test.ts (new): TOOL-05 outcome-equal comparison across MCP and ACP on one dispatcher (P5-D13).
  • test/surfaces/no-logic.test.ts (new): P5-D12 static guard over src/mcp/, src/acp/, src/omp/ in the D-99 style.
  • test/quality/suite-taxonomy.test.ts (extended): Phase 5 category entries and ID citation check.

<output> Create .planning/phases/05-omp-plugin-mcp-and-acp-surfaces/05-06-SUMMARY.md when done </output>

AGPL-3.0-only. Copyright (C) 2026 Spectrum Web Co/swcstudiospace.