Files
deepseek-harness/.agents/notes/implemented/feature/2026-06-29-todo-write-tool.md
T
Tianyi Cui cd17f8d23a Merge refreshed docs/i18n-batch-cds-postmortem into docs/i18n-batch-rfc
# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-custom-schema-dsl.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-custom-schema-dsl.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-event-sourced-sessions.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-event-sourced-sessions.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-runtime-arg-validation.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-runtime-arg-validation.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-structured-error-taxonomy.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-structured-error-taxonomy.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-tool-schemas-in-prompt-assembly.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-tool-schemas-in-prompt-assembly.zh.md
#	.agents/notes/implemented/architecture/2026-06-13-capability-seams.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md
#	.agents/notes/implemented/architecture/2026-06-13-twin-llm-adapters.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-13-twin-llm-adapters.zh.md
#	.agents/notes/implemented/architecture/2026-06-14-session-persistence.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-14-session-persistence.zh.md
#	.agents/notes/implemented/architecture/2026-06-15-turn-enclosure-invariant.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-15-turn-enclosure-invariant.zh.md
#	.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.zh.md
#	.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.zh.md
#	.agents/notes/implemented/architecture/2026-06-18-session-surface.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-18-session-surface.zh.md
#	.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.zh.md
#	.agents/notes/implemented/architecture/2026-06-20-branded-ids.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-20-branded-ids.zh.md
#	.agents/notes/implemented/architecture/2026-06-20-extract-example-app-packages.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-20-extract-example-app-packages.zh.md
#	.agents/notes/implemented/architecture/2026-06-20-package-hierarchy.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-20-package-hierarchy.md
#	.agents/notes/implemented/architecture/2026-06-20-package-hierarchy.zh.md
#	.agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.zh.md
#	.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-24-web-capability-seam.zh.md
#	.agents/notes/implemented/architecture/2026-06-26-file-context-as-event-gate.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-26-file-context-as-event-gate.zh.md
#	.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.zh.md
#	.agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.zh.md
#	.agents/notes/implemented/architecture/2026-07-02-fs-per-session-cwd.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-02-fs-per-session-cwd.zh.md
#	.agents/notes/implemented/architecture/2026-07-02-result-time-applied-hunk-diffs.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-02-result-time-applied-hunk-diffs.zh.md
#	.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.zh.md
#	.agents/notes/implemented/architecture/2026-07-03-filesystem-directory-listing-seam.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-03-filesystem-directory-listing-seam.zh.md
#	.agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.zh.md
#	.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.zh.md
#	.agents/notes/implemented/architecture/2026-07-05-subagent-provider-lifecycle-events.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-05-subagent-provider-lifecycle-events.zh.md
#	.agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.zh.md
#	.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.zh.md
#	.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.zh.md
#	.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.zh.md
#	.agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.zh.md
#	.agents/notes/implemented/feature/2026-06-14-acp-multi-session.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-14-acp-multi-session.zh.md
#	.agents/notes/implemented/feature/2026-06-15-code-mode.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-15-code-mode.zh.md
#	.agents/notes/implemented/feature/2026-06-17-filesystem-tool-schemas.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-17-filesystem-tool-schemas.zh.md
#	.agents/notes/implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.zh.md
#	.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md
#	.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md
#	.agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.zh.md
#	.agents/notes/implemented/feature/2026-06-22-acp-subagent-backend.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-22-acp-subagent-backend.zh.md
#	.agents/notes/implemented/feature/2026-06-25-ask-user-question.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-25-ask-user-question.zh.md
#	.agents/notes/implemented/feature/2026-06-29-todo-write-tool.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-29-todo-write-tool.zh.md
#	.agents/notes/implemented/feature/2026-06-30-hook-bridges.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-hook-bridges.zh.md
#	.agents/notes/implemented/feature/2026-06-30-hook-protocol-lib.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-hook-protocol-lib.zh.md
#	.agents/notes/implemented/feature/2026-06-30-interception-seams.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-interception-seams.zh.md
#	.agents/notes/implemented/feature/2026-06-30-session-store-fork-api.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-session-store-fork-api.zh.md
#	.agents/notes/implemented/feature/2026-06-30-subagent-observe-enrich.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-subagent-observe-enrich.zh.md
#	.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.zh.md
#	.agents/notes/implemented/feature/2026-07-05-skill-system.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-05-skill-system.zh.md
#	.agents/notes/implemented/feature/2026-07-06-approval-seam.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-06-approval-seam.zh.md
#	.agents/notes/implemented/feature/2026-07-06-explicit-tool-order.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-06-explicit-tool-order.zh.md
#	.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md
#	.agents/notes/implemented/feature/2026-07-07-mcp-client-plugin.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-07-mcp-client-plugin.zh.md
#	.agents/notes/implemented/feature/2026-07-07-session-prefix.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-07-session-prefix.zh.md
#	.agents/notes/implemented/feature/2026-07-08-repeat-tool-guard.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-08-repeat-tool-guard.zh.md
#	.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.zh.md
#	.agents/notes/implemented/feature/2026-07-10-session-query-service.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-10-session-query-service.zh.md
#	.agents/notes/implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.zh.md
#	.agents/notes/implemented/process/2026-06-11-doc-sync-enforcement.i18n.yaml
#	.agents/notes/implemented/process/2026-06-11-doc-sync-enforcement.zh.md
#	.agents/notes/implemented/process/2026-06-11-quality-gates.i18n.yaml
#	.agents/notes/implemented/process/2026-06-11-quality-gates.md
#	.agents/notes/implemented/process/2026-06-11-quality-gates.zh.md
#	.agents/notes/implemented/process/2026-06-11-tsdown-over-dumble.i18n.yaml
#	.agents/notes/implemented/process/2026-06-11-tsdown-over-dumble.zh.md
#	.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.i18n.yaml
#	.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.zh.md
#	.agents/notes/implemented/process/2026-06-16-pnpm-over-yarn.i18n.yaml
#	.agents/notes/implemented/process/2026-06-16-pnpm-over-yarn.zh.md
#	.agents/notes/implemented/process/2026-06-17-ts-build-config.i18n.yaml
#	.agents/notes/implemented/process/2026-06-17-ts-build-config.zh.md
#	.agents/notes/implemented/process/2026-06-18-markdown-cross-link-lint.i18n.yaml
#	.agents/notes/implemented/process/2026-06-18-markdown-cross-link-lint.zh.md
#	.agents/notes/implemented/process/2026-06-20-core-data-structures-catalog.i18n.yaml
#	.agents/notes/implemented/process/2026-06-20-core-data-structures-catalog.zh.md
#	.agents/notes/implemented/process/2026-06-20-generated-cordis-catalog.i18n.yaml
#	.agents/notes/implemented/process/2026-06-20-generated-cordis-catalog.zh.md
#	.agents/notes/implemented/process/2026-06-20-rfc-classification.i18n.yaml
#	.agents/notes/implemented/process/2026-06-20-rfc-classification.zh.md
#	.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.i18n.yaml
#	.agents/notes/implemented/process/2026-07-02-tool-schema-catalog.zh.md
#	.agents/notes/implemented/process/2026-07-03-documentation-graph-atlas.i18n.yaml
#	.agents/notes/implemented/process/2026-07-03-documentation-graph-atlas.zh.md
#	.agents/notes/implemented/process/2026-07-04-cordis-jsdoc-completeness-gate.i18n.yaml
#	.agents/notes/implemented/process/2026-07-04-cordis-jsdoc-completeness-gate.zh.md
#	.agents/notes/implemented/process/2026-07-04-doc-tiers-and-budgets.i18n.yaml
#	.agents/notes/implemented/process/2026-07-04-doc-tiers-and-budgets.zh.md
#	.agents/notes/implemented/process/2026-07-04-generate-rfc-index-tables.i18n.yaml
#	.agents/notes/implemented/process/2026-07-04-generate-rfc-index-tables.zh.md
#	.agents/notes/implemented/process/2026-07-04-persistence-log-catalog.i18n.yaml
#	.agents/notes/implemented/process/2026-07-04-persistence-log-catalog.zh.md
#	.agents/notes/implemented/process/2026-07-05-uniform-rfc-format.i18n.yaml
#	.agents/notes/implemented/process/2026-07-05-uniform-rfc-format.zh.md
#	.agents/notes/implemented/process/2026-07-06-export-surface-jsdoc-gate.i18n.yaml
#	.agents/notes/implemented/process/2026-07-06-export-surface-jsdoc-gate.zh.md
#	.agents/notes/implemented/process/2026-07-06-generated-config-catalog.i18n.yaml
#	.agents/notes/implemented/process/2026-07-06-generated-config-catalog.zh.md
#	.agents/notes/implemented/process/2026-07-06-node-engine-floor.i18n.yaml
#	.agents/notes/implemented/process/2026-07-06-node-engine-floor.zh.md
#	.agents/notes/implemented/process/2026-07-06-parallel-github-ci-gates.i18n.yaml
#	.agents/notes/implemented/process/2026-07-06-parallel-github-ci-gates.zh.md
#	.agents/notes/implemented/process/2026-07-06-parallel-pre-push-gates.i18n.yaml
#	.agents/notes/implemented/process/2026-07-06-parallel-pre-push-gates.zh.md
#	.agents/notes/implemented/process/2026-07-10-readme-known-limitations-gate.i18n.yaml
#	.agents/notes/implemented/process/2026-07-10-readme-known-limitations-gate.zh.md
#	.agents/notes/implemented/process/2026-07-12-package-model-experience-contract.i18n.yaml
#	.agents/notes/implemented/process/2026-07-12-package-model-experience-contract.zh.md
#	.agents/notes/implemented/simplification/2026-06-19-drop-mutable-session-summary.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-19-drop-mutable-session-summary.zh.md
#	.agents/notes/implemented/simplification/2026-06-20-collapse-trace-only-session-events.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-20-collapse-trace-only-session-events.zh.md
#	.agents/notes/implemented/simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.zh.md
#	.agents/notes/implemented/simplification/2026-06-20-drop-unconsumed-llm-assembled-surfaces.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-20-drop-unconsumed-llm-assembled-surfaces.zh.md
#	.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.md
#	.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.zh.md
#	.agents/notes/implemented/simplification/2026-06-20-public-agent-stop-surface.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-20-public-agent-stop-surface.zh.md
#	.agents/notes/implemented/simplification/2026-06-20-remove-agent-boundary-mirror-events.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-20-remove-agent-boundary-mirror-events.zh.md
#	.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.zh.md
#	.agents/notes/implemented/simplification/2026-07-02-remove-stream-chunk-mirror.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-02-remove-stream-chunk-mirror.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-drop-image-content-block.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-drop-image-content-block.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-drop-inert-request-knobs.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-drop-inert-request-knobs.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-drop-unconsumed-web-observation-surface.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-drop-unconsumed-web-observation-surface.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-fold-stdio-ui-helper.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-fold-stdio-ui-helper.md
#	.agents/notes/implemented/simplification/2026-07-04-fold-stdio-ui-helper.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-prune-write-only-fs-surface.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-prune-write-only-fs-surface.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-remove-agent-steering-mirror.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-remove-agent-steering-mirror.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-share-app-bin-boot-glue.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-share-app-bin-boot-glue.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-tighten-hook-protocol-contract.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-tighten-hook-protocol-contract.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-trim-acp-bridge-unreachable-surface.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-04-trim-acp-bridge-unreachable-surface.zh.md
#	.agents/notes/implemented/simplification/2026-07-12-drop-unconsumed-skill-provider-events.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-12-drop-unconsumed-skill-provider-events.zh.md
#	.agents/notes/implemented/simplification/2026-07-12-prune-unused-web-seam-fields.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-12-prune-unused-web-seam-fields.zh.md
#	.agents/notes/implemented/testing/2026-06-11-property-based-testing.i18n.yaml
#	.agents/notes/implemented/testing/2026-06-11-property-based-testing.zh.md
#	.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.i18n.yaml
#	.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.zh.md
#	.agents/notes/implemented/testing/2026-06-19-real-api-e2e-ci.i18n.yaml
#	.agents/notes/implemented/testing/2026-06-19-real-api-e2e-ci.zh.md
#	.agents/notes/implemented/testing/2026-06-20-remove-redundant-snapshot-log-goldens.i18n.yaml
#	.agents/notes/implemented/testing/2026-06-20-remove-redundant-snapshot-log-goldens.zh.md
#	.agents/notes/implemented/testing/2026-06-22-fork-child-replay-seed-boundary.i18n.yaml
#	.agents/notes/implemented/testing/2026-06-22-fork-child-replay-seed-boundary.zh.md
#	.agents/notes/implemented/testing/2026-06-22-fork-snapshot-scenarios.i18n.yaml
#	.agents/notes/implemented/testing/2026-06-22-fork-snapshot-scenarios.zh.md
#	.agents/notes/implemented/testing/2026-06-22-subagent-snapshot-replay.i18n.yaml
#	.agents/notes/implemented/testing/2026-06-22-subagent-snapshot-replay.zh.md
#	.agents/notes/implemented/testing/2026-07-04-hook-snapshot-matrix.i18n.yaml
#	.agents/notes/implemented/testing/2026-07-04-hook-snapshot-matrix.zh.md
#	.agents/notes/implemented/testing/2026-07-04-single-source-acp-replay-config.i18n.yaml
#	.agents/notes/implemented/testing/2026-07-04-single-source-acp-replay-config.zh.md
#	.agents/notes/implemented/testing/2026-07-06-pin-request-header-content-in-one-scenario.i18n.yaml
#	.agents/notes/implemented/testing/2026-07-06-pin-request-header-content-in-one-scenario.zh.md
#	.agents/notes/implemented/testing/2026-07-08-shared-acp-snapshot-package.i18n.yaml
#	.agents/notes/implemented/testing/2026-07-08-shared-acp-snapshot-package.zh.md
#	.agents/notes/proposed/architecture/2026-06-16-typed-event-schemas.i18n.yaml
#	.agents/notes/proposed/architecture/2026-06-16-typed-event-schemas.zh.md
#	.agents/notes/proposed/architecture/2026-06-20-generic-long-running-tool-runtime.i18n.yaml
#	.agents/notes/proposed/architecture/2026-06-20-generic-long-running-tool-runtime.zh.md
#	.agents/notes/proposed/feature/2026-06-30-pre-tool-input-rewrite.i18n.yaml
#	.agents/notes/proposed/feature/2026-06-30-pre-tool-input-rewrite.zh.md
#	.agents/notes/proposed/feature/2026-07-07-claude-code-and-codex-subagent-backends.i18n.yaml
#	.agents/notes/proposed/feature/2026-07-07-claude-code-and-codex-subagent-backends.zh.md
#	.agents/notes/proposed/feature/2026-07-08-interactive-side-sessions.i18n.yaml
#	.agents/notes/proposed/feature/2026-07-08-interactive-side-sessions.zh.md
#	.agents/notes/proposed/feature/2026-07-10-sqlite-session-query-provider.i18n.yaml
#	.agents/notes/proposed/feature/2026-07-10-sqlite-session-query-provider.zh.md
#	.agents/notes/proposed/feature/2026-07-13-stream-workflow-progress-through-tool-calls.i18n.yaml
#	.agents/notes/proposed/feature/2026-07-13-stream-workflow-progress-through-tool-calls.zh.md
#	.agents/notes/proposed/process/2026-06-11-api-extractor-reports.i18n.yaml
#	.agents/notes/proposed/process/2026-06-11-api-extractor-reports.md
#	.agents/notes/proposed/process/2026-06-11-api-extractor-reports.zh.md
#	.agents/notes/proposed/process/2026-06-11-architectural-conformance.i18n.yaml
#	.agents/notes/proposed/process/2026-06-11-architectural-conformance.zh.md
#	.agents/notes/proposed/process/2026-06-11-supply-chain-and-vendor-drift.i18n.yaml
#	.agents/notes/proposed/process/2026-06-11-supply-chain-and-vendor-drift.zh.md
#	.agents/notes/proposed/process/2026-06-20-discover-package-inventory.i18n.yaml
#	.agents/notes/proposed/process/2026-06-20-discover-package-inventory.zh.md
#	.agents/notes/proposed/simplification/2026-06-20-unify-agent-and-session-id.i18n.yaml
#	.agents/notes/proposed/simplification/2026-06-20-unify-agent-and-session-id.zh.md
#	.agents/notes/proposed/simplification/2026-07-04-prune-dead-core-spine-surface.i18n.yaml
#	.agents/notes/proposed/simplification/2026-07-04-prune-dead-core-spine-surface.zh.md
#	.agents/notes/proposed/simplification/2026-07-12-simplify-session-log-representation.i18n.yaml
#	.agents/notes/proposed/simplification/2026-07-12-simplify-session-log-representation.zh.md
#	.agents/notes/proposed/testing/2026-06-11-deterministic-and-stress-testing.i18n.yaml
#	.agents/notes/proposed/testing/2026-06-11-deterministic-and-stress-testing.zh.md
#	.agents/notes/proposed/testing/2026-06-11-mutation-testing.i18n.yaml
#	.agents/notes/proposed/testing/2026-06-11-mutation-testing.zh.md
#	.agents/notes/rejected/architecture/2026-06-11-immutable-public-surfaces.i18n.yaml
#	.agents/notes/rejected/architecture/2026-06-11-immutable-public-surfaces.zh.md
#	.agents/notes/rejected/architecture/2026-06-20-providerless-example-base.i18n.yaml
#	.agents/notes/rejected/architecture/2026-06-20-providerless-example-base.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-assembled-assistant-messages-only.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-assembled-assistant-messages-only.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-drop-acp-session-load.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-drop-acp-session-load.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-drop-acp-terminal-meta.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-drop-acp-terminal-meta.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-drop-bash-output-spill-files.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-drop-bash-output-spill-files.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-drop-durable-step-boundaries.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-drop-durable-step-boundaries.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-drop-unused-session-lineage.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-drop-unused-session-lineage.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-fold-session-persistence-interface.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-fold-session-persistence-interface.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-generic-tool-rendering.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-generic-tool-rendering.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-retire-mid-turn-steering.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-retire-mid-turn-steering.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-single-session-acp-bridge.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-single-session-acp-bridge.zh.md
#	.agents/notes/rejected/simplification/2026-06-20-truncate-interrupted-turns.i18n.yaml
#	.agents/notes/rejected/simplification/2026-06-20-truncate-interrupted-turns.zh.md
#	.agents/notes/rejected/simplification/2026-07-04-prune-unimplemented-subagent-vocabulary.i18n.yaml
#	.agents/notes/rejected/simplification/2026-07-04-prune-unimplemented-subagent-vocabulary.zh.md
#	.agents/notes/rejected/simplification/2026-07-12-collapse-workflow-to-foreground-core.i18n.yaml
#	.agents/notes/rejected/simplification/2026-07-12-collapse-workflow-to-foreground-core.zh.md
#	.agents/notes/rejected/simplification/2026-07-12-prune-unused-skill-registry-surface.i18n.yaml
#	.agents/notes/rejected/simplification/2026-07-12-prune-unused-skill-registry-surface.zh.md
#	docs/rfc/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.md
#	docs/rfc/implemented/architecture/2026-06-18-session-surface.md
#	docs/rfc/implemented/architecture/2026-06-20-branded-ids.md
#	docs/rfc/implemented/architecture/2026-07-02-fs-per-session-cwd.md
#	docs/rfc/implemented/feature/2026-06-18-compaction-capability-seam.md
#	docs/rfc/implemented/feature/2026-07-07-session-prefix.md
#	docs/rfc/implemented/process/2026-06-20-rfc-classification.md
#	docs/rfc/implemented/process/2026-07-04-generate-rfc-index-tables.md
#	docs/rfc/implemented/process/2026-07-05-uniform-rfc-format.md
#	docs/rfc/implemented/process/2026-07-06-parallel-github-ci-gates.md
#	docs/rfc/implemented/process/2026-07-06-parallel-pre-push-gates.md
#	docs/rfc/implemented/process/2026-07-12-package-model-experience-contract.md
#	docs/rfc/implemented/simplification/2026-06-20-remove-agent-boundary-mirror-events.md
#	docs/rfc/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md
#	docs/rfc/implemented/testing/2026-06-20-remove-redundant-snapshot-log-goldens.md
#	docs/rfc/implemented/testing/2026-07-08-shared-acp-snapshot-package.md
#	docs/rfc/proposed/architecture/2026-06-20-generic-long-running-tool-runtime.md
#	docs/rfc/proposed/simplification/2026-06-20-unify-agent-and-session-id.md
#	docs/rfc/proposed/simplification/2026-07-12-simplify-session-log-representation.md
#	docs/rfc/rejected/simplification/2026-07-04-prune-unimplemented-subagent-vocabulary.md
#	scripts/translation-pairing.manifest.json
2026-07-22 23:07:14 +08:00

