mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Remove generated Agent Note index
This commit is contained in:
@@ -1,248 +0,0 @@
|
|||||||
# Agent Note index
|
|
||||||
|
|
||||||
Generated by `pnpm run gen-agent-note-index` from the Agent Note tree — never edit by hand; `verify-agent-note-classification` fails when this file is stale. The curated front door — layout, classification, when to write one, and the in-file format — is [README.md](README.md).
|
|
||||||
|
|
||||||
## Proposed
|
|
||||||
|
|
||||||
### Feature
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Pre-tool input rewrite — a consistent design](proposed/feature/2026-06-30-pre-tool-input-rewrite.md) | 2026-06-30 |
|
|
||||||
| [Recallable compaction — index checkpoints, a state checkpoint, and in-session history recall](proposed/feature/2026-07-06-recallable-compaction.md) | 2026-07-06 |
|
|
||||||
| [Claude Code and Codex subagent backends (out-of-process delegation to external coding agents)](proposed/feature/2026-07-07-claude-code-and-codex-subagent-backends.md) | 2026-07-07 |
|
|
||||||
| [Interactive side sessions and merge-back](proposed/feature/2026-07-08-interactive-side-sessions.md) | 2026-07-08 |
|
|
||||||
| [SQLite FTS5 session search](proposed/feature/2026-07-10-sqlite-session-query-provider.md) | 2026-07-10 |
|
|
||||||
| [Stream workflow progress through tool calls](proposed/feature/2026-07-13-stream-workflow-progress-through-tool-calls.md) | 2026-07-13 |
|
|
||||||
| [Developer-owned SDK projects](proposed/feature/2026-07-14-sdk-developer-projects.md) | 2026-07-14 |
|
|
||||||
| [SDK follow-up capabilities](proposed/feature/2026-07-17-sdk-follow-up-capabilities.md) | 2026-07-17 |
|
|
||||||
|
|
||||||
### Simplification
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Prune dead public and result surface](proposed/simplification/2026-07-04-prune-dead-core-spine-surface.md) | 2026-07-04 |
|
|
||||||
| [Make JSON-RPC completion and transport directional](proposed/simplification/2026-07-19-make-jsonrpc-directional.md) | 2026-07-19 |
|
|
||||||
|
|
||||||
### Architecture
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Runtime schemas for the event vocabulary (Zod vs the merge-extensible-map pattern)](proposed/architecture/2026-06-16-typed-event-schemas.md) | 2026-06-16 |
|
|
||||||
| [SDK project editing architecture](proposed/architecture/2026-07-15-sdk-project-editing-architecture.md) | 2026-07-15 |
|
|
||||||
|
|
||||||
### Process
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [API extractor reports](proposed/process/2026-06-11-api-extractor-reports.md) | 2026-06-11 |
|
|
||||||
| [Architectural conformance — dependency rules and the adapter kit](proposed/process/2026-06-11-architectural-conformance.md) | 2026-06-11 |
|
|
||||||
| [Supply chain checks and vendor drift verification](proposed/process/2026-06-11-supply-chain-and-vendor-drift.md) | 2026-06-11 |
|
|
||||||
| [Discover package inventories instead of maintaining static lists](proposed/process/2026-06-20-discover-package-inventory.md) | 2026-06-20 |
|
|
||||||
| [Periodic human-review maintenance for dsh-code-review](proposed/process/2026-07-13-human-review-skill-maintenance.md) | 2026-07-13 |
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Deterministic tests, the replay invariant fixture, and race stress](proposed/testing/2026-06-11-deterministic-and-stress-testing.md) | 2026-06-11 |
|
|
||||||
| [Mutation testing as the coverage counterweight](proposed/testing/2026-06-11-mutation-testing.md) | 2026-06-11 |
|
|
||||||
|
|
||||||
## Implemented
|
|
||||||
|
|
||||||
### Feature
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Agent Client Protocol (ACP) support — drive the coding agent from external editors](implemented/feature/2026-06-14-acp-agent-client-protocol.md) | 2026-06-14 |
|
|
||||||
| [Multiplex concurrent ACP sessions over one connection](implemented/feature/2026-06-14-acp-multi-session.md) | 2026-06-14 |
|
|
||||||
| [Code Mode — the model writes TypeScript against the tool registry](implemented/feature/2026-06-15-code-mode.md) | 2026-06-15 |
|
|
||||||
| [Filesystem tool schemas — model-facing read/write/edit shapes](implemented/feature/2026-06-17-filesystem-tool-schemas.md) | 2026-06-17 |
|
|
||||||
| [Rich ACP bash rendering — the terminal card via the `_meta` convention](implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.md) | 2026-06-18 |
|
|
||||||
| [Compaction as a capability seam (abstract contract + basic backend)](implemented/feature/2026-06-18-compaction-capability-seam.md) | 2026-06-18 |
|
|
||||||
| [Subagent capability seam](implemented/feature/2026-06-21-subagent-capability-seam.md) | 2026-06-21 |
|
|
||||||
| [ACP subagent backend (out-of-process delegation)](implemented/feature/2026-06-22-acp-subagent-backend.md) | 2026-06-22 |
|
|
||||||
| [Workspace context instruction files](implemented/feature/2026-06-24-workspace-context.md) | 2026-06-24 |
|
|
||||||
| [Ask-user question capability](implemented/feature/2026-06-25-ask-user-question.md) | 2026-06-25 |
|
|
||||||
| [The `todo_write` tool — model task list as event-sourced session state](implemented/feature/2026-06-29-todo-write-tool.md) | 2026-06-29 |
|
|
||||||
| [dsh-hooks-claude + dsh-hooks-codex — the Claude Code / Codex hook bridges](implemented/feature/2026-06-30-hook-bridges.md) | 2026-06-30 |
|
|
||||||
| [dsh-hook-protocol — the shared Claude Code / Codex hook wire-protocol core](implemented/feature/2026-06-30-hook-protocol-lib.md) | 2026-06-30 |
|
|
||||||
| [Interception seams — the typed-Decision surface a hook programs against](implemented/feature/2026-06-30-interception-seams.md) | 2026-06-30 |
|
|
||||||
| [SessionStore fork API](implemented/feature/2026-06-30-session-store-fork-api.md) | 2026-06-30 |
|
|
||||||
| [Subagent lifecycle enrichment — lastAssistantMessage (observe-only)](implemented/feature/2026-06-30-subagent-observe-enrich.md) | 2026-06-30 |
|
|
||||||
| [Dynamic workflows — a script-driven multi-agent orchestration seam](implemented/feature/2026-07-05-dynamic-workflows.md) | 2026-07-05 |
|
|
||||||
| [Skill system — progressive disclosure instructions for agents](implemented/feature/2026-07-05-skill-system.md) | 2026-07-05 |
|
|
||||||
| [The approval seam — one-shot permission decisions over a waterfall of answerers](implemented/feature/2026-07-06-approval-seam.md) | 2026-07-06 |
|
|
||||||
| [Explicit model-facing tool order](implemented/feature/2026-07-06-explicit-tool-order.md) | 2026-07-06 |
|
|
||||||
| [The subprocess sandbox — confinement seam, native runners, escalation, and per-session modes](implemented/feature/2026-07-06-sandbox.md) | 2026-07-06 |
|
|
||||||
| [MCP client plugin — connect to external MCP servers and bridge their tools](implemented/feature/2026-07-07-mcp-client-plugin.md) | 2026-07-07 |
|
|
||||||
| [The session prefix — request-only messages in front of the derived history](implemented/feature/2026-07-07-session-prefix.md) | 2026-07-07 |
|
|
||||||
| [Background subagent tasks](implemented/feature/2026-07-08-background-subagent-tasks.md) | 2026-07-08 |
|
|
||||||
| [Repeat-tool-call guard plugin](implemented/feature/2026-07-08-repeat-tool-guard.md) | 2026-07-08 |
|
|
||||||
| [The self-referential cordis toolset](implemented/feature/2026-07-08-self-referential-cordis-toolset.md) | 2026-07-08 |
|
|
||||||
| [Bash-backed grep and glob discovery tools](implemented/feature/2026-07-09-bash-backed-grep-glob-discovery.md) | 2026-07-09 |
|
|
||||||
| [Expose agent session identity and JSONL location to tools and hooks](implemented/feature/2026-07-10-agent-session-identity-and-log-location.md) | 2026-07-10 |
|
|
||||||
| [Parallel tool-call execution by per-call safety](implemented/feature/2026-07-10-parallel-tool-call-execution.md) | 2026-07-10 |
|
|
||||||
| [Exact session query service](implemented/feature/2026-07-10-session-query-service.md) | 2026-07-10 |
|
|
||||||
| [Configure subagent persona, tool visibility, and depth](implemented/feature/2026-07-12-subagent-persona-tool-filter-and-depth.md) | 2026-07-12 |
|
|
||||||
| [Session query relationship tracing](implemented/feature/2026-07-13-session-query-tracing.md) | 2026-07-13 |
|
|
||||||
| [Optional time-context plugin](implemented/feature/2026-07-14-time-context-plugin.md) | 2026-07-14 |
|
|
||||||
| [Durable per-step time context](implemented/feature/2026-07-16-durable-per-step-time-context.md) | 2026-07-16 |
|
|
||||||
| [Dedicated full-screen TUI front door](implemented/feature/2026-07-17-dedicated-full-screen-tui-front-door.md) | 2026-07-17 |
|
|
||||||
|
|
||||||
### Simplification
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Drop the mutable session summary](implemented/simplification/2026-06-19-drop-mutable-session-summary.md) | 2026-06-19 |
|
|
||||||
| [Fold trace-only session facts into load-bearing events](implemented/simplification/2026-06-20-collapse-trace-only-session-events.md) | 2026-06-20 |
|
|
||||||
| [Drop the unconsumed `llm/adapter-change` event](implemented/simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.md) | 2026-06-20 |
|
|
||||||
| [Drop unconsumed assembled LLM convenience surfaces](implemented/simplification/2026-06-20-drop-unconsumed-llm-assembled-surfaces.md) | 2026-06-20 |
|
|
||||||
| [Prune dead methods from the persistence seam](implemented/simplification/2026-06-20-prune-dead-seam-methods.md) | 2026-06-20 |
|
|
||||||
| [Keep one public stop primitive](implemented/simplification/2026-06-20-public-agent-stop-surface.md) | 2026-06-20 |
|
|
||||||
| [Stop mirroring durable boundaries as agent events](implemented/simplification/2026-06-20-remove-agent-boundary-mirror-events.md) | 2026-06-20 |
|
|
||||||
| [Unify the agent id and the session id](implemented/simplification/2026-06-20-unify-agent-and-session-id.md) | 2026-06-20 |
|
|
||||||
| [Split the filesystem seam — provider text mutations plus the `dsh-fs-policy` plugin](implemented/simplification/2026-06-26-fsspec-style-fs-seam.md) | 2026-06-26 |
|
|
||||||
| [Stop mirroring the token stream as an agent event](implemented/simplification/2026-07-02-remove-stream-chunk-mirror.md) | 2026-07-02 |
|
|
||||||
| [Drop the `image` content block until a path can honor it](implemented/simplification/2026-07-04-drop-image-content-block.md) | 2026-07-04 |
|
|
||||||
| [Drop `GenerateOptions.prefill` and `ToolSchema.strict` — request knobs with no working end-to-end path](implemented/simplification/2026-07-04-drop-inert-request-knobs.md) | 2026-07-04 |
|
|
||||||
| [Drop the unconsumed web observation surface — the `providers-change` event and the status methods](implemented/simplification/2026-07-04-drop-unconsumed-web-observation-surface.md) | 2026-07-04 |
|
|
||||||
| [Fold the stdio UI helper into the stdio app](implemented/simplification/2026-07-04-fold-stdio-ui-helper.md) | 2026-07-04 |
|
|
||||||
| [Prune producer-less vocabulary variants (block cache hints, the `agent` message source, the `continuation` turn trigger)](implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md) | 2026-07-04 |
|
|
||||||
| [Prune write-only fields and a dead routing knob from the fs seam](implemented/simplification/2026-07-04-prune-write-only-fs-surface.md) | 2026-07-04 |
|
|
||||||
| [Remove the `agent/steering` mirror emit](implemented/simplification/2026-07-04-remove-agent-steering-mirror.md) | 2026-07-04 |
|
|
||||||
| [Share the app bins' boot glue instead of maintaining twin copies](implemented/simplification/2026-07-04-share-app-bin-boot-glue.md) | 2026-07-04 |
|
|
||||||
| [Tighten the hook-protocol contract — dialect, discarded fields, double defaults, and lib-owned `hook/result` semantics](implemented/simplification/2026-07-04-tighten-hook-protocol-contract.md) | 2026-07-04 |
|
|
||||||
| [Trim unreachable ACP bridge surface — the branding knobs and the kind-sniffing fallback](implemented/simplification/2026-07-04-trim-acp-bridge-unreachable-surface.md) | 2026-07-04 |
|
|
||||||
| [Drop unconsumed skill provider events](implemented/simplification/2026-07-12-drop-unconsumed-skill-provider-events.md) | 2026-07-12 |
|
|
||||||
| [Prune unused web seam fields](implemented/simplification/2026-07-12-prune-unused-web-seam-fields.md) | 2026-07-12 |
|
|
||||||
| [Simplify session-log representation](implemented/simplification/2026-07-12-simplify-session-log-representation.md) | 2026-07-12 |
|
|
||||||
| [Retire the standalone subagent mock package](implemented/simplification/2026-07-19-retire-subagent-mock-package.md) | 2026-07-19 |
|
|
||||||
| [Use one surface manager per session](implemented/simplification/2026-07-19-use-one-session-surface-manager.md) | 2026-07-19 |
|
|
||||||
|
|
||||||
### Architecture
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Provider-neutral content-block vocabulary owned by dsh-llm](implemented/architecture/2026-06-11-content-block-vocabulary.md) | 2026-06-11 |
|
|
||||||
| [Custom typed tool-schema DSL instead of schemastery](implemented/architecture/2026-06-11-custom-schema-dsl.md) | 2026-06-11 |
|
|
||||||
| [Source-owned session immutability and dev-mode invariants](implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md) | 2026-06-11 |
|
|
||||||
| [Event-sourced sessions with derived message history](implemented/architecture/2026-06-11-event-sourced-sessions.md) | 2026-06-11 |
|
|
||||||
| [Microkernel — extension via Cordis event taxonomy, one concrete loop](implemented/architecture/2026-06-11-microkernel-event-taxonomy.md) | 2026-06-11 |
|
|
||||||
| [Runtime arg validation at the model boundary](implemented/architecture/2026-06-11-runtime-arg-validation.md) | 2026-06-11 |
|
|
||||||
| [Structured error taxonomy](implemented/architecture/2026-06-11-structured-error-taxonomy.md) | 2026-06-11 |
|
|
||||||
| [Tool schemas are part of the system-prompt assembly](implemented/architecture/2026-06-11-tool-schemas-in-prompt-assembly.md) | 2026-06-11 |
|
|
||||||
| [Capability seams — interface / implementation / consumer split](implemented/architecture/2026-06-13-capability-seams.md) | 2026-06-13 |
|
|
||||||
| [Two LLM adapters as a design-verification twin](implemented/architecture/2026-06-13-twin-llm-adapters.md) | 2026-06-13 |
|
|
||||||
| [Session persistence as an abstract service over the existing `SessionEvent`](implemented/architecture/2026-06-14-session-persistence.md) | 2026-06-14 |
|
|
||||||
| [Every session event is enclosed in a turn](implemented/architecture/2026-06-15-turn-enclosure-invariant.md) | 2026-06-15 |
|
|
||||||
| [Filesystem capability seam — ctx.fs, local backend, and model-facing filesystem tools](implemented/architecture/2026-06-17-filesystem-capability-seam.md) | 2026-06-17 |
|
|
||||||
| [Agent lifecycle and ownership seams](implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.md) | 2026-06-18 |
|
|
||||||
| [Session surface — an ordered projection over the event log](implemented/architecture/2026-06-18-session-surface.md) | 2026-06-18 |
|
|
||||||
| [Shared persistence write coordinator](implemented/architecture/2026-06-18-shared-persistence-write-coordinator.md) | 2026-06-18 |
|
|
||||||
| [Branded IDs everywhere they belong](implemented/architecture/2026-06-20-branded-ids.md) | 2026-06-20 |
|
|
||||||
| [Extract example apps into packages](implemented/architecture/2026-06-20-extract-example-app-packages.md) | 2026-06-20 |
|
|
||||||
| [The background task runtime (`ctx.tasks`) and generic task control tools](implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md) | 2026-06-20 |
|
|
||||||
| [Reorganize packages into a modular hierarchy](implemented/architecture/2026-06-20-package-hierarchy.md) | 2026-06-20 |
|
|
||||||
| [Mandatory `User-Agent` attribution for provider requests](implemented/architecture/2026-06-21-mandatory-app-attribution-headers.md) | 2026-06-21 |
|
|
||||||
| [Web capability seam - stable tools over multiple providers](implemented/architecture/2026-06-24-web-capability-seam.md) | 2026-06-24 |
|
|
||||||
| [Make `dsh-fs-policy` an event-gate plugin, not a method interface](implemented/architecture/2026-06-26-file-context-as-event-gate.md) | 2026-06-26 |
|
|
||||||
| [stdin + extra env on the bash seam](implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md) | 2026-06-30 |
|
|
||||||
| [Event-domain semantics — session is the fact log, agent is the live surface](implemented/architecture/2026-06-30-event-domain-semantics.md) | 2026-06-30 |
|
|
||||||
| [Resolve filesystem paths against the caller's session cwd](implemented/architecture/2026-07-02-fs-per-session-cwd.md) | 2026-07-02 |
|
|
||||||
| [Result-time applied-hunk diffs for file mutations](implemented/architecture/2026-07-02-result-time-applied-hunk-diffs.md) | 2026-07-02 |
|
|
||||||
| [Tagged render-intent union for tool-call presentation](implemented/architecture/2026-07-02-tool-render-intent-union.md) | 2026-07-02 |
|
|
||||||
| [Add direct directory listing to the filesystem seam](implemented/architecture/2026-07-03-filesystem-directory-listing-seam.md) | 2026-07-03 |
|
|
||||||
| [Prompt variables and tool-guidance ownership](implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.md) | 2026-07-05 |
|
|
||||||
| [Every LLM request is reconstructable from the session log](implemented/architecture/2026-07-05-reconstructable-requests.md) | 2026-07-05 |
|
|
||||||
| [Subagent provider-lifecycle events — `subagent/provider-added` / `subagent/provider-removed`](implemented/architecture/2026-07-05-subagent-provider-lifecycle-events.md) | 2026-07-05 |
|
|
||||||
| [A shared timeout/deadline primitive, with hard-kill left to each capability](implemented/architecture/2026-07-06-timeout-deadline-library.md) | 2026-07-06 |
|
|
||||||
| [Tool result retention library](implemented/architecture/2026-07-06-tool-result-retention-library.md) | 2026-07-06 |
|
|
||||||
| [Tool-call timeout policy as a plugin](implemented/architecture/2026-07-07-tool-call-timeout-policy.md) | 2026-07-07 |
|
|
||||||
| [The agent is a registration scope](implemented/architecture/2026-07-08-agent-scope-contexts.md) | 2026-07-08 |
|
|
||||||
| [Tool output spill policy](implemented/architecture/2026-07-08-tool-output-spill-files.md) | 2026-07-08 |
|
|
||||||
| [After-call compaction pressure and context-overflow recovery](implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md) | 2026-07-10 |
|
|
||||||
| [Single-file executable SDK runtime distribution (single-exe)](implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md) | 2026-07-10 |
|
|
||||||
| [Agent-scope runtime design and correctness](implemented/architecture/2026-07-12-agent-scope-runtime-design.md) | 2026-07-12 |
|
|
||||||
| [Provider-routed LLM adapters and a generic pi-ai backend](implemented/architecture/2026-07-14-provider-routed-llm-adapters.md) | 2026-07-14 |
|
|
||||||
| [Initiating Agent scope over AsyncLocalStorage](implemented/architecture/2026-07-15-agent-initiator-scope.md) | 2026-07-15 |
|
|
||||||
| [Advisory LLM catalogs and per-session ACP model selection](implemented/architecture/2026-07-15-llm-model-catalog-and-acp-selection.md) | 2026-07-15 |
|
|
||||||
| [Replay token meter service](implemented/architecture/2026-07-15-replay-token-meter-service.md) | 2026-07-15 |
|
|
||||||
|
|
||||||
### Process
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Doc-sync enforcement](implemented/process/2026-06-11-doc-sync-enforcement.md) | 2026-06-11 |
|
|
||||||
| [Mechanical quality gates over prose guidelines](implemented/process/2026-06-11-quality-gates.md) | 2026-06-11 |
|
|
||||||
| [tsdown for JS bundling instead of dumble](implemented/process/2026-06-11-tsdown-over-dumble.md) | 2026-06-11 |
|
|
||||||
| [Vendor Cordis as source, not npm dependencies](implemented/process/2026-06-11-vendor-cordis-as-source.md) | 2026-06-11 |
|
|
||||||
| [pnpm as the package manager instead of Yarn 4](implemented/process/2026-06-16-pnpm-over-yarn.md) | 2026-06-16 |
|
|
||||||
| [TSC-first build and one tsconfig](implemented/process/2026-06-17-ts-build-config.md) | 2026-06-17 |
|
|
||||||
| [Markdown cross-link validity linting](implemented/process/2026-06-18-markdown-cross-link-lint.md) | 2026-06-18 |
|
|
||||||
| [Classify Agent Notes by kind via path-encoded subdirectories](implemented/process/2026-06-20-agent-note-classification.md) | 2026-06-20 |
|
|
||||||
| [Core-data-structures catalog and the `ts type-equiv` drift gate](implemented/process/2026-06-20-core-data-structures-catalog.md) | 2026-06-20 |
|
|
||||||
| [Generated cordis events + services catalog](implemented/process/2026-06-20-generated-cordis-catalog.md) | 2026-06-20 |
|
|
||||||
| [Bilingual documentation via paired sibling files and a pairing gate](implemented/process/2026-07-02-bilingual-docs-and-pairing-gate.md) | 2026-07-02 |
|
|
||||||
| [Generated tool-schema catalog (boot-and-harvest)](implemented/process/2026-07-02-tool-schema-catalog.md) | 2026-07-02 |
|
|
||||||
| [Documentation graph index for maintainers and SDK users](implemented/process/2026-07-03-documentation-graph-atlas.md) | 2026-07-03 |
|
|
||||||
| [JSDoc completeness gate for the cordis surface](implemented/process/2026-07-04-cordis-jsdoc-completeness-gate.md) | 2026-07-04 |
|
|
||||||
| [Documentation tiers, budgets, and the ceiling gate](implemented/process/2026-07-04-doc-tiers-and-budgets.md) | 2026-07-04 |
|
|
||||||
| [Generate the Agent Note index tables](implemented/process/2026-07-04-generate-agent-note-index-tables.md) | 2026-07-04 |
|
|
||||||
| [Generated persistence log event catalog](implemented/process/2026-07-04-persistence-log-catalog.md) | 2026-07-04 |
|
|
||||||
| [One gated in-file format for Agent Notes](implemented/process/2026-07-05-uniform-agent-note-format.md) | 2026-07-05 |
|
|
||||||
| [Export-surface JSDoc gate](implemented/process/2026-07-06-export-surface-jsdoc-gate.md) | 2026-07-06 |
|
|
||||||
| [Generated plugin config catalog](implemented/process/2026-07-06-generated-config-catalog.md) | 2026-07-06 |
|
|
||||||
| [Raise the Node LTS engine floor to 22.19](implemented/process/2026-07-06-node-engine-floor.md) | 2026-07-06 |
|
|
||||||
| [Parallel GitHub CI gates](implemented/process/2026-07-06-parallel-github-ci-gates.md) | 2026-07-06 |
|
|
||||||
| [Parallel pre-push gates](implemented/process/2026-07-06-parallel-pre-push-gates.md) | 2026-07-06 |
|
|
||||||
| [A gated Known-Limitations section in every package README](implemented/process/2026-07-10-readme-known-limitations-gate.md) | 2026-07-10 |
|
|
||||||
| [Package Model Experience contract](implemented/process/2026-07-12-package-model-experience-contract.md) | 2026-07-12 |
|
|
||||||
| [TypeScript Program-backed semantic gates](implemented/process/2026-07-14-typescript-program-backed-semantic-gates.md) | 2026-07-14 |
|
|
||||||
| [Run CI examples from built lib](implemented/process/2026-07-17-run-ci-examples-from-built-lib.md) | 2026-07-17 |
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Property-based testing for protocol-shaped code](implemented/testing/2026-06-11-property-based-testing.md) | 2026-06-11 |
|
|
||||||
| [ACP snapshot tests — record-once / replay-deterministic](implemented/testing/2026-06-19-acp-snapshot-tests.md) | 2026-06-19 |
|
|
||||||
| [Real-API e2e in CI against the external DeepSeek API](implemented/testing/2026-06-19-real-api-e2e-ci.md) | 2026-06-19 |
|
|
||||||
| [Use `session.jsonl` as the only snapshot session-log artifact](implemented/testing/2026-06-20-remove-redundant-snapshot-log-expected-output.md) | 2026-06-20 |
|
|
||||||
| [Persist the seed boundary so fork-child replay routes correctly](implemented/testing/2026-06-22-fork-child-replay-seed-boundary.md) | 2026-06-22 |
|
|
||||||
| [Record fork and mixed spawn+fork snapshot scenarios](implemented/testing/2026-06-22-fork-snapshot-scenarios.md) | 2026-06-22 |
|
|
||||||
| [Per-session snapshot replay for nested agents](implemented/testing/2026-06-22-subagent-snapshot-replay.md) | 2026-06-22 |
|
|
||||||
| [Hook snapshot matrix — end-to-end expected outputs for both bridges](implemented/testing/2026-07-04-hook-snapshot-matrix.md) | 2026-07-04 |
|
|
||||||
| [Single-source the acp-agent replay config](implemented/testing/2026-07-04-single-source-acp-replay-config.md) | 2026-07-04 |
|
|
||||||
| [Pin request-header content in one snapshot scenario](implemented/testing/2026-07-06-pin-request-header-content-in-one-scenario.md) | 2026-07-06 |
|
|
||||||
| [Extract the ACP snapshot suite into a support package](implemented/testing/2026-07-08-shared-acp-snapshot-package.md) | 2026-07-08 |
|
|
||||||
| [Snapshot semantic terminal state for the TUI](implemented/testing/2026-07-18-tui-terminal-state-snapshots.md) | 2026-07-18 |
|
|
||||||
|
|
||||||
## Rejected
|
|
||||||
|
|
||||||
### Simplification
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Persist assembled assistant messages, not stream chunks](rejected/simplification/2026-06-20-assembled-assistant-messages-only.md) | 2026-06-20 |
|
|
||||||
| [Drop ACP session/load until resume has a product shape](rejected/simplification/2026-06-20-drop-acp-session-load.md) | 2026-06-20 |
|
|
||||||
| [Drop ACP terminal `_meta` rendering](rejected/simplification/2026-06-20-drop-acp-terminal-meta.md) | 2026-06-20 |
|
|
||||||
| [Drop bash full-output spill files](rejected/simplification/2026-06-20-drop-bash-output-spill-files.md) | 2026-06-20 |
|
|
||||||
| [Drop durable step boundary events](rejected/simplification/2026-06-20-drop-durable-step-boundaries.md) | 2026-06-20 |
|
|
||||||
| [Drop unused session lineage metadata](rejected/simplification/2026-06-20-drop-unused-session-lineage.md) | 2026-06-20 |
|
|
||||||
| [Fold the persistence interface into dsh-session](rejected/simplification/2026-06-20-fold-session-persistence-interface.md) | 2026-06-20 |
|
|
||||||
| [Collapse tool-owned UI presentation](rejected/simplification/2026-06-20-generic-tool-rendering.md) | 2026-06-20 |
|
|
||||||
| [Retire mid-turn steering](rejected/simplification/2026-06-20-retire-mid-turn-steering.md) | 2026-06-20 |
|
|
||||||
| [Return the ACP bridge to one live session per connection](rejected/simplification/2026-06-20-single-session-acp-bridge.md) | 2026-06-20 |
|
|
||||||
| [Truncate interrupted final turns on load](rejected/simplification/2026-06-20-truncate-interrupted-turns.md) | 2026-06-20 |
|
|
||||||
| [Prune the unimplemented subagent seam vocabulary](rejected/simplification/2026-07-04-prune-unimplemented-subagent-vocabulary.md) | 2026-07-04 |
|
|
||||||
| [Collapse workflows to the exercised foreground core](rejected/simplification/2026-07-12-collapse-workflow-to-foreground-core.md) | 2026-07-12 |
|
|
||||||
| [Prune unused skill registry surface](rejected/simplification/2026-07-12-prune-unused-skill-registry-surface.md) | 2026-07-12 |
|
|
||||||
| [Fold the single compaction backend into its service package](rejected/simplification/2026-07-19-fold-compaction-package-split.md) | 2026-07-19 |
|
|
||||||
|
|
||||||
### Architecture
|
|
||||||
|
|
||||||
| Title | First proposed |
|
|
||||||
|---|---|
|
|
||||||
| [Deep-readonly public surfaces](rejected/architecture/2026-06-11-immutable-public-surfaces.md) | 2026-06-11 |
|
|
||||||
| [Make the shared example base providerless](rejected/architecture/2026-06-20-providerless-example-base.md) | 2026-06-20 |
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Agent Notes
|
# Agent Notes
|
||||||
|
|
||||||
One kind of design doc lives here. An **Agent Note** records a decision or proposal that shapes this codebase — the *why* and *what we gave up*, the parts code and docs can't carry. The full list is the generated [INDEX.md](INDEX.md); this file is the contract — where Agent Notes live, when to write one, and [the in-file format](#the-file-format).
|
One kind of design doc lives here. An **Agent Note** records a decision or proposal that shapes this codebase — the *why* and *what we gave up*, the parts code and docs can't carry. This file is the front door and contract: where Agent Notes live, when to write one, and [the in-file format](#the-file-format).
|
||||||
|
|
||||||
## Layout and naming
|
## Layout and naming
|
||||||
|
|
||||||
@@ -14,9 +14,11 @@ Every Agent Note has two axes, both encoded in its **path** — `{lifecycle}/{cl
|
|||||||
|
|
||||||
The date in the filename is when the topic was **first proposed** (per git history). Cross-references between Agent Notes use relative markdown links (`[topic](../../implemented/architecture/2026-…-….md)`) — never bare prose or numbers — so they are mechanically checkable and survive moves between folders.
|
The date in the filename is when the topic was **first proposed** (per git history). Cross-references between Agent Notes use relative markdown links (`[topic](../../implemented/architecture/2026-…-….md)`) — never bare prose or numbers — so they are mechanically checkable and survive moves between folders.
|
||||||
|
|
||||||
|
The tree is the inventory: browse its lifecycle/class folders or search the repository. Do not add a centralized `INDEX.md`; the [no-index Agent Note](implemented/process/2026-07-19-remove-generated-agent-note-index.md) owns the rationale.
|
||||||
|
|
||||||
## Classification
|
## Classification
|
||||||
|
|
||||||
Each Agent Note belongs to one path-encoded class from the closed set in `scripts/agent-note-index.ts`; the classification gate rejects other folders. [INDEX.md](INDEX.md) is generated from paths, titles, and filename dates, and its freshness is gated. Adding a class requires updating the canonical set and this section. See the [classification](implemented/process/2026-06-20-agent-note-classification.md) and [index-generation](implemented/process/2026-07-04-generate-agent-note-index-tables.md) Agent Notes.
|
Each Agent Note belongs to one path-encoded class from the closed set in `scripts/agent-note-tree.ts`; the classification gate rejects other folders. Adding a class requires updating the canonical set and this section. See the [classification Agent Note](implemented/process/2026-06-20-agent-note-classification.md).
|
||||||
|
|
||||||
| Class | What it covers |
|
| Class | What it covers |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Status: implemented
|
|||||||
|
|
||||||
## Problem
|
## Problem
|
||||||
|
|
||||||
`.agents/notes/` grouped Agent Notes by **lifecycle** only — `proposed/` / `implemented/` / `rejected/`. Nothing recorded what *kind* of decision each Agent Note was. The index was one flat list per lifecycle, with no way to scan "show me every simplification" or "every testing-strategy decision." A wave of simplification Agent Notes landing on the same day made the gap concrete: a reader skimming `proposed/` could not tell a new capability from a removal from a tooling-policy change without opening each file.
|
A lifecycle-only Agent Note tree — `proposed/` / `implemented/` / `rejected/` — does not record what *kind* of decision each file contains. A reader browsing one lifecycle cannot distinguish a new capability from a removal or a tooling-policy change without opening each file.
|
||||||
|
|
||||||
The repo's standing bias is [mechanical quality gates over prose guidelines](2026-06-11-quality-gates.md): a convention that isn't machine-checked rots. So a classification scheme here had to be enforceable, not an honor-system header.
|
The repo's standing bias is [mechanical quality gates over prose guidelines](2026-06-11-quality-gates.md): a convention that isn't machine-checked rots. So a classification scheme here had to be enforceable, not an honor-system header.
|
||||||
|
|
||||||
@@ -29,18 +29,18 @@ The `architecture` / `process` line: **architecture** is about the source we shi
|
|||||||
|
|
||||||
Both are `doc-sync` members, in the `verify-md-wrap` style (tsx ESM, verify-don't-generate, exit non-zero on the first violation):
|
Both are `doc-sync` members, in the `verify-md-wrap` style (tsx ESM, verify-don't-generate, exit non-zero on the first violation):
|
||||||
|
|
||||||
- **`scripts/verify-agent-note-classification.ts`** — the closed set and index freshness. It asserts every file under a lifecycle folder lives in a class folder from the canonical set (a loose `.md` at a lifecycle root, or an unknown class folder, fails), and that the generated [INDEX.md](../../INDEX.md) byte-matches a fresh render from the tree (see [generate the Agent Note index tables](2026-07-04-generate-agent-note-index-tables.md)). The canonical class set lives as a `const` in `scripts/agent-note-index.ts` — the machine source of truth shared with the generator — and [the README](../../README.md) documents it in prose; the class *descriptions* stay hand-written, the index is generated.
|
- **`scripts/verify-agent-note-classification.ts`** — the closed lifecycle and class sets. It asserts every file under a lifecycle folder lives in a class folder from the canonical set (a loose `.md` at a lifecycle root, or an unknown class folder, fails) and rejects a centralized `INDEX.md`. The canonical sets live in `scripts/agent-note-tree.ts`, and [the README](../../README.md) documents each class in prose.
|
||||||
- **`scripts/verify-doc-refs.ts`** — source comments that cite docs. Agent Note paths are referenced not only from Markdown but from TypeScript doc comments (root-relative prose like `.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md`). `verify-md-links` never saw those, so the reorg could have silently orphaned them. This gate scans repo-authored `.ts` under `packages/**` and `examples/**` (excluding built `lib/` and `vendor/`) for `docs/….md` tokens, resolves each root-relative, and asserts it exists. It requires the `.md` extension so extensionless prose (`docs/postmortem/0001`, `docs/architecture.md § Extending The Harness`) is left alone.
|
- **`scripts/verify-doc-refs.ts`** — source comments that cite docs. Agent Note paths are referenced not only from Markdown but from TypeScript doc comments (root-relative prose like `.agents/notes/implemented/testing/2026-06-19-acp-snapshot-tests.md`). `verify-md-links` does not see those, so a reorganization could silently orphan them. This gate scans repo-authored `.ts` under `packages/**` and `examples/**` (excluding built `lib/` and `vendor/`) for `docs/….md` and `.agents/notes/….md` tokens, resolves each root-relative path, and asserts it exists. It requires the `.md` extension so extensionless prose is left alone.
|
||||||
|
|
||||||
## Alternatives considered
|
## Alternatives considered
|
||||||
|
|
||||||
- **A `Classification:` prose line** in each file (next to `Status:`), parsed by the gate. Workable, but it duplicates into the file a fact the path can already carry, and a line can disagree with its folder. Path-encoding makes the label and its storage the same thing — there is nothing to keep in sync.
|
- **A `Classification:` prose line** in each file (next to `Status:`), parsed by the gate. Workable, but it duplicates into the file a fact the path can already carry, and a line can disagree with its folder. Path-encoding makes the label and its storage the same thing — there is nothing to keep in sync.
|
||||||
- **A `refactor` class.** It overlaps `simplification` almost entirely; the only discriminator anyone reached for was "does observable behavior change?", which `simplification` already encodes (it does not). One class, not two.
|
- **A `refactor` class.** It overlaps `simplification` almost entirely; the only discriminator anyone reached for was "does observable behavior change?", which `simplification` already encodes (it does not). One class, not two.
|
||||||
- **Auto-generating the index** from the filesystem. Rejected here to keep the index hand-written; superseded by [generate the Agent Note index tables](2026-07-04-generate-agent-note-index-tables.md) once stacked proposal waves made the hand-written tables the repo's most conflict-prone docs region — the list is now the fully generated [INDEX.md](../../INDEX.md) while the README prose stays curated.
|
- **A generated or hand-maintained corpus index.** Rejected because the lifecycle/class tree is authoritative, while a centralized inventory creates a merge hotspot without providing discovery that tree navigation or repository search cannot provide. The separate [index proposal](../../rejected/process/2026-07-04-generate-agent-note-index-tables.md) records the discarded generated shape.
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
- Every Agent Note now sits under a class folder, and the index groups by class within each lifecycle. A reader scans one heading to see all simplifications, or all testing decisions.
|
- Every Agent Note sits under a class folder. A reader can browse one folder to see all simplifications or all testing decisions within a lifecycle.
|
||||||
- Two more fast tsx scripts in the `doc-sync` chain; no new dependency (the mdast/GFM stack was already present for `verify-md-wrap`/`verify-md-links`).
|
- Two more fast tsx scripts in the `doc-sync` chain; no new dependency (the mdast/GFM stack was already present for `verify-md-wrap`/`verify-md-links`).
|
||||||
- Adding a class is a deliberate act: amend the `const` in `scripts/agent-note-index.ts` and the [Classification section](../../README.md#classification), not just `mkdir` a folder. The gate rejects an unknown folder, so an ad-hoc class can't slip in.
|
- Adding a class is a deliberate act: amend the `const` in `scripts/agent-note-tree.ts` and the [Classification section](../../README.md#classification), not just `mkdir` a folder. The gate rejects an unknown folder, so an ad-hoc class can't slip in.
|
||||||
- Source-comment doc references are now gated too — a moved or renamed doc that a `.ts` comment cites fails the pre-push hook, closing a drift class `verify-md-links` structurally could not see.
|
- Source-comment doc references are now gated too — a moved or renamed doc that a `.ts` comment cites fails the pre-push hook, closing a drift class `verify-md-links` structurally could not see.
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
# Agent Note: Generate the Agent Note index tables
|
|
||||||
|
|
||||||
Status: implemented
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
|
|
||||||
The Agent Note index's per-lifecycle/per-class tables list facts that are fully derivable: an Agent Note's path encodes lifecycle and class, its filename encodes the first-proposed date, and its H1 carries the title. A hand-maintained copy of those facts is also the repo's highest-contention docs hotspot: every proposal wave appends rows to the same few lines, so concurrent Agent Note branches conflict precisely there while agreeing everywhere else, and each conflict is resolved by hand-merging rows whose content the filesystem already knows. [The classification Agent Note](2026-06-20-agent-note-classification.md) originally kept the index hand-written for curation's sake — but the curated part of the README is the prose, and the prose never conflicts; only the mechanical tables do.
|
|
||||||
|
|
||||||
## Decision
|
|
||||||
|
|
||||||
Keep the curated prose; generate the list. The tables live in [`.agents/notes/INDEX.md`](../../INDEX.md), a **fully generated file** — the curated prose stays in README.md, which carries no index rows at all. [`scripts/agent-note-index.ts`](../../../../scripts/agent-note-index.ts) is the shared source of truth — the tree walker (owning the closed lifecycle/class sets and the structure rules, including a parseable-H1 requirement) and the renderer (rows from H1 title with any `Agent Note: ` prefix stripped, plus the filename date, sorted by date then filename, grouped as `### {Class}` sections in canonical class order). Two thin consumers share it:
|
|
||||||
|
|
||||||
- [`scripts/gen-agent-note-index.ts`](../../../../scripts/gen-agent-note-index.ts) (`pnpm run gen-agent-note-index`) rewrites INDEX.md in full from the tree.
|
|
||||||
- [`scripts/verify-agent-note-classification.ts`](../../../../scripts/verify-agent-note-classification.ts) (a `doc-sync` member) checks structure, asserts the committed INDEX.md byte-matches a fresh render — the `gen-cordis-catalog`/`verify-cordis-catalog` pattern — and rejects an index-shaped row in the curated README. Freshness subsumes the index-completeness check: a generated-from-disk table is definitionally complete and correctly headed.
|
|
||||||
|
|
||||||
Adding, moving, or deleting an Agent Note means editing only the Agent Note file and running the generator; the classification Agent Note's rejected-alternatives record carries the supersession cross-link.
|
|
||||||
|
|
||||||
## Alternatives considered
|
|
||||||
|
|
||||||
### Why not marker-delimited regions inside README.md?
|
|
||||||
|
|
||||||
The first landed shape: the generator spliced the tables into README.md between `gen-agent-note-index` marker comments, under each `## {Lifecycle}` heading. Superseded by the whole-file INDEX.md once the README also absorbed the in-file format contract ([the uniform-format Agent Note](2026-07-05-uniform-agent-note-format.md)): a front-door README hosting hundreds of generated rows dwarfed its curated prose, and splice mechanics (marker pairs, heading checks, outside-region row detection) exist only to protect curated text that a dedicated generated file simply doesn't contain.
|
|
||||||
|
|
||||||
### Why not the verifier-only model?
|
|
||||||
|
|
||||||
It catches mistakes but still makes every proposal edit a shared hotspot in a hand-maintained table, and a failed verifier is strictly more annoying than a generator for a purely mechanical row: the author has already named and placed the file; the index copy adds no information. This is the same hand-list-versus-derivation judgment the [package-inventory proposal](../../proposed/process/2026-06-20-discover-package-inventory.md) applies to tsconfig references and knip stanzas — applied to the one list that demonstrably conflicts.
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
|
|
||||||
- The generated file is explicit: its banner names the generator, there is no curated region to protect inside it, and the generator refuses to run on a structurally invalid tree.
|
|
||||||
- A malformed or missing H1 is a hard error in both the generator and the gate — the H1 is now load-bearing as the index title source.
|
|
||||||
- Concurrent Agent Note branches resolve index conflicts by rerunning the generator, never by hand-merging rows.
|
|
||||||
@@ -18,10 +18,10 @@ The whole corpus was normalized in the same change that defined the format — t
|
|||||||
- **Header-only normalization** (H1 and Status, bodies untouched) — rejected: the debt markers flagged the *body* genre split, and leaving `Context`/`Decision` beside `Problem`/`Proposal` indefinitely resolves nothing.
|
- **Header-only normalization** (H1 and Status, bodies untouched) — rejected: the debt markers flagged the *body* genre split, and leaving `Context`/`Decision` beside `Problem`/`Proposal` indefinitely resolves nothing.
|
||||||
- **No Status line** (the folder already is the status; the three newest pre-format Agent Notes (and the zh counterpart of one) omitted the line) — rejected in favor of keeping a self-describing file: the drift risk that motivated dropping it is neutralized by gating the line against the folder instead.
|
- **No Status line** (the folder already is the status; the three newest pre-format Agent Notes (and the zh counterpart of one) omitted the line) — rejected in favor of keeping a self-describing file: the drift risk that motivated dropping it is neutralized by gating the line against the folder instead.
|
||||||
- **Dated status** (`Status: implemented (accepted YYYY-MM-DD)`) — rejected: the acceptance date is narrated history the writing rules keep out of docs; the filename carries first-proposed, git carries the rest, and the gate could check a date's format but never its truth.
|
- **Dated status** (`Status: implemented (accepted YYYY-MM-DD)`) — rejected: the acceptance date is narrated history the writing rules keep out of docs; the filename carries first-proposed, git carries the rest, and the gate could check a date's format but never its truth.
|
||||||
- **A bare `# <title>` H1** — rejected: the `Agent Note: ` prefix is the corpus-majority form and self-describes the genre when a file is read outside its tree; the index generator strips it, so index rows are identical either way.
|
- **A bare `# <title>` H1** — rejected: the `Agent Note: ` prefix self-describes the genre when a file is read outside its tree, and the format gate prevents it from drifting.
|
||||||
- **`## What we give up` as the implemented closer** (the README's own phrase for what an Agent Note records) — rejected: it names only costs, and an honest consequences section records what the trade-off bought as well.
|
- **`## What we give up` as the implemented closer** (the README's own phrase for what an Agent Note records) — rejected: it names only costs, and an honest consequences section records what the trade-off bought as well.
|
||||||
- **Convention without a gate** (write the contract down, enforce by review) — rejected: the slop checklist already outlawed spec-speak in `implemented/` by convention, and nineteen files show what convention alone achieves here.
|
- **Convention without a gate** (write the contract down, enforce by review) — rejected: the slop checklist already outlawed spec-speak in `implemented/` by convention, and nineteen files show what convention alone achieves here.
|
||||||
- **A standalone `FORMAT.md` contract file** — the first landed home; folded into README.md once the generated index moved out to [INDEX.md](../../INDEX.md): with the tables gone the README regained the room, and one front door carrying layout, classification, and format beats splitting the contract across two files.
|
- **A standalone `FORMAT.md` contract file** — rejected because one front door carrying layout, classification, and format is easier to discover and maintain than two contract files.
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||||
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||||
|
# after editing either side, bring the other along and re-record with:
|
||||||
|
# pnpm run verify-translation-pairing --write
|
||||||
|
2026-07-19-remove-generated-agent-note-index.md: 27c1591b29a1ca64370de6ffadfb9c524a804ced
|
||||||
|
2026-07-19-remove-generated-agent-note-index.zh.md: 868955bc10900f784bd88066042abe24454e27b5
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Agent Note: Keep Agent Notes discoverable without a generated index
|
||||||
|
|
||||||
|
Status: implemented
|
||||||
|
|
||||||
|
English | [中文](2026-07-19-remove-generated-agent-note-index.zh.md)
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
A committed Agent Note index duplicates facts already encoded by each file's lifecycle/class path, filename date, and H1. Every branch that adds, moves, or renames an otherwise unrelated Agent Note rewrites the same generated file, making that artifact a predictable merge hotspot.
|
||||||
|
|
||||||
|
The centralized chronological list adds little discovery value beyond browsing the lifecycle/class tree or searching the repository, while its generator, renderer, command, and freshness check remain maintenance surface.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
The lifecycle/class filesystem tree is the Agent Note inventory. [README.md](../../README.md) remains the curated front door and contract, while ordinary tree navigation and repository search provide discovery.
|
||||||
|
|
||||||
|
`scripts/agent-note-tree.ts` owns the closed lifecycle/class sets and structural walker. `verify-agent-note-classification` validates that tree and rejects the legacy homes and a root `INDEX.md`; it does not render or freshness-check a centralized list.
|
||||||
|
|
||||||
|
This decision supersedes the rejected [generated-index proposal](../../rejected/process/2026-07-04-generate-agent-note-index-tables.md).
|
||||||
|
|
||||||
|
## Alternatives considered
|
||||||
|
|
||||||
|
**Keep the committed generated index and resolve conflicts by regenerating it.** Regeneration makes conflict resolution mechanical but does not prevent unrelated branches from modifying the same artifact or reduce the review noise it creates.
|
||||||
|
|
||||||
|
**Offer an uncommitted on-demand index command.** It avoids committed conflicts but preserves a renderer and command for a discovery path already served by tree navigation and repository search.
|
||||||
|
|
||||||
|
**Restore a hand-maintained index.** It has the same shared-file contention and adds completeness/order mistakes that generation avoided.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- Adding, moving, or renaming an Agent Note no longer changes a corpus-wide generated file.
|
||||||
|
- The classification gate performs less work and the documentation gate topology gains no process or stage.
|
||||||
|
- Readers give up a single chronological page and use the lifecycle/class tree or repository search instead.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Agent Note: 无需生成索引即可发现 Agent Note
|
||||||
|
|
||||||
|
Status: implemented
|
||||||
|
|
||||||
|
[English](2026-07-19-remove-generated-agent-note-index.md) | 中文
|
||||||
|
|
||||||
|
## 问题
|
||||||
|
|
||||||
|
提交到仓库的 Agent Note 索引,会重复记录每个文件的生命周期/类别路径、文件名日期和 H1 已经编码的事实。任何分支只要添加、移动或重命名彼此无关的 Agent Note,都会重写同一个生成文件,因此该产物会成为可预见的合并冲突热点。
|
||||||
|
|
||||||
|
与浏览生命周期/类别目录树或搜索仓库相比,这份集中式时间顺序清单提供的发现价值有限;但其生成器、渲染器、命令和新鲜度检查仍然构成维护负担。
|
||||||
|
|
||||||
|
## 决策
|
||||||
|
|
||||||
|
生命周期/类别文件系统目录树就是 Agent Note 清单。[README.md](../../README.md) 继续作为人工维护的入口和契约,普通的目录树浏览与仓库搜索负责内容发现。
|
||||||
|
|
||||||
|
`scripts/agent-note-tree.ts` 持有封闭的生命周期/类别集合与结构遍历器。`verify-agent-note-classification` 校验该目录树,并拒绝旧目录和根目录中的 `INDEX.md`,但不会渲染集中式清单或检查其新鲜度。
|
||||||
|
|
||||||
|
本决策取代已拒绝的[生成索引提案](../../rejected/process/2026-07-04-generate-agent-note-index-tables.md)。
|
||||||
|
|
||||||
|
## 备选方案
|
||||||
|
|
||||||
|
**保留提交到仓库的生成索引,并通过重新生成解决冲突。** 重新生成能让冲突解决过程机械化,但无法阻止无关分支修改同一产物,也不会减少由此产生的评审噪音。
|
||||||
|
|
||||||
|
**提供不提交到仓库的按需索引命令。** 这可以避免已提交文件的冲突,但仍需维护渲染器和命令,而目录树浏览与仓库搜索已经覆盖该发现路径。
|
||||||
|
|
||||||
|
**恢复人工维护的索引。** 它具有相同的共享文件争用问题,还会重新引入生成机制已经避免的完整性和排序错误。
|
||||||
|
|
||||||
|
## 影响
|
||||||
|
|
||||||
|
- 添加、移动或重命名 Agent Note 时,不再改动覆盖整个语料库的生成文件。
|
||||||
|
- 分类门禁执行的工作更少,文档门禁拓扑也不会增加进程或阶段。
|
||||||
|
- 读者不再获得单一的时间顺序页面,改用生命周期/类别目录树或仓库搜索。
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Agent Note: Generate the Agent Note index tables
|
||||||
|
|
||||||
|
Status: rejected — a centralized generated list is merge-prone and adds little discovery value
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Per-lifecycle/per-class tables would list facts that are fully derivable: an Agent Note's path encodes lifecycle and class, its filename encodes the first-proposed date, and its H1 carries the title. A hand-maintained copy of those facts would also be a high-contention docs hotspot because concurrent Agent Note branches append rows to the same few lines. [The classification Agent Note](../../implemented/process/2026-06-20-agent-note-classification.md) makes the tree itself authoritative.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
Keep the curated prose and generate the list as a fully generated `.agents/notes/INDEX.md`. A shared `scripts/agent-note-index.ts` module would own both the tree walker and the renderer. Two thin consumers would share it:
|
||||||
|
|
||||||
|
- `scripts/gen-agent-note-index.ts` (`pnpm run gen-agent-note-index`) would rewrite INDEX.md in full from the tree.
|
||||||
|
- `scripts/verify-agent-note-classification.ts` would check structure and assert that the committed INDEX.md byte-matches a fresh render.
|
||||||
|
|
||||||
|
Adding, moving, or deleting an Agent Note would mean editing the Agent Note file and running the generator.
|
||||||
|
|
||||||
|
## Alternatives considered
|
||||||
|
|
||||||
|
### Why not marker-delimited regions inside README.md?
|
||||||
|
|
||||||
|
Marker-delimited tables inside README.md would mix generated and curated text, requiring splice mechanics and protection for the surrounding contract. A dedicated generated file would at least keep those concerns separate.
|
||||||
|
|
||||||
|
### Why not the verifier-only model?
|
||||||
|
|
||||||
|
It catches mistakes but still makes every proposal edit a shared hotspot in a hand-maintained table. The author has already named and placed the file, so the index copy adds no information. This is the same hand-list-versus-derivation judgment the [package-inventory proposal](../../proposed/process/2026-06-20-discover-package-inventory.md) applies to tsconfig references and knip stanzas.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- The generated file would be explicit and contain no curated region.
|
||||||
|
- A malformed or missing H1 would be a hard error because the H1 supplies each row title.
|
||||||
|
- Concurrent branches would still modify the same committed artifact, even if conflicts could be resolved by rerunning the generator.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
The implemented [no-index decision](../../implemented/process/2026-07-19-remove-generated-agent-note-index.md) keeps the tree and repository search as the discovery mechanisms.
|
||||||
@@ -14,7 +14,7 @@ description: Use when reviewing a pull request in the deepseek-harness repo —
|
|||||||
- [docs/AGENTS.md](../../../docs/AGENTS.md): documentation placement and prose discipline.
|
- [docs/AGENTS.md](../../../docs/AGENTS.md): documentation placement and prose discipline.
|
||||||
- [dsh-prose-standard](../dsh-prose-standard/SKILL.md): required coverage and editorial judgment for comments, docs, prompts, and visible strings.
|
- [dsh-prose-standard](../dsh-prose-standard/SKILL.md): required coverage and editorial judgment for comments, docs, prompts, and visible strings.
|
||||||
- [docs/testing.md](../../../docs/testing.md) and the [quality-gates Agent Note](../../notes/implemented/process/2026-06-11-quality-gates.md): required test tiers and gates.
|
- [docs/testing.md](../../../docs/testing.md) and the [quality-gates Agent Note](../../notes/implemented/process/2026-06-11-quality-gates.md): required test tiers and gates.
|
||||||
- [Agent Note index](../../notes/README.md): design rationale. Treat disagreement with an Agent Note as a design discussion, not an automatic veto.
|
- [Agent Notes](../../notes/README.md): design rationale. Treat disagreement with an Agent Note as a design discussion, not an automatic veto.
|
||||||
- For bilingual changes, read [translation-rules.md](../../../docs/i18n/translation-rules.md), [terminology.md](../../../docs/i18n/terminology.md), and [dsh-translate-docs](../dsh-translate-docs/SKILL.md).
|
- For bilingual changes, read [translation-rules.md](../../../docs/i18n/translation-rules.md), [terminology.md](../../../docs/i18n/terminology.md), and [dsh-translate-docs](../dsh-translate-docs/SKILL.md).
|
||||||
|
|
||||||
## Blocking requirements
|
## Blocking requirements
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ This skill helps turn a broad "find things to simplify" request into evidence-ba
|
|||||||
|
|
||||||
- Read `AGENTS.md`, especially the pre-release stance and the conventions (including the tests-are-not-golden-truth and Agent Notes-are-not-golden-truth doctrines), plus [docs/defensive-patterns.md](../../../docs/defensive-patterns.md) and [docs/testing.md](../../../docs/testing.md).
|
- Read `AGENTS.md`, especially the pre-release stance and the conventions (including the tests-are-not-golden-truth and Agent Notes-are-not-golden-truth doctrines), plus [docs/defensive-patterns.md](../../../docs/defensive-patterns.md) and [docs/testing.md](../../../docs/testing.md).
|
||||||
- Skim [docs/architecture.md](../../../docs/architecture.md) before judging anything under `packages/`; simplifications that fight the service map or event taxonomy need extra evidence.
|
- Skim [docs/architecture.md](../../../docs/architecture.md) before judging anything under `packages/`; simplifications that fight the service map or event taxonomy need extra evidence.
|
||||||
- Use the Agent Note index ([.agents/notes/README.md](../../notes/README.md)) to understand intentional architecture. The most relevant implemented examples are [drop mutable session summary](../../notes/implemented/simplification/2026-06-19-drop-mutable-session-summary.md), [shared persistence write coordinator](../../notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.md), [capability seams](../../notes/implemented/architecture/2026-06-13-capability-seams.md), and the twin adapter / dual persistence backend Agent Notes.
|
- Use the Agent Note tree and its [contract](../../notes/README.md) to understand intentional architecture. The most relevant implemented examples are [drop mutable session summary](../../notes/implemented/simplification/2026-06-19-drop-mutable-session-summary.md), [shared persistence write coordinator](../../notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.md), [capability seams](../../notes/implemented/architecture/2026-06-13-capability-seams.md), and the twin adapter / dual persistence backend Agent Notes.
|
||||||
- Treat dual LLM adapters and dual persistence backends as intentional by default. Do not propose deleting either twin/backend as "low effort" unless the user explicitly overrides that constraint. Removing an unused method or hook inside a protected seam can still be valid if it does not collapse the protected design.
|
- Treat dual LLM adapters and dual persistence backends as intentional by default. Do not propose deleting either twin/backend as "low effort" unless the user explicitly overrides that constraint. Removing an unused method or hook inside a protected seam can still be valid if it does not collapse the protected design.
|
||||||
|
|
||||||
## What Counts As A Strong Candidate
|
## What Counts As A Strong Candidate
|
||||||
@@ -68,7 +68,7 @@ Reject or downgrade a candidate when:
|
|||||||
|
|
||||||
## Write The Agent Note
|
## Write The Agent Note
|
||||||
|
|
||||||
Create one file per durable proposal under `.agents/notes/<lifecycle>/<class>/yyyy-mm-dd-topic.md`, following the lifecycle/classification contract in `.agents/notes/README.md`. Regenerate `.agents/notes/INDEX.md`; never add a manual Agent Note table to the README. Keep prose paragraphs on one physical line and use relative Markdown links.
|
Create one file per durable proposal under `.agents/notes/<lifecycle>/<class>/yyyy-mm-dd-topic.md`, following the lifecycle/classification contract in `.agents/notes/README.md`. Keep prose paragraphs on one physical line and use relative Markdown links.
|
||||||
|
|
||||||
Prefer this shape, adjusting when the idea needs it:
|
Prefer this shape, adjusting when the idea needs it:
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||||
# after editing either side, bring the other along and re-record with:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write
|
# pnpm run verify-translation-pairing --write
|
||||||
development.md: 31d9f76b6f32b1d26e7b61cdbc2a09aa3504fd6a
|
development.md: 94eb4f03329b574862a1ac1de2f8c1d4db4f4a0a
|
||||||
development.zh.md: 57d9ca376ed85c212cfd075e1b056882f6449e05
|
development.zh.md: b533aff43a66ff7cfc5dc61e5b9b224a01c51f12
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ pnpm run verify-cordis-catalog # fail if either cordis catalog is stale
|
|||||||
pnpm run verify-export-jsdoc # fail if a module-level package export lacks complete JSDoc
|
pnpm run verify-export-jsdoc # fail if a module-level package export lacks complete JSDoc
|
||||||
pnpm run gen-doc-graphs # regenerate generated relationship docs from source and curated graph definitions
|
pnpm run gen-doc-graphs # regenerate generated relationship docs from source and curated graph definitions
|
||||||
pnpm run verify-doc-graphs # fail if generated relationship docs are stale
|
pnpm run verify-doc-graphs # fail if generated relationship docs are stale
|
||||||
pnpm run gen-agent-note-index # regenerate .agents/notes/INDEX.md from the Agent Note tree
|
|
||||||
pnpm run verify-md-wrap # fail on hard-wrapped prose paragraphs in docs/README markdown
|
pnpm run verify-md-wrap # fail on hard-wrapped prose paragraphs in docs/README markdown
|
||||||
pnpm run verify-mermaid # fail if a ```mermaid diagram has invalid Mermaid syntax
|
pnpm run verify-mermaid # fail if a ```mermaid diagram has invalid Mermaid syntax
|
||||||
pnpm run verify-type-equiv # fail if a ```ts type-equiv doc block drifts from its source type
|
pnpm run verify-type-equiv # fail if a ```ts type-equiv doc block drifts from its source type
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ pnpm run verify-cordis-catalog # fail if either cordis catalog is stale
|
|||||||
pnpm run verify-export-jsdoc # fail if a module-level package export lacks complete JSDoc
|
pnpm run verify-export-jsdoc # fail if a module-level package export lacks complete JSDoc
|
||||||
pnpm run gen-doc-graphs # regenerate generated relationship docs from source and curated graph definitions
|
pnpm run gen-doc-graphs # regenerate generated relationship docs from source and curated graph definitions
|
||||||
pnpm run verify-doc-graphs # fail if generated relationship docs are stale
|
pnpm run verify-doc-graphs # fail if generated relationship docs are stale
|
||||||
pnpm run gen-agent-note-index # regenerate .agents/notes/INDEX.md from the Agent Note tree
|
|
||||||
pnpm run verify-md-wrap # fail on hard-wrapped prose paragraphs in docs/README markdown
|
pnpm run verify-md-wrap # fail on hard-wrapped prose paragraphs in docs/README markdown
|
||||||
pnpm run verify-mermaid # fail if a ```mermaid diagram has invalid Mermaid syntax
|
pnpm run verify-mermaid # fail if a ```mermaid diagram has invalid Mermaid syntax
|
||||||
pnpm run verify-type-equiv # fail if a ```ts type-equiv doc block drifts from its source type
|
pnpm run verify-type-equiv # fail if a ```ts type-equiv doc block drifts from its source type
|
||||||
|
|||||||
@@ -53,7 +53,6 @@
|
|||||||
"verify-runtime-closure": "tsx scripts/verify-runtime-closure.ts",
|
"verify-runtime-closure": "tsx scripts/verify-runtime-closure.ts",
|
||||||
"verify-cordis-config": "tsx scripts/verify-cordis-config.ts",
|
"verify-cordis-config": "tsx scripts/verify-cordis-config.ts",
|
||||||
"gen-cordis-catalog": "tsx scripts/gen-cordis-catalog.ts",
|
"gen-cordis-catalog": "tsx scripts/gen-cordis-catalog.ts",
|
||||||
"gen-agent-note-index": "tsx scripts/gen-agent-note-index.ts",
|
|
||||||
"verify-cordis-catalog": "tsx scripts/gen-cordis-catalog.ts --check",
|
"verify-cordis-catalog": "tsx scripts/gen-cordis-catalog.ts --check",
|
||||||
"gen-cordis-api": "tsx scripts/gen-cordis-api.ts",
|
"gen-cordis-api": "tsx scripts/gen-cordis-api.ts",
|
||||||
"verify-cordis-api": "tsx scripts/gen-cordis-api.ts --check",
|
"verify-cordis-api": "tsx scripts/gen-cordis-api.ts --check",
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
/**
|
|
||||||
* Shared source of truth for the Agent Note index: the tree walker (structure rules) and the README
|
|
||||||
* table renderer. `gen-agent-note-index.ts` writes the generated regions;
|
|
||||||
* `verify-agent-note-classification.ts` checks structure and asserts the committed regions are fresh.
|
|
||||||
* Lifecycle and class sets are closed under `.agents/notes/README.md`; rows derive
|
|
||||||
* from path, H1, and filename date and sort deterministically. Import is pure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { readFileSync, readdirSync } from 'node:fs'
|
|
||||||
import { resolve, sep } from 'node:path'
|
|
||||||
import { globSync } from 'node:fs'
|
|
||||||
|
|
||||||
export const agentNoteRoot = resolve(import.meta.dirname, '../.agents/notes')
|
|
||||||
|
|
||||||
/** The closed set of Agent Note lifecycles (top-level folders under .agents/notes/). */
|
|
||||||
const LIFECYCLES = ['proposed', 'implemented', 'rejected'] as const
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The closed set of Agent Note classes (nested folder under each lifecycle). Adding a
|
|
||||||
* class is a deliberate act: extend this list AND the README's Classification
|
|
||||||
* section. The gate rejects any folder not listed here.
|
|
||||||
*/
|
|
||||||
const CLASSES = ['feature', 'bug-fix', 'simplification', 'architecture', 'process', 'testing'] as const
|
|
||||||
|
|
||||||
/** Non-Agent Note Markdown allowed to sit directly at a lifecycle root. */
|
|
||||||
const ROOT_ALLOWLIST = new Set(['AGENTS.md', 'CLAUDE.md'])
|
|
||||||
|
|
||||||
/** Title-case a class/lifecycle folder name for a README heading. */
|
|
||||||
const heading = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1)
|
|
||||||
|
|
||||||
/** One Agent Note file, as discovered by the walker. */
|
|
||||||
export interface AgentNote {
|
|
||||||
lifecycle: string
|
|
||||||
cls: string
|
|
||||||
base: string
|
|
||||||
/** Path relative to .agents/notes — the README link target. */
|
|
||||||
rel: string
|
|
||||||
/** H1 text with any `Agent Note: ` prefix stripped — the README row title. */
|
|
||||||
title: string
|
|
||||||
/** `yyyy-mm-dd` from the filename — the "First proposed" column. */
|
|
||||||
date: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Walk the Agent Note tree, enforcing the structure rules. Returns every valid Agent Note
|
|
||||||
* plus one error string per violation (unknown lifecycle or class folder, bad
|
|
||||||
* depth, bad filename, missing/malformed H1). Callers treat a non-empty error
|
|
||||||
* list as fatal — the index is only generated from a structurally valid tree.
|
|
||||||
*/
|
|
||||||
export function walkAgentNoteTree(): { notes: AgentNote[]; errors: string[] } {
|
|
||||||
const notes: AgentNote[] = []
|
|
||||||
const errors: string[] = []
|
|
||||||
// The lifecycle set is closed too: any directory under .agents/notes/ that is not
|
|
||||||
// a known lifecycle would otherwise hold Agent Notes invisible to the walk below.
|
|
||||||
for (const entry of readdirSync(agentNoteRoot, { withFileTypes: true })) {
|
|
||||||
if (entry.isDirectory() && !(LIFECYCLES as readonly string[]).includes(entry.name)) {
|
|
||||||
errors.push(`structure: ${entry.name}/ — unknown lifecycle folder (allowed: ${LIFECYCLES.join(', ')})`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const lifecycle of LIFECYCLES) {
|
|
||||||
for (const match of globSync(`${lifecycle}/**/*.md`, { cwd: agentNoteRoot }).map(path => path.split(sep).join('/')).sort()) {
|
|
||||||
const segs = match.split('/')
|
|
||||||
// Allowlisted file directly at the lifecycle root (e.g. implemented/AGENTS.md).
|
|
||||||
if (segs.length === 2 && ROOT_ALLOWLIST.has(segs[1] ?? '')) continue
|
|
||||||
// A Chinese counterpart (foo.zh.md, docs/i18n/README.md) is the SAME Agent Note,
|
|
||||||
// indexed via its English filename; the pairing gate owns its consistency.
|
|
||||||
if (match.endsWith('.zh.md')) continue
|
|
||||||
const cls = segs[1]
|
|
||||||
const base = segs[2]
|
|
||||||
if (segs.length !== 3 || cls === undefined || base === undefined) {
|
|
||||||
errors.push(`structure: ${match} — expected {lifecycle}/{class}/file.md (got depth ${segs.length})`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (!(CLASSES as readonly string[]).includes(cls)) {
|
|
||||||
errors.push(`structure: ${match} — unknown class folder "${cls}" (allowed: ${CLASSES.join(', ')})`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (!/^\d{4}-\d{2}-\d{2}-.+\.md$/.test(base)) {
|
|
||||||
errors.push(`structure: ${match} — filename must be yyyy-mm-dd-topic.md`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const firstLine = readFileSync(resolve(agentNoteRoot, match), 'utf8').split('\n', 1)[0] ?? ''
|
|
||||||
const h1 = /^#\s+(?:Agent Note:\s+)?(.+?)\s*$/.exec(firstLine)
|
|
||||||
if (!h1?.[1]) {
|
|
||||||
errors.push(`title: ${match} — first line must be an H1 (\`# Agent Note: <title>\` or \`# <title>\`), got: ${JSON.stringify(firstLine)}`)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
notes.push({ lifecycle, cls, base, rel: match, title: h1[1], date: base.slice(0, 10) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { notes, errors }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render one lifecycle's section body: a `### {Class}` heading plus a
|
|
||||||
* `| Title | First proposed |` table for every non-empty class, in CLASSES
|
|
||||||
* order, rows sorted by date then filename.
|
|
||||||
*/
|
|
||||||
function renderLifecycle(notes: AgentNote[], lifecycle: string): string {
|
|
||||||
const sections: string[] = []
|
|
||||||
for (const cls of CLASSES) {
|
|
||||||
const rows = notes
|
|
||||||
.filter(r => r.lifecycle === lifecycle && r.cls === cls)
|
|
||||||
.sort((a, b) => a.date.localeCompare(b.date) || a.base.localeCompare(b.base))
|
|
||||||
if (rows.length === 0) continue
|
|
||||||
const table = rows.map(r => `| [${r.title}](${r.rel}) | ${r.date} |`).join('\n')
|
|
||||||
sections.push(`### ${heading(cls)}\n\n| Title | First proposed |\n|---|---|\n${table}`)
|
|
||||||
}
|
|
||||||
return sections.join('\n\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the complete `.agents/notes/INDEX.md` content: a generated-file banner
|
|
||||||
* followed by one `## {Lifecycle}` section per lifecycle in canonical order.
|
|
||||||
* The whole file is generated state — there is no curated region to preserve.
|
|
||||||
*/
|
|
||||||
export function renderIndex(notes: AgentNote[]): string {
|
|
||||||
const parts = [
|
|
||||||
'# Agent Note index',
|
|
||||||
'',
|
|
||||||
'Generated by `pnpm run gen-agent-note-index` from the Agent Note tree — never edit by hand; `verify-agent-note-classification` fails when this file is stale. The curated front door — layout, classification, when to write one, and the in-file format — is [README.md](README.md).',
|
|
||||||
]
|
|
||||||
for (const lifecycle of LIFECYCLES) {
|
|
||||||
parts.push('', `## ${heading(lifecycle)}`, '', renderLifecycle(notes, lifecycle))
|
|
||||||
}
|
|
||||||
return `${parts.join('\n')}\n`
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Matches an index-shaped table row (a `| [title](lifecycle/…) |` line) — generated state that must not appear in curated prose. */
|
|
||||||
export const INDEX_ROW = /^\|\s*\[[^\]]+\]\((?:proposed|implemented|rejected)\//
|
|
||||||
78
scripts/agent-note-tree.ts
Normal file
78
scripts/agent-note-tree.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* Shared structural source of truth for the Agent Note tree. Lifecycle and class
|
||||||
|
* sets are closed under `.agents/notes/README.md`; importing this module is pure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { globSync, readdirSync } from 'node:fs'
|
||||||
|
import { resolve, sep } from 'node:path'
|
||||||
|
|
||||||
|
export const agentNoteRoot = resolve(import.meta.dirname, '../.agents/notes')
|
||||||
|
|
||||||
|
/** The closed set of Agent Note lifecycles (top-level folders under .agents/notes/). */
|
||||||
|
const LIFECYCLES = ['proposed', 'implemented', 'rejected'] as const
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The closed set of Agent Note classes (nested folder under each lifecycle). Adding a
|
||||||
|
* class is a deliberate act: extend this list AND the README's Classification
|
||||||
|
* section. The gate rejects any folder not listed here.
|
||||||
|
*/
|
||||||
|
const CLASSES = ['feature', 'bug-fix', 'simplification', 'architecture', 'process', 'testing'] as const
|
||||||
|
|
||||||
|
/** Non-Agent Note Markdown allowed to sit directly at a lifecycle root. */
|
||||||
|
const ROOT_ALLOWLIST = new Set(['AGENTS.md', 'CLAUDE.md'])
|
||||||
|
|
||||||
|
/** One Agent Note file, as discovered by the walker. */
|
||||||
|
export interface AgentNote {
|
||||||
|
lifecycle: string
|
||||||
|
/** Path relative to .agents/notes. */
|
||||||
|
rel: string
|
||||||
|
/** `yyyy-mm-dd` from the filename. */
|
||||||
|
date: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walk the Agent Note tree, enforcing the structure rules. Returns every valid Agent Note
|
||||||
|
* plus one error string per violation (unknown lifecycle or class folder, bad
|
||||||
|
* depth, or bad filename). Callers treat a non-empty error list as fatal.
|
||||||
|
*/
|
||||||
|
export function walkAgentNoteTree(): { notes: AgentNote[]; errors: string[] } {
|
||||||
|
const notes: AgentNote[] = []
|
||||||
|
const errors: string[] = []
|
||||||
|
// The lifecycle set is closed too: any directory under .agents/notes/ that is not
|
||||||
|
// a known lifecycle would otherwise hold Agent Notes invisible to the walk below.
|
||||||
|
for (const entry of readdirSync(agentNoteRoot, { withFileTypes: true })) {
|
||||||
|
if (entry.name === 'INDEX.md') {
|
||||||
|
errors.push('structure: INDEX.md — centralized Agent Note indexes are forbidden; browse the lifecycle/class tree or search the repository')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (entry.isDirectory() && !(LIFECYCLES as readonly string[]).includes(entry.name)) {
|
||||||
|
errors.push(`structure: ${entry.name}/ — unknown lifecycle folder (allowed: ${LIFECYCLES.join(', ')})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const lifecycle of LIFECYCLES) {
|
||||||
|
for (const match of globSync(`${lifecycle}/**/*.md`, { cwd: agentNoteRoot }).map(path => path.split(sep).join('/')).sort()) {
|
||||||
|
const segs = match.split('/')
|
||||||
|
// Allowlisted file directly at the lifecycle root (e.g. implemented/AGENTS.md).
|
||||||
|
if (segs.length === 2 && ROOT_ALLOWLIST.has(segs[1] ?? '')) continue
|
||||||
|
// A Chinese counterpart (foo.zh.md, docs/i18n/README.md) is the SAME Agent Note,
|
||||||
|
// indexed via its English filename; the pairing gate owns its consistency.
|
||||||
|
if (match.endsWith('.zh.md')) continue
|
||||||
|
const cls = segs[1]
|
||||||
|
const base = segs[2]
|
||||||
|
if (segs.length !== 3 || cls === undefined || base === undefined) {
|
||||||
|
errors.push(`structure: ${match} — expected {lifecycle}/{class}/file.md (got depth ${segs.length})`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!(CLASSES as readonly string[]).includes(cls)) {
|
||||||
|
errors.push(`structure: ${match} — unknown class folder "${cls}" (allowed: ${CLASSES.join(', ')})`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!/^\d{4}-\d{2}-\d{2}-.+\.md$/.test(base)) {
|
||||||
|
errors.push(`structure: ${match} — filename must be yyyy-mm-dd-topic.md`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
notes.push({ lifecycle, rel: match, date: base.slice(0, 10) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { notes, errors }
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* Regenerate `.agents/notes/INDEX.md` — the fully generated Agent Note index — from the
|
|
||||||
* Agent Note tree (see [agent-note-index.ts](./agent-note-index.ts) for the layout contract and
|
|
||||||
* rendering rules). The whole file is generated state; the curated prose lives
|
|
||||||
* in `.agents/notes/README.md`. Freshness is asserted by
|
|
||||||
* `verify-agent-note-classification.ts` (a `doc-sync` member), so a stale committed
|
|
||||||
* index fails CI.
|
|
||||||
*
|
|
||||||
* Run: `pnpm run gen-agent-note-index`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { readFileSync, writeFileSync } from 'node:fs'
|
|
||||||
import { resolve } from 'node:path'
|
|
||||||
import { agentNoteRoot, renderIndex, walkAgentNoteTree } from './agent-note-index.ts'
|
|
||||||
|
|
||||||
const { notes, errors } = walkAgentNoteTree()
|
|
||||||
if (errors.length > 0) {
|
|
||||||
console.error('gen-agent-note-index: refusing to generate from a structurally invalid tree:')
|
|
||||||
for (const e of errors) console.error(` ${e}`)
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const indexPath = resolve(agentNoteRoot, 'INDEX.md')
|
|
||||||
const next = renderIndex(notes)
|
|
||||||
let current: string | undefined
|
|
||||||
try {
|
|
||||||
current = readFileSync(indexPath, 'utf8')
|
|
||||||
} catch {
|
|
||||||
// Missing INDEX.md is the fresh-generation case, not an error: fall through and write it.
|
|
||||||
}
|
|
||||||
if (next === current) {
|
|
||||||
console.log(`gen-agent-note-index: .agents/notes/INDEX.md is up to date (${notes.length} Agent Notes).`)
|
|
||||||
} else {
|
|
||||||
writeFileSync(indexPath, next)
|
|
||||||
console.log(`gen-agent-note-index: .agents/notes/INDEX.md regenerated (${notes.length} Agent Notes).`)
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* Enforce Agent Note lifecycle/class paths, dated filenames, and titles; verify the
|
* Enforce Agent Note lifecycle/class paths and dated filenames. Structural rules
|
||||||
* generated index and reject index rows in the curated README. Structural rules
|
* are shared with `agent-note-tree.ts`; the closed classification contract lives
|
||||||
* and rendering are shared with `agent-note-index.ts`; the closed classification
|
* in `.agents/notes/README.md`.
|
||||||
* contract lives in `.agents/notes/README.md`.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { existsSync, readFileSync } from 'node:fs'
|
import { existsSync } from 'node:fs'
|
||||||
import { resolve } from 'node:path'
|
import { resolve } from 'node:path'
|
||||||
import { agentNoteRoot, INDEX_ROW, renderIndex, walkAgentNoteTree } from './agent-note-index.ts'
|
import { walkAgentNoteTree } from './agent-note-tree.ts'
|
||||||
|
|
||||||
const { notes, errors } = walkAgentNoteTree()
|
const { notes, errors } = walkAgentNoteTree()
|
||||||
|
|
||||||
@@ -19,25 +18,7 @@ for (const legacyRoot of ['docs/rfc', 'docs/rfcs']) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (errors.length === 0) {
|
if (errors.length === 0) {
|
||||||
let index: string | undefined
|
console.log(`verify-agent-note-classification: ${notes.length} Agent Note(s) checked, structure consistent.`)
|
||||||
try {
|
|
||||||
index = readFileSync(resolve(agentNoteRoot, 'INDEX.md'), 'utf8')
|
|
||||||
} catch {
|
|
||||||
// A missing INDEX.md is reported below as staleness, exactly like a drifted one.
|
|
||||||
}
|
|
||||||
if (renderIndex(notes) !== index) {
|
|
||||||
errors.push('index: .agents/notes/INDEX.md is stale or missing — run `pnpm run gen-agent-note-index` and commit the result')
|
|
||||||
}
|
|
||||||
const readme = readFileSync(resolve(agentNoteRoot, 'README.md'), 'utf8')
|
|
||||||
for (const line of readme.split('\n')) {
|
|
||||||
if (INDEX_ROW.test(line)) {
|
|
||||||
errors.push(`readme: index-shaped row in the curated README (the list lives in INDEX.md): ${JSON.stringify(line.slice(0, 80))}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errors.length === 0) {
|
|
||||||
console.log(`verify-agent-note-classification: ${notes.length} Agent Note(s) checked, structure and index consistent.`)
|
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import { readFileSync } from 'node:fs'
|
import { readFileSync } from 'node:fs'
|
||||||
import { resolve } from 'node:path'
|
import { resolve } from 'node:path'
|
||||||
import { agentNoteRoot, walkAgentNoteTree } from './agent-note-index.ts'
|
import { agentNoteRoot, walkAgentNoteTree } from './agent-note-tree.ts'
|
||||||
|
|
||||||
/** The date the format contract landed; the grandfather comment is valid only before it. */
|
/** The date the format contract landed; the grandfather comment is valid only before it. */
|
||||||
const FORMAT_ADOPTED = '2026-07-05'
|
const FORMAT_ADOPTED = '2026-07-05'
|
||||||
|
|||||||
Reference in New Issue
Block a user