From e819a586b0d7e4478c8846144038af0a2a5cd651 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 24 Jul 2026 01:40:25 +0800 Subject: [PATCH 01/32] refactor(acp): reduce bridge to automation protocol --- .../2026-06-14-session-persistence.md | 4 +- ...-18-agent-lifecycle-and-ownership-seams.md | 4 +- .../architecture/2026-06-20-branded-ids.md | 2 +- ...2026-06-20-extract-example-app-packages.md | 2 +- ...06-20-generic-long-running-tool-runtime.md | 2 +- .../2026-06-20-package-hierarchy.md | 9 +- .../2026-06-30-event-domain-semantics.md | 4 +- .../2026-07-02-fs-per-session-cwd.md | 8 +- ...26-07-02-result-time-applied-hunk-diffs.md | 8 +- .../2026-07-02-tool-render-intent-union.md | 15 +- ...cutable-sdk-runtime-distribution.i18n.yaml | 4 +- ...ile-executable-sdk-runtime-distribution.md | 2 +- ...-executable-sdk-runtime-distribution.zh.md | 2 +- .../2026-07-12-agent-scope-runtime-design.md | 10 +- .../2026-07-12-scoped-layers-store.i18n.yaml | 4 +- .../2026-07-12-scoped-layers-store.md | 2 +- .../2026-07-12-scoped-layers-store.zh.md | 2 +- ...-model-catalog-and-acp-selection.i18n.yaml | 4 +- ...-15-llm-model-catalog-and-acp-selection.md | 35 +- ...-llm-model-catalog-and-acp-selection.zh.md | 39 +- .../2026-07-15-lsp-capability-seam.i18n.yaml | 4 +- .../2026-07-15-lsp-capability-seam.md | 8 +- .../2026-07-15-lsp-capability-seam.zh.md | 8 +- ...ui-interactive-extension-service.i18n.yaml | 4 +- ...07-22-tui-interactive-extension-service.md | 2 +- ...22-tui-interactive-extension-service.zh.md | 2 +- ...de-mode-result-card-completeness.i18n.yaml | 4 +- ...7-20-code-mode-result-card-completeness.md | 8 +- ...0-code-mode-result-card-completeness.zh.md | 8 +- .../2026-06-14-acp-agent-client-protocol.md | 6 +- .../feature/2026-06-14-acp-multi-session.md | 20 +- .../feature/2026-06-15-code-mode.md | 2 +- ...6-06-18-acp-terminal-and-tool-rendering.md | 2 + .../feature/2026-06-25-ask-user-question.md | 14 +- .../feature/2026-06-29-todo-write-tool.md | 24 +- .../feature/2026-06-30-hook-bridges.md | 4 +- .../feature/2026-06-30-interception-seams.md | 2 +- .../2026-06-30-session-store-fork-api.md | 2 +- .../feature/2026-07-05-dynamic-workflows.md | 2 +- .../feature/2026-07-05-skill-system.md | 4 +- .../feature/2026-07-06-approval-seam.md | 40 +- .../implemented/feature/2026-07-06-sandbox.md | 31 +- .../feature/2026-07-07-mcp-client-plugin.md | 4 +- .../feature/2026-07-07-plan-mode.md | 12 +- .../2026-07-16-harness-level-loop.i18n.yaml | 4 +- .../feature/2026-07-16-harness-level-loop.md | 8 +- .../2026-07-16-harness-level-loop.zh.md | 8 +- ...26-07-16-persistent-pty-sessions.i18n.yaml | 4 +- .../2026-07-16-persistent-pty-sessions.md | 6 +- .../2026-07-16-persistent-pty-sessions.zh.md | 8 +- ...cated-full-screen-tui-front-door.i18n.yaml | 4 +- ...17-dedicated-full-screen-tui-front-door.md | 2 +- ...dedicated-full-screen-tui-front-door.zh.md | 2 +- ...-fresh-agent-ralph-workflow-tool.i18n.yaml | 4 +- ...6-07-19-fresh-agent-ralph-workflow-tool.md | 2 +- ...7-19-fresh-agent-ralph-workflow-tool.zh.md | 2 +- .../2026-07-19-human-goal-command.i18n.yaml | 4 +- .../feature/2026-07-19-human-goal-command.md | 18 +- .../2026-07-19-human-goal-command.zh.md | 18 +- ...26-07-19-model-facing-goal-tools.i18n.yaml | 4 +- .../2026-07-19-model-facing-goal-tools.md | 2 +- .../2026-07-19-model-facing-goal-tools.zh.md | 2 +- ...7-19-plugin-command-registration.i18n.yaml | 4 +- .../2026-07-19-plugin-command-registration.md | 35 +- ...26-07-19-plugin-command-registration.zh.md | 35 +- ...9-same-session-goal-round-driver.i18n.yaml | 4 +- ...26-07-19-same-session-goal-round-driver.md | 2 +- ...07-19-same-session-goal-round-driver.zh.md | 2 +- ...-20-code-mode-typed-tool-returns.i18n.yaml | 4 +- ...2026-07-20-code-mode-typed-tool-returns.md | 4 +- ...6-07-20-code-mode-typed-tool-returns.zh.md | 4 +- ...6-07-21-cross-session-references.i18n.yaml | 4 +- .../2026-07-21-cross-session-references.md | 16 +- .../2026-07-21-cross-session-references.zh.md | 16 +- ...-07-21-log-backed-session-titles.i18n.yaml | 4 +- .../2026-07-21-log-backed-session-titles.md | 4 +- ...2026-07-21-log-backed-session-titles.zh.md | 4 +- .../2026-07-03-documentation-graph-atlas.md | 5 +- .../2026-07-04-doc-tiers-and-budgets.md | 2 +- ...2026-06-19-drop-mutable-session-summary.md | 4 +- ...6-20-collapse-trace-only-session-events.md | 2 +- .../2026-06-20-prune-dead-seam-methods.md | 4 +- .../2026-06-20-public-agent-stop-surface.md | 2 +- ...-20-remove-agent-boundary-mirror-events.md | 2 +- .../2026-07-02-remove-stream-chunk-mirror.md | 2 +- .../2026-07-04-drop-image-content-block.md | 8 +- .../2026-07-04-fold-stdio-ui-helper.md | 2 +- ...-04-trim-acp-bridge-unreachable-surface.md | 8 +- ...07-20-retire-readline-front-door.i18n.yaml | 4 +- .../2026-07-20-retire-readline-front-door.md | 2 +- ...026-07-20-retire-readline-front-door.zh.md | 2 +- ...lan-specific-collaboration-state.i18n.yaml | 4 +- ...07-22-plan-specific-collaboration-state.md | 9 +- ...22-plan-specific-collaboration-state.zh.md | 9 +- ...itles-from-session-title-service.i18n.yaml | 4 +- ...2-tui-titles-from-session-title-service.md | 2 +- ...ui-titles-from-session-title-service.zh.md | 2 +- ...-23-acp-automation-only-protocol.i18n.yaml | 6 + ...2026-07-23-acp-automation-only-protocol.md | 51 + ...6-07-23-acp-automation-only-protocol.zh.md | 51 + .../testing/2026-06-19-acp-snapshot-tests.md | 10 +- .../testing/2026-06-19-real-api-e2e-ci.md | 2 +- .../2026-06-22-subagent-snapshot-replay.md | 2 +- .../2026-07-04-hook-snapshot-matrix.md | 2 +- .../2026-06-30-pre-tool-input-rewrite.md | 2 +- ...026-07-14-sdk-developer-projects.i18n.yaml | 4 +- .../2026-07-14-sdk-developer-projects.md | 4 +- .../2026-07-14-sdk-developer-projects.zh.md | 4 +- ...026-07-04-prune-dead-core-spine-surface.md | 2 +- ...am-workflow-progress-through-tool-calls.md | 2 +- .../2026-06-20-drop-acp-session-load.md | 2 +- .../skills/dsh-find-simplifications/SKILL.md | 2 +- AGENTS.md | 7 +- docs/architecture.i18n.yaml | 4 +- docs/architecture.md | 2 +- docs/architecture.zh.md | 2 +- docs/capability-seams.md | 28 +- docs/config-catalog.md | 27 +- docs/cookbook/adding-a-tool.i18n.yaml | 4 +- docs/cookbook/adding-a-tool.md | 16 +- docs/cookbook/adding-a-tool.zh.md | 16 +- docs/cookbook/extension-cookbook.i18n.yaml | 4 +- docs/cookbook/extension-cookbook.md | 6 +- docs/cookbook/extension-cookbook.zh.md | 6 +- docs/core-data-structures/approval.md | 4 +- docs/core-data-structures/commands.md | 6 +- docs/core-data-structures/session.md | 9 +- docs/core-data-structures/tools.md | 4 +- docs/core-data-structures/user-interaction.md | 4 +- docs/development.i18n.yaml | 4 +- docs/development.md | 4 +- docs/development.zh.md | 4 +- docs/event-producer-consumer.md | 8 +- docs/graph-atlas.md | 1 - docs/module-graph.md | 36 +- docs/persistence-catalog.md | 30 +- .../0001-acp-default-export-drops-inject.md | 4 +- docs/testing.md | 4 +- docs/tool-catalog.md | 4 +- docs/user/develop/basic/tool.i18n.yaml | 4 +- docs/user/develop/basic/tool.md | 2 +- docs/user/develop/basic/tool.zh.md | 2 +- docs/user/guide/config.i18n.yaml | 4 +- docs/user/guide/config.md | 2 +- docs/user/guide/config.zh.md | 2 +- examples/README.md | 6 +- examples/acp-agent/README.md | 57 +- examples/acp-agent/composition.md | 15 +- examples/acp-agent/cordis.yml | 39 +- examples/acp-agent/package.json | 2 +- examples/acp-agent/tests/acp.e2e.ts | 63 +- examples/acp-agent/tests/acp.snapshot.ts | 70 +- examples/acp-agent/tests/escalation.e2e.ts | 55 +- ...ve-mode-switching-2026-07-07.session.jsonl | 2212 ----------------- .../goal-snapshots/goal-session/input.json | 5 +- .../goal-session/replay.override.json | 2 +- .../goal-session/stdout.expected.jsonl | 11 +- examples/acp-agent/tests/goal.snapshot.ts | 6 +- examples/acp-agent/tests/hooks.e2e.ts | 6 +- examples/acp-agent/tests/plan-mode.e2e.ts | 84 - .../stdout.expected.jsonl | 9 - .../tests/semantic-checkpoint.snapshot.ts | 129 - .../advanced-toolchain/stdout.expected.jsonl | 16 +- .../system-prompt.expected.md | 36 - .../tool-schemas.expected.json | 79 - .../tests/snapshots/bash-spill/session.jsonl | 2 +- .../bash-spill/stdout.expected.jsonl | 8 +- .../input.json | 2 +- .../session.jsonl | 0 .../bash-tool-turn/stdout.expected.jsonl | 4 + .../both-mode-turn/stdout.expected.jsonl | 66 +- .../both-mode-turn/system-prompt.expected.md | 36 - .../both-mode-turn/tool-schemas.expected.json | 79 - .../snapshots/cancel-tool-calls/input.json | 4 +- .../cancel-tool-calls/stdout.expected.jsonl | 10 +- .../tests/snapshots/cancel/input.json | 6 +- .../snapshots/cancel/replay.override.json | 2 +- .../snapshots/cancel/stdout.expected.jsonl | 7 +- .../code-mode-turn/stdout.expected.jsonl | 574 +---- .../code-mode-turn/system-prompt.expected.md | 36 - .../stdout.expected.jsonl | 141 +- .../system-prompt.expected.md | 36 - .../tests/snapshots/config-options/input.json | 30 - .../snapshots/config-options/session.jsonl | 1 - .../config-options/stdout.expected.jsonl | 7 - .../stdout.expected.jsonl | 10 +- .../error-finish/stdout.expected.jsonl | 7 +- .../snapshots/escalation-approved/input.json | 5 - .../escalation-approved/session.jsonl | 369 ++- .../escalation-approved/stdout.expected.jsonl | 81 +- .../system-prompt.expected.md | 24 + .../tool-schemas.expected.json | 473 ++++ .../snapshots/escalation-rejected/input.json | 5 - .../escalation-rejected/session.jsonl | 423 ++-- .../escalation-rejected/stdout.expected.jsonl | 104 +- .../tests/snapshots/fs-edit/session.jsonl | 2 +- .../snapshots/fs-edit/stdout.expected.jsonl | 91 +- .../fs-escalation-approved/input.json | 1 - .../fs-escalation-approved/session.jsonl | 247 +- .../stdout.expected.jsonl | 57 +- .../snapshots/fs-policy-reject/session.jsonl | 4 +- .../fs-policy-reject/stdout.expected.jsonl | 152 +- .../fs-read-window/stdout.expected.jsonl | 94 +- .../snapshots/fs-read/stdout.expected.jsonl | 77 +- .../fs-terminal-card/stdout.expected.jsonl | 49 - .../fs-write-overwrite/session.jsonl | 2 +- .../fs-write-overwrite/stdout.expected.jsonl | 88 +- .../tests/snapshots/fs-write/session.jsonl | 2 +- .../snapshots/fs-write/stdout.expected.jsonl | 58 +- .../snapshots/goal-command-status/input.json | 7 - .../goal-command-status/session.jsonl | 1 - .../goal-command-status/stdout.expected.jsonl | 5 - .../snapshots/handshake/stdout.expected.jsonl | 5 +- .../stdout.expected.jsonl | 94 +- .../stdout.expected.jsonl | 82 +- .../hook-cc-pretool-ask/session.jsonl | 4 +- .../hook-cc-pretool-ask/stdout.expected.jsonl | 70 +- .../stdout.expected.jsonl | 77 +- .../stdout.expected.jsonl | 5 +- .../stdout.expected.jsonl | 28 +- .../stdout.expected.jsonl | 47 +- .../stdout.expected.jsonl | 73 +- .../stdout.expected.jsonl | 72 +- .../stdout.expected.jsonl | 74 +- .../stdout.expected.jsonl | 5 +- .../stdout.expected.jsonl | 47 +- .../stdout.expected.jsonl | 47 +- .../lsp-definition/stdout.expected.jsonl | 8 +- .../lsp-definition/tool-schemas.expected.json | 79 - .../snapshots/model-switching/input.json | 23 - .../snapshots/model-switching/session.jsonl | 70 - .../model-switching/stdout.expected.jsonl | 49 - .../model-switching/system-prompt.expected.md | 53 - .../tool-schemas.expected.json | 1102 -------- .../snapshots/modes-advertise/input.json | 22 - .../snapshots/modes-advertise/session.jsonl | 1 - .../modes-advertise/stdout.expected.jsonl | 8 - .../multi-turn/stdout.expected.jsonl | 45 +- .../packed-chunks/stdout.expected.jsonl | 77 +- .../parallel-tool-calls/stdout.expected.jsonl | 10 +- .../snapshots/permission-switching/input.json | 32 - .../permission-switching/session.jsonl | 239 -- .../stdout.expected.jsonl | 129 - .../system-prompt.expected.md | 52 - .../tool-schemas.expected.json | 1102 -------- .../permission-switching/workspace/notes.txt | 1 - .../snapshots/plan-mode-reject/input.json | 24 - .../snapshots/plan-mode-reject/session.jsonl | 425 ---- .../plan-mode-reject/stdout.expected.jsonl | 279 --- .../plan-mode-reject/workspace/notes.txt | 2 - .../tests/snapshots/plan-mode/input.json | 28 - .../tests/snapshots/plan-mode/session.jsonl | 532 ---- .../snapshots/plan-mode/stdout.expected.jsonl | 267 -- .../plan-mode/system-prompt.expected.md | 66 - .../plan-mode/tool-schemas.expected.json | 1102 -------- .../snapshots/plan-mode/workspace/notes.txt | 2 - .../tests/snapshots/pty-tools/input.json | 2 +- .../snapshots/pty-tools/stdout.expected.jsonl | 18 +- .../pty-tools/tool-schemas.expected.json | 79 - .../reject-extra-dirs/stdout.expected.jsonl | 4 +- .../repeat-tool-guard/stdout.expected.jsonl | 21 +- .../snapshots/session-sandbox-root/input.json | 1 - .../session-sandbox-root/session.jsonl | 47 +- .../stdout.expected.jsonl | 11 +- .../skill-load/stdout.expected.jsonl | 10 +- .../skill-load/tool-schemas.expected.json | 79 - .../stdout.expected.jsonl | 8 +- .../subagent-fork/stdout.expected.jsonl | 120 +- .../subagent-mixed/stdout.expected.jsonl | 171 +- .../subagent-multi/stdout.expected.jsonl | 117 +- .../subagent-spawn/stdout.expected.jsonl | 110 +- .../snapshots/text-turn/stdout.expected.jsonl | 29 +- .../text-turn/tool-schemas.expected.json | 79 - .../snapshots/todo-plan/stdout.expected.jsonl | 62 - .../{todo-plan => todo-write}/input.json | 0 .../{todo-plan => todo-write}/session.jsonl | 0 .../todo-write/stdout.expected.jsonl | 4 + .../tool-call-turn/stdout.expected.jsonl | 53 +- .../workflow-run/stdout.expected.jsonl | 132 +- .../workspace-context/stdout.expected.jsonl | 8 +- .../tool-schemas.expected.json | 79 - .../workspace-edit/stdout.expected.jsonl | 136 +- .../stdout.expected.windows.jsonl | 134 - .../semantic-checkpoint.cordis.snapshot.yml | 37 + .../fixtures/semantic-checkpoint-agent.ts | 25 + .../tool-outcome-unknown/replay.jsonl | 0 .../tool-outcome-unknown/replay.override.json | 0 .../session.expected.jsonl | 0 .../tests/semantic-checkpoint.snapshot.ts | 113 + .../tests/snapshots/pty-tools/session.jsonl | 2 +- knip.json | 1 + packages/README.md | 5 +- packages/acp/README.md | 9 + packages/acp/acp/README.md | 77 + packages/acp/acp/package.json | 51 + packages/acp/acp/src/codec.ts | 49 + packages/acp/acp/src/index.ts | 317 +++ packages/{ui => acp}/acp/src/invariant.ts | 4 +- packages/acp/acp/tests/approval.spec.ts | 71 + packages/acp/acp/tests/bridge.spec.ts | 123 + packages/acp/acp/tests/codec.spec.ts | 37 + packages/acp/acp/tests/dispose.spec.ts | 85 + packages/acp/acp/tests/edges.spec.ts | 65 + packages/acp/acp/tests/harness.ts | 171 ++ packages/acp/acp/tests/multi-session.spec.ts | 95 + packages/acp/acp/tests/turns.spec.ts | 156 ++ packages/acp/acp/tsconfig.json | 33 + packages/context/README.md | 2 +- packages/context/session-reference/README.md | 4 +- packages/cordis/tool-cordis/src/present.ts | 8 +- packages/core/session/src/types.ts | 7 +- packages/core/tools/src/code-mode.ts | 2 +- packages/core/tools/src/index.ts | 2 +- packages/core/tools/src/presentation.ts | 21 +- packages/core/tools/tests/code-mode.spec.ts | 6 +- packages/examples/README.md | 6 +- packages/examples/acp-demo/README.md | 87 +- packages/examples/acp-demo/package.json | 14 +- packages/examples/acp-demo/src/bin.ts | 2 +- packages/examples/acp-demo/src/index.ts | 33 +- .../examples/acp-demo/tests/acp-agent.spec.ts | 23 +- .../examples/acp-demo/tests/built-bin.e2e.ts | 46 +- .../examples/acp-demo/tests/load-path.e2e.ts | 25 +- packages/examples/acp-demo/tsconfig.json | 23 +- packages/examples/agent-spine-demo/README.md | 4 +- packages/fs/tool-fs/src/diff.ts | 5 +- packages/fs/tool-fs/src/session-cwd.ts | 2 +- packages/fs/tool-fs/src/write.ts | 12 +- packages/fs/tool-fs/tests/diff.spec.ts | 2 +- packages/fs/tool-fs/tests/integration.spec.ts | 4 +- packages/fs/tool-fs/tests/tools.spec.ts | 11 +- packages/goal/command-goal/README.md | 8 +- packages/goal/tool-goal/README.md | 2 +- packages/hooks/hooks-claude/src/index.ts | 2 +- packages/host/runtime/src/start.ts | 6 +- packages/llm/llm-deepseek/README.md | 2 +- packages/lsp/tool-lsp/README.md | 6 +- packages/lsp/tool-lsp/src/render.ts | 8 +- packages/plan/README.md | 2 +- packages/plan/plan-mode/README.md | 2 +- .../plan/plan-mode/tests/integration.spec.ts | 4 +- packages/pty/tool-pty/README.md | 2 +- packages/pty/tool-pty/src/render.ts | 2 +- packages/sandbox/sandbox-policy/README.md | 2 +- .../sandbox-policy/src/session-mode.ts | 4 +- .../sdk/create-sdk/src/create-questions.ts | 2 +- .../sdk/create-sdk/tests/create.snapshot.ts | 8 +- packages/sdk/helper/README.md | 2 +- .../sdk/helper/src/features/builtin/app.ts | 10 +- .../sdk/helper/src/features/builtin/index.ts | 2 +- .../helper/src/templates/assets/README.md.tpl | 4 +- packages/sdk/helper/tests/project.spec.ts | 17 +- .../__snapshots__/config.snapshot.ts.snap | 2 +- packages/sdk/scripts/tests/scripts.spec.ts | 8 +- packages/subagent/subagent-acp/README.md | 2 +- packages/support/acp-snapshot/README.md | 28 +- packages/support/acp-snapshot/src/harness.ts | 168 +- packages/support/acp-snapshot/src/index.ts | 1 - packages/support/acp-snapshot/src/launcher.ts | 7 - .../support/acp-snapshot/src/normalize.ts | 3 - packages/support/acp-snapshot/src/suite.ts | 3 + .../tests/fixtures/fake-acp-agent.ts | 137 +- .../acp-snapshot/tests/harness.spec.ts | 264 +- .../acp-snapshot/tests/normalize.spec.ts | 18 - .../support/acp-snapshot/tests/suite.spec.ts | 1 + packages/support/llm-replay/README.md | 4 +- packages/support/llm-replay/src/index.ts | 11 +- .../llm-replay/tests/llm-replay.spec.ts | 6 +- packages/tasks/tool-tasks/README.md | 2 +- packages/todo/README.md | 2 +- packages/todo/tool-todo/README.md | 6 +- packages/ui/README.md | 11 +- packages/ui/acp/README.md | 199 -- packages/ui/acp/acp-feature-support.md | 158 -- packages/ui/acp/package.json | 86 - packages/ui/acp/snapshot-replay.md | 27 - packages/ui/acp/src/codec.ts | 138 - packages/ui/acp/src/index.ts | 1756 ------------- packages/ui/acp/tests/approval.spec.ts | 113 - packages/ui/acp/tests/bridge.spec.ts | 468 ---- packages/ui/acp/tests/codec.spec.ts | 101 - packages/ui/acp/tests/commands.spec.ts | 299 --- packages/ui/acp/tests/config-options.spec.ts | 420 ---- packages/ui/acp/tests/dispose.spec.ts | 320 --- packages/ui/acp/tests/edges.spec.ts | 68 - packages/ui/acp/tests/harness.ts | 340 --- packages/ui/acp/tests/load.spec.ts | 337 --- packages/ui/acp/tests/modes.spec.ts | 116 - packages/ui/acp/tests/multi-session.spec.ts | 129 - packages/ui/acp/tests/properties.spec.ts | 112 - packages/ui/acp/tests/session-list.spec.ts | 92 - packages/ui/acp/tests/stream-update.spec.ts | 966 ------- packages/ui/acp/tests/turns.spec.ts | 406 --- packages/ui/acp/tsconfig.json | 72 - packages/ui/commands/README.md | 8 +- packages/ui/commands/src/index.ts | 2 +- packages/ui/permission/README.md | 4 +- packages/ui/permission/src/index.ts | 2 +- packages/ui/user-approval/README.md | 6 +- packages/ui/user-interaction/README.md | 2 +- pnpm-lock.yaml | 162 +- scripts/gen-doc-graphs.ts | 55 +- scripts/gen-module-graph.ts | 1 + scripts/gen-tool-catalog.ts | 2 +- tsconfig.base.json | 2 + tsconfig.host.json | 2 +- 406 files changed, 3880 insertions(+), 21325 deletions(-) create mode 100644 .agents/notes/implemented/simplification/2026-07-23-acp-automation-only-protocol.i18n.yaml create mode 100644 .agents/notes/implemented/simplification/2026-07-23-acp-automation-only-protocol.md create mode 100644 .agents/notes/implemented/simplification/2026-07-23-acp-automation-only-protocol.zh.md rename .agents/notes/{proposed => rejected}/feature/2026-07-13-stream-workflow-progress-through-tool-calls.md (98%) delete mode 100644 examples/acp-agent/tests/fixtures/live-mode-switching-2026-07-07.session.jsonl delete mode 100644 examples/acp-agent/tests/plan-mode.e2e.ts delete mode 100644 examples/acp-agent/tests/semantic-checkpoint-snapshots/tool-outcome-unknown/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/semantic-checkpoint.snapshot.ts rename examples/acp-agent/tests/snapshots/{fs-terminal-card => bash-tool-turn}/input.json (77%) rename examples/acp-agent/tests/snapshots/{fs-terminal-card => bash-tool-turn}/session.jsonl (100%) create mode 100644 examples/acp-agent/tests/snapshots/bash-tool-turn/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/config-options/input.json delete mode 100644 examples/acp-agent/tests/snapshots/config-options/session.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/config-options/stdout.expected.jsonl create mode 100644 examples/acp-agent/tests/snapshots/escalation-approved/system-prompt.expected.md create mode 100644 examples/acp-agent/tests/snapshots/escalation-approved/tool-schemas.expected.json delete mode 100644 examples/acp-agent/tests/snapshots/fs-terminal-card/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/goal-command-status/input.json delete mode 100644 examples/acp-agent/tests/snapshots/goal-command-status/session.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/goal-command-status/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/model-switching/input.json delete mode 100644 examples/acp-agent/tests/snapshots/model-switching/session.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/model-switching/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/model-switching/system-prompt.expected.md delete mode 100644 examples/acp-agent/tests/snapshots/model-switching/tool-schemas.expected.json delete mode 100644 examples/acp-agent/tests/snapshots/modes-advertise/input.json delete mode 100644 examples/acp-agent/tests/snapshots/modes-advertise/session.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/modes-advertise/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/permission-switching/input.json delete mode 100644 examples/acp-agent/tests/snapshots/permission-switching/session.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/permission-switching/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/permission-switching/system-prompt.expected.md delete mode 100644 examples/acp-agent/tests/snapshots/permission-switching/tool-schemas.expected.json delete mode 100644 examples/acp-agent/tests/snapshots/permission-switching/workspace/notes.txt delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode-reject/input.json delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode-reject/session.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode-reject/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode-reject/workspace/notes.txt delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode/input.json delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode/session.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode/system-prompt.expected.md delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode/tool-schemas.expected.json delete mode 100644 examples/acp-agent/tests/snapshots/plan-mode/workspace/notes.txt delete mode 100644 examples/acp-agent/tests/snapshots/todo-plan/stdout.expected.jsonl rename examples/acp-agent/tests/snapshots/{todo-plan => todo-write}/input.json (100%) rename examples/acp-agent/tests/snapshots/{todo-plan => todo-write}/session.jsonl (100%) create mode 100644 examples/acp-agent/tests/snapshots/todo-write/stdout.expected.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/workspace-edit/stdout.expected.windows.jsonl create mode 100644 examples/headless-agent/semantic-checkpoint.cordis.snapshot.yml create mode 100644 examples/headless-agent/tests/fixtures/semantic-checkpoint-agent.ts rename examples/{acp-agent => headless-agent}/tests/semantic-checkpoint-snapshots/tool-outcome-unknown/replay.jsonl (100%) rename examples/{acp-agent => headless-agent}/tests/semantic-checkpoint-snapshots/tool-outcome-unknown/replay.override.json (100%) rename examples/{acp-agent => headless-agent}/tests/semantic-checkpoint-snapshots/tool-outcome-unknown/session.expected.jsonl (100%) create mode 100644 examples/headless-agent/tests/semantic-checkpoint.snapshot.ts create mode 100644 packages/acp/README.md create mode 100644 packages/acp/acp/README.md create mode 100644 packages/acp/acp/package.json create mode 100644 packages/acp/acp/src/codec.ts create mode 100644 packages/acp/acp/src/index.ts rename packages/{ui => acp}/acp/src/invariant.ts (85%) create mode 100644 packages/acp/acp/tests/approval.spec.ts create mode 100644 packages/acp/acp/tests/bridge.spec.ts create mode 100644 packages/acp/acp/tests/codec.spec.ts create mode 100644 packages/acp/acp/tests/dispose.spec.ts create mode 100644 packages/acp/acp/tests/edges.spec.ts create mode 100644 packages/acp/acp/tests/harness.ts create mode 100644 packages/acp/acp/tests/multi-session.spec.ts create mode 100644 packages/acp/acp/tests/turns.spec.ts create mode 100644 packages/acp/acp/tsconfig.json delete mode 100644 packages/ui/acp/README.md delete mode 100644 packages/ui/acp/acp-feature-support.md delete mode 100644 packages/ui/acp/package.json delete mode 100644 packages/ui/acp/snapshot-replay.md delete mode 100644 packages/ui/acp/src/codec.ts delete mode 100644 packages/ui/acp/src/index.ts delete mode 100644 packages/ui/acp/tests/approval.spec.ts delete mode 100644 packages/ui/acp/tests/bridge.spec.ts delete mode 100644 packages/ui/acp/tests/codec.spec.ts delete mode 100644 packages/ui/acp/tests/commands.spec.ts delete mode 100644 packages/ui/acp/tests/config-options.spec.ts delete mode 100644 packages/ui/acp/tests/dispose.spec.ts delete mode 100644 packages/ui/acp/tests/edges.spec.ts delete mode 100644 packages/ui/acp/tests/harness.ts delete mode 100644 packages/ui/acp/tests/load.spec.ts delete mode 100644 packages/ui/acp/tests/modes.spec.ts delete mode 100644 packages/ui/acp/tests/multi-session.spec.ts delete mode 100644 packages/ui/acp/tests/properties.spec.ts delete mode 100644 packages/ui/acp/tests/session-list.spec.ts delete mode 100644 packages/ui/acp/tests/stream-update.spec.ts delete mode 100644 packages/ui/acp/tests/turns.spec.ts delete mode 100644 packages/ui/acp/tsconfig.json diff --git a/.agents/notes/implemented/architecture/2026-06-14-session-persistence.md b/.agents/notes/implemented/architecture/2026-06-14-session-persistence.md index 4e105ef598..d6f8da3dce 100644 --- a/.agents/notes/implemented/architecture/2026-06-14-session-persistence.md +++ b/.agents/notes/implemented/architecture/2026-06-14-session-persistence.md @@ -4,7 +4,7 @@ Status: implemented ## Problem -Sessions lived only in memory. The example `session-jsonl.ts` plugin (duplicated byte-for-byte in both examples) was write-only telemetry: it buffered `session/event` and appended JSON lines, with no read/replay path, no crash-safety (no fsync, no atomic write, a fire-and-forget dispose drain), no listing, and no format versioning. Nothing could rehydrate a past session from disk into a live agent, so durable resume ("continue yesterday's task"), durable forking, and the ACP `session/load` method ([ACP support](../feature/2026-06-14-acp-agent-client-protocol.md)) were all impossible. +Sessions lived only in memory. The example `session-jsonl.ts` plugin (duplicated byte-for-byte in both examples) was write-only telemetry: it buffered `session/event` and appended JSON lines, with no read/replay path, no crash-safety (no fsync, no atomic write, a fire-and-forget dispose drain), no listing, and no format versioning. Nothing could rehydrate a past session from disk into a live agent, so durable resume, durable forking, and host-side session browsing were all impossible. The [event-sourced model](2026-06-11-event-sourced-sessions.md) makes the append-only log the single source of truth and derives LLM history from it. Persistence had to stay faithful to that: persist the existing `SessionEvent` directly, with no parallel "persisted message" type that the log is converted to and from. The backend also had to be swappable — a file store now, a database store later — behind one interface. @@ -31,4 +31,4 @@ Format versioning: the header carries a `version`; `load` rejects any non-curren ## Consequences -Two new packages and the metadata seam in `dsh-session` (`session.header`, the `create(id?, options?)` signature). Bought: durable resume/fork, a read/replay path, crash tolerance, and the foundation the ACP `session/load` ([ACP support](../feature/2026-06-14-acp-agent-client-protocol.md)) needs — all over the existing event-sourced log, with the backend swappable behind one interface. The reusable `runPersistenceContract` suite holds every backend to the same append-only, contiguous-seq, lazy-materialization, and serializability semantics. Persisting the full log also settles event fidelity: `assistant/chunk` remains verbatim. +Two new packages and the metadata seam in `dsh-session` (`session.header`, the `create(id?, options?)` signature). Bought: durable resume/fork, a read/replay path, crash tolerance, and host-side session access over the existing event-sourced log, with the backend swappable behind one interface. The reusable `runPersistenceContract` suite holds every backend to the same append-only, contiguous-seq, lazy-materialization, and serializability semantics. Persisting the full log also settles event fidelity: `assistant/chunk` remains verbatim. diff --git a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.md b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.md index 3d84c8074b..e8c6db7439 100644 --- a/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.md +++ b/.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.md @@ -16,7 +16,7 @@ A new `cancel()` verb on the `Agent` interface — the single public stop primit ### 2. `AgentHandle` async disposer -`ctx.agents.create`/`resume` (and the `AgentFactory` interface) return `AgentHandle = { agent: Agent; dispose(): Promise }`. The disposer is a **consumer capability** — a registry observer holding only the bare `Agent` cannot tear it down. The caller fiber and registered factory provider are structural co-owners: caller unload enforces structured ownership, while provider unload must stop old instances whose scoped dependency surface resolves through that provider. All three paths reach the same memoized teardown: stop the loop, await its exit and idle flushes (true quiescence, not just the `disposed` status flip), detach the agent, detach its session, and unwind its scope. Each public ID becomes reusable when its exact registry entry detaches; there is no separate reservation-release phase. Config-created agents are already owned by the `AgentLoop` fiber (the handle is discarded). ACP holds each session's disposer in its `SessionRecord` and runs it on disconnect/teardown, so a bare client disconnect leaves no registered agent and no session-store entry — even when `session/load` races teardown (the just-resumed handle is disposed before the closed-guard throw). +`ctx.agents.create`/`resume` (and the `AgentFactory` interface) return `AgentHandle = { agent: Agent; dispose(): Promise }`. The disposer is a **consumer capability** — a registry observer holding only the bare `Agent` cannot tear it down. The caller fiber and registered factory provider are structural co-owners: caller unload enforces structured ownership, while provider unload must stop old instances whose scoped dependency surface resolves through that provider. All three paths reach the same memoized teardown: stop the loop, await its exit and idle flushes (true quiescence, not just the `disposed` status flip), detach the agent, detach its session, and unwind its scope. Each public ID becomes reusable when its exact registry entry detaches; there is no separate reservation-release phase. Config-created agents are already owned by the `AgentLoop` fiber (the handle is discarded). ACP holds each fresh session's disposer in its `SessionRecord` and runs it on disconnect or plugin teardown, so a bare client disconnect leaves no registered agent and no session-store entry. A create that loses the close race disposes its unpublished handle. **Teardown ORDER is load-bearing for durability**, and the implementation folds the session lifecycle into the agent's SINGLE composite cordis effect (`SessionStore.prepare`/`enter`/`announce`, replacing a sibling-effect split). A fiber unload disposes sibling effects concurrently (`Promise.all`), which would race removing the session store's append publication hooks against the loop's closing `session/flush` and drop the closing `turn/end`; inside one effect the disposers run as an ordered LIFO chain (loop stopped + `await agent.done` BEFORE the session detaches), so the loop's final flush is captured on BOTH the handle's `dispose()` and a fiber unload. The contained `agent/disposed` and `session/disposed` notifications cannot reject the chain or skip later teardown. @@ -28,7 +28,7 @@ Background-task ownership moved from a `tool-bash` plugin-local `Map exec.agent?.id` in `packages/bash/tool-bash/src/index.ts`) wearing a different seam-local name. It is compared for access control (`owner !== callerToken(exec)`), so a mismatched-but-well-typed string here is a cross-session isolation bug the type system currently cannot catch. This is the shared id alias covered by the [unified agent/session identity decision](../simplification/2026-06-20-unify-agent-and-session-id.md). -**Gap 2 — brand erosion at the seams of the *already-branded* IDs.** Even `CallId` and `SessionId` decay back to bare `string` at exactly the places confusion is most likely: registry/store key types and public method params. Representative sites include the session store, the agent registry (both keyed by the shared `SessionId`), `ToolPresenter`'s call-id map, ACP's session-id records and loading set, and the persistence coordinator. A brand that is dropped at a collection key buys nothing on lookups — the value of the existing brands is partly unrealized. +**Gap 2 — brand erosion at the seams of the *already-branded* IDs.** Even `CallId` and `SessionId` decay back to bare `string` at exactly the places confusion is most likely: registry/store key types and public method params. Representative sites include the session store, the agent registry (both keyed by the shared `SessionId`), tool-presentation call-id maps, ACP's session records, and the persistence coordinator. A brand that is dropped at a collection key buys nothing on lookups — the value of the existing brands is partly unrealized. ## Decision diff --git a/.agents/notes/implemented/architecture/2026-06-20-extract-example-app-packages.md b/.agents/notes/implemented/architecture/2026-06-20-extract-example-app-packages.md index 05d72e4e49..87529a04dd 100644 --- a/.agents/notes/implemented/architecture/2026-06-20-extract-example-app-packages.md +++ b/.agents/notes/implemented/architecture/2026-06-20-extract-example-app-packages.md @@ -40,7 +40,7 @@ The old `base*.yml`/`acp-tail.yml` includes already deduped the *config*, but a - Example directories contain only their config, README, and tests: `start.ts`, the infrastructure preamble, and the shared YAML includes are gone. - `demo:tui`, `demo:headless`, and `demo:acp` invoke the app-package bins. - Each new package has a README and per-file 100% coverage; each app package also has a keyless real-Loader-path bin smoke that catches export-shape failures described in [postmortem 0001](../../../../docs/postmortem/0001-acp-default-export-drops-inject.md). -- The ACP replay transcript remains unchanged because the plugin set and load order did not change. +- The ACP replay suite boots through the app-package bin, so protocol wiring and assembled backend behavior cross the real Loader boundary. ## Consequences diff --git a/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md b/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md index f3fe6373ea..f821b0fa4c 100644 --- a/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md +++ b/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md @@ -67,7 +67,7 @@ A producer loaded without any control surface would let callers start work they ## Model-facing control surface -`dsh-tool-tasks` registers three kind-independent tools with generic ACP cards: +`dsh-tool-tasks` registers three kind-independent tools with generic UI cards: - `task_output(task_id, wait?, timeout_ms?)` reads output and always appends `[status: ...]`. Stream tasks return only output since the previous read; final-output tasks return their result after settlement. Reads are non-blocking unless `wait: true`, whose timeout is defaulted and capped by plugin config. A wait timeout reports the still-running status and does not stop the task. - `task_list()` returns caller-visible tasks as ` []