65 lines
7.0 KiB
Markdown

# Agent Note: The `todo_write` tool — model task list as event-sourced session state
Status: implemented
English | [中文](2026-06-29-todo-write-tool.zh.md)
## Problem
The harness gives the model bash and subagent tools but no way to record a structured task list. A todo list serves two co-equal purposes: it steers the model to plan multi-step work and keep the active task unambiguous (at most one active, exactly one while work remains), and it gives the human a live progress checklist. The ACP protocol has a native `plan` sessionUpdate that editors (Zed) already render, but the bridge never emitted one. Every reference coding agent surveyed (claude-code, opencode, codex, oh-my-pi, pi) ships some form of this; the harness had nothing.
## Decision
Add a model-facing `todo_write(todos: [{ content, status }])` tool whose whole-list state lives on the event-sourced session log as a new `todo/write` `SessionEventMap` variant. Both the stdio UI and the ACP bridge render off the existing `session/event` — the ACP bridge maps the list to a `plan` sessionUpdate.
### Whole-list replace, three-state status
The model sends the ENTIRE list every call; the new list replaces the old (last-write-wins on replay). This is the shape claude-code V1, opencode, and codex `update_plan` all use, and the shape the model is most trained on — no per-item ids, no delta protocol. `status` is exactly `pending | in_progress | completed`: the same triple as codex `update_plan` and, crucially, **identical to the ACP `PlanEntryStatus`**, so the bridge maps it 1:1 with no lossy translation.
### State on the session log, not a service
The list is appended as a `todo/write` event carrying the full `{ todos }` snapshot. The harness is event-sourced — the LLM history, tool calls, and turn structure all live on the log — so the todo list lives there too. This buys durability, replay, and `session/load` reconstruction for free: a reopened session re-derives the current list (the last `todo/write`) and the ACP bridge re-emits the `plan` on load, with no separate persistence backend, no in-memory service to rehydrate, and no extra wiring. An in-memory `ctx.todos` service would have had to reinvent all of that.
### NOT a surface event
`todo/write` is deliberately excluded from `SurfaceEventType`. The surface is the projection that produces the LLM message history (`deriveMessages()`); a todo write produces no conversation message. So it carries no `surfaceOp`, never joins the ordered surface, and never reaches `deriveMessages()` — it is durable, replayable *UI* state that travels alongside the conversation without being part of it. (The dev-mode invariants still require it to sit inside an open turn, which it always does: it is appended mid-step during a tool call.)
### Priority synthesized only at the ACP boundary
ACP's `PlanEntry` requires `content` + `priority` + `status`, but a `TodoItem` has no priority — the model never reasons about it. Rather than burden the schema with a field the model must always supply, the bridge synthesizes a constant `priority: 'medium'` on every entry when it builds the `plan`. Priority is an ACP wire requirement, not a harness concept, so it lives at exactly the boundary that needs it.
### Dropped vs claude-code V1: `activeForm`, id, priority
claude-code V1's item is `{ content, status, activeForm }`; later (V2) it grew ids, dependencies, and ownership — but only to support agent *swarms* (disk-backed, lock-guarded, per-item mutation). This tool keeps the item at the minimum: `{ content, status }`. No `activeForm` (the present-continuous label) — the UI shows `content`; no id — whole-list replace needs no stable identity; no priority — see above. Each dropped field is one less thing the model must produce on every call.
### Single owner — no swarm machinery (YAGNI)
Each list belongs to the calling agent session, and non-agent calls are rejected. There is no shared scope, resolver, or delta protocol. Cross-agent lists would require per-item log deltas and explicit scope selection, so they remain a separate future design.
### Validation: the cheap middle
The schema enforces type/required/enum. Beyond that, `execute` rejects empty or duplicate `content` and more than one `in_progress` task. claude-code leaves single-in-progress to the prompt; oh-my-pi enforces it in code. We take the middle: enforce the cheap invariants that make a plan *coherent* (no blank tasks, no dupes, at most one active), but leave ordering and the discipline of keeping the list current to the model via the tool description. A rejected write returns an `isError` result so the model self-corrects.
## Why no cordis-catalog entry / no `@mode`
`todo/write` is a member of `SessionEventMap`, not a first-class cordis `interface Events` event. The catalog generator (`scripts/gen-cordis-catalog.ts`) scans `interface Events` declarations; a `SessionEventMap` variant rides the existing `session/event` emit and produces no new catalog row. So it carries no `@mode` tag (which the generator requires only on `interface Events` members) — adding one would be meaningless.
## Testing
Four tiers, designed up front:
- **Unit** — the session event (append/snapshot-clone/last-write-wins/not-on-surface); the tool (schema shape, arg validation via the real `ctx.tools.execute`, value validation, the event append + replacement, no-agent rejection, `presentCall`, HMR-safety); the ACP `todosToPlan` mapping; the stdio render arm.
- **Real-Loader path** — the plugin run through `Loader.unwrapExports`, asserting the namespace export shape survives (it HAS `inject`, so a stray default would crash at load — postmortem/0001).
- **Full-loop integration** — a scripted mock model calls `todo_write` through the real agent loop; the `todo/write` event lands and a second call replaces it.
- **`session/load` replay** — a persisted `todo/write` re-emits the `plan` update when a fresh ACP bridge loads the session.
- **With-key e2e + snapshot** — a real prompt induces a `todo_write`; the snapshot expected output gains the `plan` notification and the log event.
## Alternatives considered
- **In-memory `ctx.todos` service** — would reinvent durability, replay, and `session/load` reconstruction the log gives for free.
- **Per-item delta protocol** — only needed for a shared multi-owner list, which is out of scope; whole-list replace is simpler and matches the references.
- **Tool in `core/`** — `todo_write` is an extension tool registering on `ctx.tools`, not part of the spine; it lives in its own `packages/todo/` group like other tool families.
## Consequences
The todo list is durable, replayable session state: a persisted `todo/write` re-emits the editor's `plan` update on `session/load`, and the log — not plugin memory — is the single source of truth. Whole-list replace means one tool call per update with last-write-wins; there is no delta protocol to reconcile. The event stays off the surface, so a todo update never perturbs the derived model history — the model sees only its own tool call and result.