From 49df3794bc15d610988acc674637384ce8f1d4be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Sat, 12 Sep 2026 17:23:20 +0100 Subject: [PATCH] docs: replace tracked document catalogs (#3482) --- .agents/skills/context-engineering/SKILL.md | 9 +- .agents/skills/fix/SKILL.md | 9 +- .agents/skills/plan/SKILL.md | 5 +- .agents/skills/record/SKILL.md | 14 +- .agents/skills/spec/SKILL.md | 27 +- .github/workflows/lint-harness-files.yml | 6 + .pre-commit-config.yaml | 7 + AGENTS.md | 8 +- .../0001-file-based-knowledge-system.md | 6 +- ...26-08-22-system-oriented-specifications.md | 16 +- .../2026-09-07-on-demand-document-catalogs.md | 97 +++ docs/decisions/INDEX.md | 300 +-------- docs/plans/docs-catalog-discovery/plan.md | 131 ++++ .../task-01-build-catalog-command.md | 110 ++++ .../task-02-replace-derived-catalogs.md | 121 ++++ .../task-03-wire-authoring-validation.md | 114 ++++ docs/specs/INDEX.md | 82 ++- docs/specs/README.md | 6 +- docs/specs/agents/README.md | 77 +-- docs/specs/auth/README.md | 24 +- docs/specs/canvases/README.md | 13 - docs/specs/ci/README.md | 14 - docs/specs/cli/README.md | 16 +- docs/specs/costs/README.md | 18 +- docs/specs/desktop/README.md | 18 +- docs/specs/disambiguate-waiting/spec.md | 3 +- docs/specs/executors/README.md | 40 +- docs/specs/guide/requirements.md | 13 +- docs/specs/guide/structure-and-ownership.md | 30 +- .../specs/guide/traceability-and-lifecycle.md | 9 +- docs/specs/integrations/README.md | 74 +-- docs/specs/launcher/README.md | 10 - docs/specs/office/README.md | 100 +-- docs/specs/platform/README.md | 85 +-- docs/specs/plugins/README.md | 34 +- .../plugin-nav-sidebar-footer-01.md | 11 +- docs/specs/product/README.md | 13 +- docs/specs/release/README.md | 20 +- docs/specs/spec-lint-exceptions.tsv | 2 +- docs/specs/system-page/README.md | 30 +- docs/specs/tasks/README.md | 171 +---- docs/specs/templates/system-readme.md | 13 +- docs/specs/ui/README.md | 212 ------- docs/specs/workspaces/README.md | 35 +- scripts/lint-spec-files.py | 191 ++---- scripts/list-docs.py | 589 ++++++++++++++++++ scripts/list-docs.test.py | 420 +++++++++++++ scripts/spec_metadata.py | 194 ++++++ 48 files changed, 2048 insertions(+), 1499 deletions(-) create mode 100644 docs/decisions/2026-09-07-on-demand-document-catalogs.md create mode 100644 docs/plans/docs-catalog-discovery/plan.md create mode 100644 docs/plans/docs-catalog-discovery/task-01-build-catalog-command.md create mode 100644 docs/plans/docs-catalog-discovery/task-02-replace-derived-catalogs.md create mode 100644 docs/plans/docs-catalog-discovery/task-03-wire-authoring-validation.md create mode 100644 scripts/list-docs.py create mode 100644 scripts/list-docs.test.py create mode 100644 scripts/spec_metadata.py diff --git a/.agents/skills/context-engineering/SKILL.md b/.agents/skills/context-engineering/SKILL.md index 824b2bdd06..eccc2b97cc 100644 --- a/.agents/skills/context-engineering/SKILL.md +++ b/.agents/skills/context-engineering/SKILL.md @@ -27,11 +27,12 @@ Before changing code: - Read the scoped `AGENTS.md` for the subtree you will touch, e.g. `apps/backend/AGENTS.md`, `apps/web/AGENTS.md`, or integration-specific guidance. - Use `rg` to find existing patterns before inventing one. - Read the file you will edit and nearby tests. -- For product features, read `docs/specs/README.md`, the owning system index, - adjacent indexes with similar capability names, and only the relevant +- For product features, read `docs/specs/README.md`, the owning system `README.md`, + adjacent system README files with similar capability names, and only the relevant requirement and system-design files. Choose the owner from the durable - contract, not the affected code layer. During migration, use - `docs/specs/INDEX.md` to find a legacy source. + contract, not the affected code layer. Use `python3 scripts/list-docs.py + specs --format paths` to find documents. During migration, add + `--kind legacy` to find a legacy source. - When implementing from a plan, read `plan.md` for orientation and only the current work order. Follow its `REQ-*`, `AC-*`, and system-design references. - Dependency, sibling, and stacked PR references are snapshots. Resolve the diff --git a/.agents/skills/fix/SKILL.md b/.agents/skills/fix/SKILL.md index 0fb8e7c85f..55bcd114cf 100644 --- a/.agents/skills/fix/SKILL.md +++ b/.agents/skills/fix/SKILL.md @@ -35,9 +35,12 @@ If the cause remains uncertain, stop and ask the user. ## Phase 1: Reconcile specifications -Read `docs/specs/README.md`, the owning system index, and the relevant -requirement and system-design documents. Use the legacy catalog only when the -system has not migrated. +Read `docs/specs/README.md`, the owning system `README.md`, and the relevant +requirement and system-design documents. Use this command for discovery: + + python3 scripts/list-docs.py specs --format paths + +Add `--kind legacy` when the system has not migrated. Search adjacent systems before you create or move an artifact. A UI symptom does not make the repair UI-owned. Update the system that owns the failed contract, diff --git a/.agents/skills/plan/SKILL.md b/.agents/skills/plan/SKILL.md index d2a9ab03c9..64ae5f26b0 100644 --- a/.agents/skills/plan/SKILL.md +++ b/.agents/skills/plan/SKILL.md @@ -53,8 +53,9 @@ Identify: - Existing tests and end-to-end patterns. - The dependency order for implementation. -Check `docs/decisions/INDEX.md` for relevant decisions. Stop when the -requirements, system design, ADRs, and code disagree on a material boundary. +Use `python3 scripts/list-docs.py decisions --text --format paths` +to locate relevant decisions. Stop when the requirements, system design, ADRs, +and code disagree on a material boundary. ### 2. Write `plan.md` diff --git a/.agents/skills/record/SKILL.md b/.agents/skills/record/SKILL.md index ae8d63ed67..e967e2b3f7 100644 --- a/.agents/skills/record/SKILL.md +++ b/.agents/skills/record/SKILL.md @@ -27,7 +27,8 @@ change, plan sequence, or temporary migration step. 1. Choose an ID in the form `YYYY-MM-DD-short-title`. 2. Make sure that `docs/decisions/.md` does not exist. 3. Create the ADR with the template below. -4. Add it to `docs/decisions/INDEX.md`. +4. Run `python3 scripts/list-docs.py decisions --format paths` to confirm the + new ADR is discoverable. Do not edit a catalog row. 5. Reconcile affected specifications. Existing numeric ADR IDs remain valid. Do not rename them. @@ -58,8 +59,9 @@ State each meaningful alternative and why it was not selected. ## Reconcile specifications -Read `docs/specs/README.md`, the owning system index, and the relevant files in -`docs/specs/guide/`. +Read `docs/specs/README.md`, the owning system `README.md`, and the relevant +files in `docs/specs/guide/`. Use the catalog command to locate the owning +requirements and designs. Apply these rules: @@ -78,7 +80,10 @@ Do not copy the ADR into requirements or system design. Link the ADR from the affected design. Requirements contain observable outcomes, not decision rationale. -During legacy migration, use `docs/specs/INDEX.md` to locate existing sources. +During legacy migration, use this command to locate existing sources: + + python3 scripts/list-docs.py specs --kind legacy --format paths + Do not create a new generic `spec.md` file. ## Validation @@ -87,6 +92,7 @@ Run: ```bash python3 scripts/lint-spec-files.py --all +python3 scripts/list-docs.py validate git diff --check -- docs/decisions docs/specs ``` diff --git a/.agents/skills/spec/SKILL.md b/.agents/skills/spec/SKILL.md index 31e6390737..7bbdb7442f 100644 --- a/.agents/skills/spec/SKILL.md +++ b/.agents/skills/spec/SKILL.md @@ -48,12 +48,18 @@ confirmation. ### 1. Locate the owning system -Read `docs/specs/README.md` and the likely system `README.md`. If the system has -not migrated, use `docs/specs/INDEX.md` to locate the legacy source. +Read `docs/specs/README.md` and the likely system `README.md`. If the system +has not migrated, run this command to locate the legacy source: -Search all system indexes, requirements, and designs for the capability name -and its main nouns. Update an existing capability when it owns the same actor, -lifecycle, and contract. + python3 scripts/list-docs.py specs --kind legacy --format paths + +Search the catalog, requirements, and designs for the capability name and its +main nouns: + + python3 scripts/list-docs.py specs --text --format paths + +Update an existing capability when it owns the same actor, lifecycle, and +contract. Choose the system that owns the source of truth and durable contract. Do not choose an owner from the code directories that change. Record one sentence in @@ -121,10 +127,12 @@ design can include backend services, storage, projections, frontend components, responsive behavior, and tests. Do not create a parallel UI design for those same requirements. -### 5. Update the system index +### 5. Update the system boundary -Add the new documents to the system `README.md`. State the system boundary and -link adjacent systems when ownership can be confused. +Update the system `README.md` only when the system boundary, migration record, +or related-system links change. State the system boundary and link adjacent +systems when ownership can be confused. Do not add a requirement or +system-design list. Before and after adding required links, run `wc -c /README.md`. Near the 12 KiB `system-index` limit, keep every required link but use concise @@ -157,11 +165,12 @@ Review the artifacts before you run the linter: - Each design identifier that names existing code matches the current source. Use `rg` to confirm exact symbols before the artifact is complete. - New files do not copy the legacy `Migrated source detail` wrapper. -- New artifacts appear in the owning system index. +- New artifacts appear in the catalog command output for the owning system. Run: ```bash +python3 scripts/list-docs.py validate python3 scripts/lint-spec-files.test.py python3 scripts/lint-spec-files.py --all git diff --check -- docs/specs docs/decisions diff --git a/.github/workflows/lint-harness-files.yml b/.github/workflows/lint-harness-files.yml index 4bea50ceea..970e943b92 100644 --- a/.github/workflows/lint-harness-files.yml +++ b/.github/workflows/lint-harness-files.yml @@ -49,6 +49,12 @@ jobs: - name: Lint harness files run: python3 .github/scripts/lint-harness-files.py --all + - name: Test documentation catalog + run: python3 scripts/list-docs.test.py + + - name: Validate documentation catalog + run: python3 scripts/list-docs.py validate + - name: Test specification linter run: python3 scripts/lint-spec-files.test.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7081633b9e..6f33818349 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,6 +18,13 @@ repos: language: system pass_filenames: true + - id: docs-catalog + name: Documentation catalog validation + entry: python3 scripts/list-docs.py validate + language: system + files: ^docs/(decisions|specs)/.*\.md$|^scripts/(list-docs|spec_metadata|lint-spec-files)\.py$|^scripts/(list-docs|lint-spec-files)\.test\.py$ + pass_filenames: false + - id: architecture-lint name: Architecture lint and compatibility expiry entry: python3 scripts/lint-architecture.py --all diff --git a/AGENTS.md b/AGENTS.md index 931a91825e..59fa67ab63 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -158,10 +158,10 @@ history and remains immutable. `docs/specs//system-design/`. Read `docs/specs/README.md` and the relevant file in `docs/specs/guide/`. Choose the owner from the durable contract, not the affected code layer. Keep one vertical requirement/design - pair and include its UI outcomes there. Use `docs/specs/INDEX.md` only to - find unmigrated legacy specifications. Run `python3 - scripts/lint-spec-files.py --all` after specification changes. -- **Decisions:** Architecture decisions are recorded in `docs/decisions/`. Read `docs/decisions/INDEX.md` for an overview. When making significant architectural choices, create a new ADR via `/record decision`. + pair and include its UI outcomes there. Find current documents with + `python3 scripts/list-docs.py specs --system --format paths`; use + `--kind legacy` to include legacy sources. Run `python3 scripts/list-docs.py validate` and `python3 scripts/lint-spec-files.py --all` after specification changes. +- **Decisions:** Architecture decisions are recorded in `docs/decisions/`. Use `python3 scripts/list-docs.py decisions --format markdown` to find relevant ADRs. The `docs/decisions/INDEX.md` page contains command examples. When making significant architectural choices, create a new ADR via `/record decision`. - **Plans:** Implementation plans are generated from requirements and system designs through `/plan`. `docs/plans//plan.md` is a work-package manifest. Its sibling `task--.md` files are work orders. diff --git a/docs/decisions/0001-file-based-knowledge-system.md b/docs/decisions/0001-file-based-knowledge-system.md index 2596f768fe..567860fe17 100644 --- a/docs/decisions/0001-file-based-knowledge-system.md +++ b/docs/decisions/0001-file-based-knowledge-system.md @@ -1,6 +1,6 @@ # 0001: File-based knowledge system -**Status:** accepted (specification layout amended by ADR-2026-08-22-system-oriented-specifications) +**Status:** accepted (specification layout amended by ADR-2026-08-22-system-oriented-specifications and ADR-2026-09-07-on-demand-document-catalogs) **Date:** 2026-03-28 (amended 2026-08-22) **Area:** infra @@ -13,7 +13,7 @@ Agents working on Kandev had no way to record architectural decisions or store i Use a three-tier, file-based knowledge system: - **Tier 1 (always loaded):** `CLAUDE.md` stays slim and points to Tier 2 indexes. -- **Tier 2 (index files):** `docs/decisions/INDEX.md` and `docs/specs/INDEX.md` — one-line-per-entry tables that agents read to find relevant items. +- **Tier 2 (catalog entry pages):** `docs/decisions/INDEX.md` and `docs/specs/INDEX.md` explain how to query source files with `scripts/list-docs.py`. - **Tier 3 (individual files):** Individual ADRs and specification documents, loaded only when needed. @@ -42,7 +42,7 @@ future work must follow. ## Consequences -- Agents can discover past decisions by reading a small index file, then drill into specific ADRs. +- Agents can discover past decisions with stable filters, then drill into specific ADRs. - No file grows unbounded — each decision is its own file. - Knowledge is committed to git and survives across sessions, branches, and agent providers. - The `/spec` skill integrates with the decision log (reads in design, writes when a durable decision is needed). diff --git a/docs/decisions/2026-08-22-system-oriented-specifications.md b/docs/decisions/2026-08-22-system-oriented-specifications.md index 6bf645c45f..92fb29ee90 100644 --- a/docs/decisions/2026-08-22-system-oriented-specifications.md +++ b/docs/decisions/2026-08-22-system-oriented-specifications.md @@ -1,6 +1,6 @@ # ADR-2026-08-22-system-oriented-specifications: Organize Specifications by System -**Status:** accepted +**Status:** accepted (amended by ADR-2026-09-07-on-demand-document-catalogs) **Date:** 2026-08-22 **Area:** workflow, infra @@ -34,15 +34,18 @@ for acceptance criteria. System designs and work orders reference these identifiers. Tests reference acceptance criteria when the mapping is useful. Use `docs/specs/guide/` as the canonical authoring guide. Skills apply this -guide but do not duplicate its complete rules. A repository linter enforces -the mechanical rules, including file-size limits. +guide but do not duplicate its complete rules. The catalog command derives +document lists from paths and frontmatter. A repository linter enforces the +mechanical rules, including file-size limits. Do not move all legacy specifications in one mechanical change. A migration must separate product intent from technical design. Each migrated system must name one new source of truth before legacy content becomes a link or archive. -This decision amends the specification layout in ADR-0001. It does not change -the file-based and progressively loaded knowledge model. +This decision amends the specification layout in ADR-0001. ADR-2026-09-07 +amends this decision by replacing tracked specification lists with on-demand +catalog output. The change does not alter the file-based and progressively +loaded knowledge model. No product specification needs an update. This decision changes the repository authoring system and not Kandev product behavior. @@ -50,7 +53,7 @@ authoring system and not Kandev product behavior. ## Consequences Requirements and system designs stay close because they share an owning -system. Agents can load one system index and select only the necessary files. +system. Agents can query one system and select only the necessary files. The term `specification` becomes an umbrella term. New documents do not use a generic `spec.md` filename. Authors must identify each document as a product @@ -79,4 +82,3 @@ sprawl. This option followed an external software-factory model. The term did not match Kandev terminology and implied a more rigid document than a living system design. - diff --git a/docs/decisions/2026-09-07-on-demand-document-catalogs.md b/docs/decisions/2026-09-07-on-demand-document-catalogs.md new file mode 100644 index 0000000000..18dea0118a --- /dev/null +++ b/docs/decisions/2026-09-07-on-demand-document-catalogs.md @@ -0,0 +1,97 @@ +# ADR-2026-09-07-on-demand-document-catalogs: Derive Documentation Catalogs on Demand + +**Status:** accepted +**Date:** 2026-09-07 +**Area:** workflow, infra + +## Context + +The decision log and specification catalog contain lists that repeat data from +the documents they describe. Every new architecture decision changes +`docs/decisions/INDEX.md`. Specification changes also update +`docs/specs/INDEX.md` and large maps in system README files. + +These shared files change in many pull requests. Concurrent pull requests then +conflict even when they add unrelated documents. The copied rows also become +stale when a document moves or its metadata changes. + +The repository already stores the required catalog data in filenames, headings, +paths, and document metadata. A catalog does not need a tracked generated copy. + +## Decision + +Treat architecture decision files and specification files as the catalog source +of truth. Provide one repository script that lists and filters both document +types on demand. + +The command must support these catalog views: + +- Decisions, with filters for status, area, and text. +- Specifications, with filters for system, document kind, status, and text. +- Markdown, path-only, and JSON output for people and other tools. + +The command must use deterministic ordering. It must validate required metadata +and report malformed source files with actionable errors. Pre-commit and CI must +run validation. They must not rewrite documentation files. + +Keep `docs/decisions/INDEX.md` and `docs/specs/INDEX.md` as short entry pages. +They describe the document model and show catalog commands. They do not contain +rows for individual documents. + +Keep each specification system README as a durable boundary document. It keeps +the purpose, scope, ownership, exclusions, migration record, and related-system +links. Remove exhaustive requirement and system-design maps from these files. +The catalog command derives those maps from paths and frontmatter. + +Keep manually curated information manual when file metadata cannot derive it. +This includes public documentation navigation in `docs/public/meta.json` and +the semantic ownership map in `docs/public/coverage.json`. Plans remain grouped +by initiative and do not need a repository-wide catalog. + +This decision amends ADR-0001 and +ADR-2026-08-22-system-oriented-specifications. It changes repository authoring, +not Kandev product behavior. No product requirement or system design changes. + +## Consequences + +Unrelated document additions no longer edit one shared list. Authors can find +documents with filters instead of scanning long Markdown tables. + +Catalog output always reflects the checked-out branch. Consumers that need a +snapshot can request JSON or Markdown from the script without committing the +result. + +The repository gains one small Python command and focused tests. Authors must +keep source metadata valid because validation replaces manual list maintenance. + +Links to the old exhaustive tables and system maps need an update. Agent skills, +authoring guides, templates, pre-commit, and CI must use the new command. + +## Alternatives Considered + +### Commit generated catalog files + +This option keeps browsable tables on GitHub. It still makes concurrent pull +requests update the same files. Deterministic generation does not remove merge +conflicts. + +### Update catalogs in a follow-up bot pull request + +This option removes catalog edits from feature branches. It adds automation, +permissions, another pull request, and a delay before the catalog is accurate. + +### Generate catalogs in each pull request + +A pre-commit hook can rewrite the tables in the same pull request. The rewrite +still creates the shared-file conflict that this decision removes. + +### Split catalogs by date or system + +Sharding reduces the conflict rate. It keeps duplicated data and manual index +maintenance. On-demand discovery removes both problems. + +### Use separate scripts for decisions and specifications + +Separate commands avoid shared implementation. One command gives authors one +discovery interface and one output contract. The two catalogs remain separate +subcommands with type-specific parsers and filters. diff --git a/docs/decisions/INDEX.md b/docs/decisions/INDEX.md index c2127915a7..2d1945d326 100644 --- a/docs/decisions/INDEX.md +++ b/docs/decisions/INDEX.md @@ -1,270 +1,38 @@ # Decision Log -Architecture Decision Records (ADRs) for the Kandev project. Each decision captures the context, choice, consequences, and alternatives for significant architectural or design decisions. +Architecture Decision Records (ADRs) describe durable architecture, ownership, +boundary, contract, and repository decisions for Kandev. -Read individual ADRs for full context. Create new ones via `/record decision` or manually following the template in `0001-file-based-knowledge-system.md`. +This page is a static entry page. It does not contain a generated decision +table. The decision files are the source of truth. -| ID | Title | Status | Area | Date | -| ---- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------- | --------------------------- | ---------- | -| 0001 | [File-based knowledge system](0001-file-based-knowledge-system.md) | accepted (amended 2026-08-22) | infra | 2026-03-28 | -| 0002 | [Host utility agentctl for sessionless ACP flows](0002-host-utility-agentctl-for-sessionless-flows.md) | accepted | backend | 2026-04-08 | -| 0003 | [executors_running as the single source of truth for agent_execution_id](0003-executors-running-as-execution-id-source-of-truth.md) | accepted | backend | 2026-05-03 | -| 0004 | [Task model unification — shared base, per-strategy meta, shared kernel](0004-task-model-unification.md) | proposed | backend, frontend | 2026-05-05 | -| 0005 | [Agent model unification — one `agents` table](0005-agent-model-unification.md) | proposed | backend, frontend | 2026-05-06 | -| 0006 | [Tier routing vs cheap_agent_profile_id coexistence](0006-tier-routing-vs-cheap-agent-profile-coexistence.md) | superseded | backend | 2026-05-11 | -| 0007 | [profiles.yaml — runtime defaults for prod / dev / e2e](0007-runtime-feature-flags.md) | accepted | backend, frontend | 2026-05-16 | -| 0008 | [DB upgrade safety - meta table, pre-migration backup, migration logging](0008-db-upgrade-safety.md) | accepted | backend | 2026-05-16 | -| 0009 | [Fail-closed GC semantics for filesystem and container cleanup](0009-fail-closed-gc-semantics.md) | accepted (implementation superseded 2026-09-08) | backend | 2026-05-16 | -| 0010 | [Worktree copy-files — per-repo, idempotent, host-local](0010-worktree-copy-files.md) | accepted | backend, frontend | 2026-05-19 | -| 0011 | [Transient provider errors (529 Overloaded) auto-retry with visible backoff](0011-transient-provider-error-retry.md) | superseded by 2026-08-08-provider-neutral-agent-error-recovery | backend, frontend | 2026-05-30 | -| 0012 | [Service-only UI self-update](0012-service-only-self-update.md) | accepted | backend, frontend, cli | 2026-05-29 | -| 0013 | [Multi-branch task support — N (repo, branch) pairs per task](0013-multi-branch-tasks.md) | accepted | backend, frontend | 2026-06-01 | -| 0014 | [Per-CLI MCP server injection for passthrough mode](0014-passthrough-mcp-injection-strategies.md) | accepted | backend | 2026-05-29 | -| 0015 | [Explicit completion signal for auto-advance](0015-explicit-completion-signal-for-auto-advance.md) | proposed (amended 2026-08-14, 2026-09-05) | backend, frontend | 2026-06-04 | -| 0016 | [Read-only absolute file paths](0016-observed-external-file-reads.md) | accepted | backend | 2026-06-14 | -| 0017 | [Resource metrics sampling](0017-resource-metrics-sampling.md) | accepted | backend, frontend, protocol | 2026-06-14 | -| 0018 | [Runtime settings overrides](0018-runtime-settings-overrides.md) | accepted (amended 2026-08-11) | backend, frontend, cli | 2026-06-14 | -| 0019 | [Restart supervisor owns backend restarts](0019-restart-supervisor.md) | accepted | backend, frontend, cli | 2026-06-14 | -| 0020 | [Pi project MCP config injection](0020-pi-project-mcp-config-injection.md) | accepted | backend | 2026-06-16 | -| 0021 | [Go-served SPA with boot state](0021-go-served-spa-with-boot-state.md) | accepted | backend, frontend, cli | 2026-06-15 | -| 0022 | [Embedded Vite assets](0022-embedded-vite-assets.md) | accepted | backend, frontend, cli | 2026-06-17 | -| 0023 | [Active workspace cookie for boot state](0023-active-workspace-cookie.md) | accepted | backend, frontend | 2026-06-18 | -| 0024 | [Go-fronted Vite dev mode](0024-go-fronted-vite-dev-mode.md) | accepted | backend, frontend, cli | 2026-06-18 | -| 0025 | [Runtime cleanup uses `executors_running`](0025-runtime-cleanup-uses-executors-running.md) | accepted (amended 2026-07-06) | backend | 2026-06-22 | -| 0026 | [Tauri desktop shell over native runtime](0026-tauri-desktop-shell.md) | accepted (amended 2026-07-15) | frontend, backend, cli, infra | 2026-06-23 | -| 0027 | [Replayable schema migrations across SQLite and Postgres](0027-replayable-schema-migrations.md) | accepted | backend | 2026-06-24 | -| 0028 | [Backend-owned task-create last-used preferences](0028-task-create-last-used-source-of-truth.md) | accepted (amended by 0041) | backend, frontend | 2026-06-29 | -| 0029 | [Release backfill and desktop diagnostics](0029-release-backfill-and-desktop-diagnostics.md) | accepted (amended 2026-07-16) | infra, workflow | 2026-07-01 | -| 0030 | [Workspace-scoped integration settings](0030-workspace-scoped-integration-settings.md) | accepted | backend, frontend | 2026-07-01 | -| 0031 | [Office skill reference files](0031-office-skill-reference-files.md) | accepted | backend | 2026-07-06 | -| 0032 | [Configurable worktree branch names](0032-configurable-worktree-branch-names.md) | accepted (amended 2026-08-24) | backend, frontend | 2026-07-07 | -| 0033 | [Durable plan implementation start marker](0033-durable-plan-implementation-start.md) | accepted | backend, frontend | 2026-07-09 | -| 0034 | [Agent Client Protocol Codex ACP Bridge](0034-agentclientprotocol-codex-acp.md) | accepted (amended 2026-07-25) | backend, protocol | 2026-07-10 | -| 0035 | [Version AgentReady events by prompt generation](0035-version-agent-ready-events-by-prompt-generation.md) | accepted | backend | 2026-07-14 | -| 0036 | [Normalize ACP shell output at the adapter boundary](0036-normalize-acp-shell-output-at-adapter-boundary.md) | accepted | backend, frontend, protocol | 2026-07-14 | -| 0037 | [Resource-aware frontend unit tests](0037-resource-aware-frontend-unit-tests.md) | accepted (amended 2026-08-28) | frontend, infra | 2026-07-14 | -| 0038 | [Quick Chat Repository Isolation](0038-quick-chat-repository-isolation.md) | accepted | backend, frontend | 2026-07-14 | -| 0039 | [Native desktop integration boundary](0039-native-desktop-integration-boundary.md) | accepted (amended 2026-07-24) | desktop, frontend, backend, infra | 2026-07-15 | -| 0040 | [Separate updater integrity from OS publisher identity](0040-separate-updater-integrity-from-os-publisher-identity.md) | accepted | desktop, infra, workflow | 2026-07-15 | -| 0041 | [Backend-owned portable user settings](0041-backend-owned-portable-user-settings.md) | accepted (amended 2026-09-03) | backend, frontend | 2026-07-15 | -| 0042 | [Project shell output and fetch it on demand](0042-project-shell-output-and-fetch-on-demand.md) | accepted | backend, frontend, protocol | 2026-07-16 | -| 0043 | [Plugins read/write kandev data via capability-gated Host gRPC RPCs](0043-plugin-host-data-api.md) | accepted | backend, protocol | 2026-07-17 | -| 2026-07-14-typed-utility-chat-sessions | [Typed Utility Chats Share the Quick Chat Session Model](2026-07-14-typed-utility-chat-sessions.md) | accepted | backend, frontend | 2026-07-14 | -| 2026-07-15-office-agent-execution-profile-routing | [Separate Office identity from routed execution profiles](2026-07-15-office-agent-execution-profile-routing.md) | superseded by 2026-08-13-dynamic-agent-profile-routing | backend, frontend | 2026-07-15 | -| 0044 | [ACP agent compatibility dialects](0044-acp-agent-compatibility-dialects.md) | accepted | backend, protocol | 2026-07-16 | -| 0045 | [Install-wide storage maintenance uses typed ownership providers and quarantine](0045-install-wide-storage-maintenance.md) | accepted (amended 2026-07-22) | backend, frontend, infra | 2026-07-14 | -| 2026-09-10-storage-overlap-attribution | [Attribute storage by measured files](2026-09-10-storage-overlap-attribution.md) | accepted | backend, frontend | 2026-09-10 | -| 0046 | [Settings route save coordinator](0046-settings-route-save-coordinator.md) | accepted (amended 2026-08-09) | frontend | 2026-07-14 | -| 0047 | [Plugins read conversation content via a capability-gated Host RPC](0047-plugin-host-conversation-reads.md) | accepted | backend, protocol | 2026-07-21 | -| 0048 | [Plugins invoke a settings-selectable utility agent](0048-plugin-host-utility-agent-invoke.md) | accepted | backend, frontend, protocol | 2026-07-21 | -| 0049 | [Fine-grained foreground-idle busy signal](0049-fine-grained-foreground-idle-busy-signal.md) | superseded by 2026-07-28-coarse-running-busy-signal | backend, frontend, protocol | 2026-07-11 | -| 0050 | [Plugins provide OIDC/SAML login via a capability-gated, host-minted session](0050-plugin-external-auth-capability.md) | accepted | backend, security, protocol | 2026-07-26 | -| 0051 | [PR agent notifications extend task PR automation](0051-pr-agent-notifications-extend-task-pr-automation.md) | accepted | backend, frontend, workflow, GitHub, MCP | 2026-07-23 | -| 0052 | [Plugins reconcile pending agent interactions through a dedicated Host contract](0052-plugin-host-interaction-api.md) | accepted | backend, protocol | 2026-08-22 | -| 2026-07-23-opencode-review-evidence-trust | [Trusted OpenCode Review Evidence](2026-07-23-opencode-review-evidence-trust.md) | accepted | workflow, infra | 2026-07-23 | -| 2026-07-23-planner-direct-small-work | [Planner Direct Small Work](2026-07-23-planner-direct-small-work.md) | superseded by 2026-07-26 | workflow | 2026-07-23 | -| 2026-07-23-post-commit-hook-aware-verification | [Post-Commit Hook-Aware Verification](2026-07-23-post-commit-hook-aware-verification.md) | superseded by 2026-07-26 | workflow | 2026-07-23 | -| 2026-07-23-workspace-source-root-move-boundary | [Workspace Source Root Move Boundary](2026-07-23-workspace-source-root-move-boundary.md) | accepted | backend | 2026-07-23 | -| 2026-07-24-operator-owned-agent-launcher-settings | [Operator-Owned Agent Launcher Settings](2026-07-24-operator-owned-agent-launcher-settings.md) | accepted | backend, frontend, protocol | 2026-07-24 | -| 2026-08-05-plugin-native-integration-settings | [Plugins Contribute Native Integration Settings](2026-08-05-plugin-native-integration-settings.md) | accepted | frontend, protocol | 2026-08-05 | -| 2026-08-06-plugin-code-host-dashboard-parity | [Code-Host Plugins Reuse Native Dashboard Primitives](2026-08-06-plugin-code-host-dashboard-parity.md) | accepted | frontend, protocol | 2026-08-06 | -| 2026-08-10-plugin-change-request-mutations | [Route Native Change-Request Mutations Through Providers](2026-08-10-plugin-change-request-mutations.md) | accepted | frontend, protocol | 2026-08-10 | -| 2026-08-12-plugin-localization-contract | [Host-Scoped Plugin Localization](2026-08-12-plugin-localization-contract.md) | accepted | frontend, protocol | 2026-08-12 | -| 2026-07-18-turn-configuration-snapshots | [Attribute runtime configuration to turns](2026-07-18-turn-configuration-snapshots.md) | accepted (amended 2026-08-13) | backend, frontend | 2026-07-18 | -| 2026-07-22-gpg-signed-release-tags | [GPG-signed release tags](2026-07-22-gpg-signed-release-tags.md) | accepted | infra, workflow | 2026-07-22 | -| 2026-07-19-reject-mcp-actions-on-raw-websocket | [Reject MCP Actions on the Raw WebSocket](2026-07-19-reject-mcp-actions-on-raw-websocket.md) | accepted | backend, protocol | 2026-07-19 | -| 2026-07-19-workspace-symlink-entries | [Treat Nested Workspace Symlinks as Entries](2026-07-19-workspace-symlink-entries.md) | accepted | backend, infra | 2026-07-19 | -| 0047 | [Separate GitHub deployment, workspace automation, and personal identities](0047-github-authentication-ownership.md) | accepted | backend, frontend, security | 2026-07-19 | -| 2026-07-20-managed-github-app-registration | [Manage Self-Hosted GitHub App Registration at Runtime](2026-07-20-managed-github-app-registration.md) | superseded | backend, frontend, security | 2026-07-20 | -| 2026-07-20-explicit-local-repository-trust | [Explicit Local Repository Trust](2026-07-20-explicit-local-repository-trust.md) | accepted | backend, frontend | 2026-07-20 | -| 2026-07-20-provider-neutral-remote-repositories | [Provider-neutral remote repositories](2026-07-20-provider-neutral-remote-repositories.md) | accepted | backend, frontend, protocol | 2026-07-20 | -| 2026-07-21-workspace-selectable-github-app-registrations | [Select GitHub App Registrations Per Workspace](2026-07-21-workspace-selectable-github-app-registrations.md) | accepted | backend, frontend, security | 2026-07-21 | -| 2026-07-20-repository-provider-origin-identity | [Persist Provider Origin In Repository Identity](2026-07-20-repository-provider-origin-identity.md) | accepted | backend, frontend | 2026-07-20 | -| 2026-07-21-portable-status-bar-order | [Portable Status Bar Order](2026-07-21-portable-status-bar-order.md) | accepted | backend, frontend, protocol | 2026-07-21 | -| 2026-07-21-work-item-reference-search | [Backend-normalized work-item references](2026-07-21-work-item-reference-search.md) | accepted | backend, frontend, protocol | 2026-07-21 | -| 2026-07-22-runtime-mutable-task-workspace-sources | [Runtime-Mutable Task Workspace Sources](2026-07-22-runtime-mutable-task-workspace-sources.md) | accepted (amended by 2026-07-27) | backend, frontend, protocol | 2026-07-22 | -| 2026-07-24-opt-in-authentication | [Opt-in Authentication and Per-User Workspace Scoping](2026-07-24-opt-in-authentication.md) | accepted | backend, frontend, protocol, security | 2026-07-24 | -| 2026-07-24-semantic-notification-events | [Semantic notification events come from domain occurrences](2026-07-24-semantic-notification-events.md) | accepted | backend, frontend, desktop | 2026-07-24 | -| 2026-07-26-user-managed-agent-runtime-updates | [User-Managed Agent Runtime Updates](2026-07-26-user-managed-agent-runtime-updates.md) | superseded by 2026-08-12-validated-managed-runtime-version-selection | backend, frontend, protocol | 2026-07-26 | -| 2026-08-12-validated-managed-runtime-version-selection | [Validate and Persist Managed Runtime Version Selection](2026-08-12-validated-managed-runtime-version-selection.md) | accepted (amended 2026-08-21, 2026-08-24, and by 2026-09-07) | backend, frontend, protocol, workflow | 2026-08-12 | -| 2026-09-07-host-utility-managed-runtime-recovery | [Recover Host Capability Probes Before Publishing Failure](2026-09-07-host-utility-managed-runtime-recovery.md) | accepted | backend, agentctl, protocol, security | 2026-09-07 | -| 2026-07-26-single-session-model-switching | [Single-Session Model Switching](2026-07-26-single-session-model-switching.md) | accepted (amended 2026-07-27) | workflow, infra | 2026-07-26 | -| 2026-07-27-task-git-credential-policy | [Separate GitHub Automation From Task Git Credential Policy](2026-07-27-task-git-credential-policy.md) | accepted | backend, frontend, security | 2026-07-27 | -| 2026-07-27-spa-failure-containment-and-deployment-recovery | [SPA Failure Containment and Deployment Recovery](2026-07-27-spa-failure-containment-and-deployment-recovery.md) | accepted | frontend | 2026-07-27 | -| 2026-07-27-legacy-add-branch-live-rescan | [Preserve Live Rescan for Legacy Add Branch](2026-07-27-legacy-add-branch-live-rescan.md) | accepted | backend, protocol | 2026-07-27 | -| 2026-07-28-visible-wip-overflow-queues | [Separate Visible Queueing From WIP Admission](2026-07-28-visible-wip-overflow-queues.md) | proposed | backend, frontend, protocol, workflow | 2026-07-28 | -| 2026-08-12-queue-task-moves-at-wip-capacity | [Queue Task Moves at WIP Capacity](2026-08-12-queue-task-moves-at-wip-capacity.md) | accepted | backend, frontend, protocol, workflow | 2026-08-12 | -| 2026-08-15-subagent-context-schema-boundary | [Start with the execution-aware subagent schema](2026-08-15-subagent-context-schema-boundary.md) | accepted | backend | 2026-08-15 | -| 2026-08-15-portable-agent-configuration-bundles | [Use Explicit Portable Agent Configuration Bundles](2026-08-15-portable-agent-configuration-bundles.md) | accepted | backend, frontend, protocol, security | 2026-08-15 | -| 2026-08-15-executor-authoritative-model-selection | [Let the Executor Own Model Selection](2026-08-15-executor-authoritative-model-selection.md) | accepted | backend, frontend, protocol, persistence | 2026-08-15 | -| 2026-09-07-unique-model-variation-resolution | [Resolve Only One Advertised Model Variation](2026-09-07-unique-model-variation-resolution.md) | proposed | backend, frontend, protocol | 2026-09-07 | -| 2026-08-18-context-reset-preserves-runtime-configuration | [Preserve ACP Runtime Configuration Across Context Reset](2026-08-18-context-reset-preserves-runtime-configuration.md) | accepted | backend, protocol, workflow | 2026-08-18 | -| 2026-08-19-parent-authorized-child-workspace-sources | [Parent-authorized child workspace sources](2026-08-19-parent-authorized-child-workspace-sources.md) | accepted | backend, protocol, security | 2026-08-19 | -| 2026-08-24-task-snapshotted-branch-policies | [Snapshot Repository Branch Policies on Tasks](2026-08-24-task-snapshotted-branch-policies.md) | proposed | backend, frontend, persistence | 2026-08-24 | -| 2026-07-28-coarse-running-busy-signal | [Restore Coarse Running Prompt Admission](2026-07-28-coarse-running-busy-signal.md) | accepted | backend, frontend, protocol | 2026-07-28 | -| 2026-07-29-agent-stall-user-controlled-recovery | [Keep Agent Stall Recovery User Controlled](2026-07-29-agent-stall-user-controlled-recovery.md) | accepted | backend, frontend, protocol | 2026-07-29 | -| 2026-07-29-quarantine-retention-override | [Make Quarantine Retention Overridable but Visible](2026-07-29-quarantine-retention-override.md) | accepted | backend, frontend | 2026-07-29 | -| 2026-07-29-interactive-accent-surface-semantics | [Separate Brand Accent from Interactive Surface Fills](2026-07-29-interactive-accent-surface-semantics.md) | accepted | frontend | 2026-07-29 | -| 2026-07-30-embedded-editor-executor-capabilities | [Derive Embedded Editor Availability from the Active Executor](2026-07-30-embedded-editor-executor-capabilities.md) | accepted | backend, frontend, protocol | 2026-07-30 | -| 2026-07-30-session-owned-mcp-observability | [Keep MCP Attachment Evidence Session Owned](2026-07-30-session-owned-mcp-observability.md) | accepted (amended by 2026-08-30-dual-era-mcp-protocol) | backend, frontend, protocol, security | 2026-07-30 | -| 2026-07-30-file-backed-diagnostic-bundles | [File-backed diagnostic bundles](2026-07-30-file-backed-diagnostic-bundles.md) | accepted (amended 2026-08-23; backend file retention amended by 2026-08-22) | backend, frontend, infra, protocol, workflow | 2026-07-30 | -| 2026-07-30-runtime-task-state-before-running-event | [Publish Task State Before Running Session State](2026-07-30-runtime-task-state-before-running-event.md) | accepted | backend, frontend, protocol, workflow | 2026-07-30 | -| 2026-07-31-authenticated-plugin-actions | [Authenticated Plugin Actions](2026-07-31-authenticated-plugin-actions.md) | accepted | backend, frontend, protocol, security | 2026-07-31 | -| 2026-07-31-plugin-repository-provider-extensions | [Plugin Repository Provider Extensions](2026-07-31-plugin-repository-provider-extensions.md) | accepted | frontend, backend, protocol | 2026-07-31 | -| 2026-07-31-provider-neutral-git-credential-broker | [Provider-Neutral Git Credential Broker](2026-07-31-provider-neutral-git-credential-broker.md) | accepted | backend, protocol, security | 2026-07-31 | -| 2026-08-26-server-owned-plugin-repository-task-resolution | [Resolve First-Use Plugin Repositories on the Server](2026-08-26-server-owned-plugin-repository-task-resolution.md) | accepted | backend, frontend, protocol, security, plugins | 2026-08-26 | -| 2026-08-01-bitbucket-initial-release-remains-unsigned | [Bitbucket Initial Release Remains Unsigned](2026-08-01-bitbucket-initial-release-remains-unsigned.md) | accepted | infra, workflow, security | 2026-08-01 | -| 2026-07-31-npm-nightly-release-channel | [Publish deterministic npm-only nightlies](2026-07-31-npm-nightly-release-channel.md) | accepted (amended 2026-08-03) | workflow, backend, frontend, cli | 2026-07-31 | -| 2026-07-31-isolate-manual-pr-review-content | [Isolate Manual PR Review Content](2026-07-31-isolate-manual-pr-review-content.md) | accepted | infra, workflow, security | 2026-07-31 | -| 2026-07-31-agent-generated-task-titles | [Bind Agent Title Generation to Pending Tasks](2026-07-31-agent-generated-task-titles.md) | accepted | backend, frontend, protocol | 2026-07-31 | -| 2026-07-31-system-service-user-continuity | [Preserve System Service Identity Across Reinstallation](2026-07-31-system-service-user-continuity.md) | accepted | backend, cli, security, operations | 2026-07-31 | -| 2026-08-01-workflow-session-original-configuration | [Keep Workflow Restoration Separate From Provider Defaults](2026-08-01-workflow-session-original-configuration.md) | accepted | backend, frontend, workflow | 2026-08-01 | -| 2026-08-01-repository-task-executor-defaults | [Resolve Task Executor Policy Before Last-Used Profile](2026-08-01-repository-task-executor-defaults.md) | accepted | frontend | 2026-08-01 | -| 2026-08-01-validate-mcp-tool-arguments | [Validate MCP Tool Arguments at the Shared Server Boundary](2026-08-01-validate-mcp-tool-arguments.md) | accepted | backend, protocol | 2026-08-01 | -| 2026-08-01-separate-task-summary-session-stream-traffic | [Separate Task Summary and Session Stream Traffic](2026-08-01-separate-task-summary-session-stream-traffic.md) | accepted | backend, frontend, protocol | 2026-08-01 | -| 2026-08-01-global-run-scheduler-ownership | [Separate Global Run Dispatch from Office Maintenance](2026-08-01-global-run-scheduler-ownership.md) | accepted | backend, workflow | 2026-08-01 | -| 2026-08-01-architecture-lint-budgets | [Architecture Lint Budgets and Compatibility Expiry](2026-08-01-architecture-lint-budgets.md) | accepted (amended 2026-08-02) | infra | 2026-08-01 | -| 2026-08-01-release-toggle-gating-contract | [Release Toggles Are Install-Wide Fail-Closed Gates](2026-08-01-release-toggle-gating-contract.md) | proposed | backend, frontend, workflow | 2026-08-01 | -| 2026-08-01-share-artifact-locale | [Shared-Task Artifacts Render in the Creator's Locale](2026-08-01-share-artifact-locale.md) | accepted | backend | 2026-08-01 | -| 2026-08-01-gitlab-mr-lifecycle-notifications | [GitLab MR Lifecycle Notifications](2026-08-01-gitlab-mr-lifecycle-notifications.md) | accepted | backend, frontend | 2026-08-01 | -| 2026-08-01-per-user-plugin-storage | [Host-Provided Per-User Plugin Storage](2026-08-01-per-user-plugin-storage.md) | accepted | backend, frontend, security | 2026-08-01 | -| 2026-08-11-composer-access-authenticated-webhooks | [Composer Access and Authenticated Webhooks](2026-08-11-composer-access-authenticated-webhooks.md) | accepted | frontend, backend, protocol, security | 2026-08-11 | -| 2026-08-01-plugin-task-panel-contributions | [Plugin Task Panel, Kanban Menu Action, and Card Indicator Contributions](2026-08-01-plugin-task-panel-contributions.md) | accepted | frontend | 2026-08-01 | -| 2026-08-02-new-workspace-github-access-defaults | [Bootstrap New Workspaces From Host GitHub Access](2026-08-02-new-workspace-github-access-defaults.md) | accepted | backend, frontend, security | 2026-08-02 | -| 2026-08-02-explicit-user-cancel-completion | [Explicit User Cancellation May Complete a Workflow Step](2026-08-02-explicit-user-cancel-completion.md) | accepted | workflow | 2026-08-02 | -| 2026-08-02-single-owner-agent-task-titles | [Assign Agent Task Titles to One Session](2026-08-02-single-owner-agent-task-titles.md) | accepted | backend, frontend, protocol, workflow | 2026-08-02 | -| 2026-08-02-agent-terminal-diagnostics-over-stderr | [Capture Agent Terminal Diagnostics From Managed Stderr](2026-08-02-agent-terminal-diagnostics-over-stderr.md) | accepted | backend, frontend, protocol, security | 2026-08-02 | -| 2026-08-07-allowlisted-provider-action-links | [Allowlisted Provider Action Links](2026-08-07-allowlisted-provider-action-links.md) | accepted | backend, frontend, protocol, security | 2026-08-07 | -| 2026-08-08-provider-neutral-agent-error-recovery | [Separate Agent Error Evidence From Recovery Policy](2026-08-08-provider-neutral-agent-error-recovery.md) | accepted (amended 2026-08-13 and 2026-08-17) | backend, frontend, protocol | 2026-08-08 | -| 2026-08-08-utility-agent-profile-execution | [Utility Agents Use Execution Profiles](2026-08-08-utility-agent-profile-execution.md) | accepted (amended 2026-08-14) | backend, frontend, protocol | 2026-08-08 | -| 2026-08-08-utility-profile-dependency-safety | [Warn Before Breaking Utility Profile Bindings](2026-08-08-utility-profile-dependency-safety.md) | accepted (amended 2026-08-14) | backend, frontend, protocol | 2026-08-08 | -| 2026-08-02-class-aware-git-subprocess-admission | [Class-Aware Git Subprocess Admission](2026-08-02-class-aware-git-subprocess-admission.md) | accepted | backend, agentctl, observability | 2026-08-02 | -| 2026-08-02-isolate-replaceable-session-stream-traffic | [Isolate Replaceable Session Stream Traffic](2026-08-02-isolate-replaceable-session-stream-traffic.md) | accepted | backend, frontend, protocol | 2026-08-02 | -| 2026-08-03-backend-owned-cancellation-progress | [Keep Cancellation Progress Backend Owned](2026-08-03-backend-owned-cancellation-progress.md) | accepted | backend, frontend, protocol | 2026-08-03 | -| 2026-08-03-separate-message-queue-provenance-cancellation-and-capacity | [Separate Message Queue Provenance, Cancellation, and Capacity](2026-08-03-separate-message-queue-provenance-cancellation-and-capacity.md) | accepted | backend, frontend, protocol, security | 2026-08-03 | -| 2026-08-03-provider-scoped-task-mcp-tools | [Derive Provider-Scoped Task MCP Tools in the Backend](2026-08-03-provider-scoped-task-mcp-tools.md) | accepted | backend, agentctl, protocol, integrations | 2026-08-03 | -| 2026-08-05-queue-send-now-replaces-turn | [Queue Send Now Replaces the Active Turn](2026-08-05-queue-send-now-replaces-turn.md) | accepted | backend, frontend, protocol, workflow | 2026-08-05 | -| 2026-08-16-server-owned-queue-auto-run | [Keep Queue Auto-run Server Owned](2026-08-16-server-owned-queue-auto-run.md) | accepted | backend, frontend, protocol, workflow | 2026-08-16 | -| 2026-08-04-file-backed-prompt-attachments | [File-backed prompt attachments](2026-08-04-file-backed-prompt-attachments.md) | accepted | backend, frontend, protocol, infra | 2026-08-04 | -| 2026-08-04-plugin-contribution-lifecycle-authority | [Make Plugin Contribution Lifecycle Authoritative](2026-08-04-plugin-contribution-lifecycle-authority.md) | accepted | frontend, security | 2026-08-04 | -| 2026-08-04-navigation-manifest-boundaries | [Centralize Navigation and Namespace Plugin Destinations](2026-08-04-navigation-manifest-boundaries.md) | accepted | frontend | 2026-08-04 | -| 2026-08-04-mid-turn-steering | [Deliver Operator Input Into a Generating Turn](2026-08-04-mid-turn-steering.md) | accepted | backend, frontend, protocol | 2026-08-04 | -| 2026-08-04-remote-contribution-bindings | [Bind Remote Contributions to Target Repositories](2026-08-04-remote-contribution-bindings.md) | accepted | backend, protocol, security, GitHub, GitLab | 2026-08-04 | -| 2026-08-03-scope-and-merge-repository-secrets | [Scope and Merge Repository Secrets](2026-08-03-scope-and-merge-repository-secrets.md) | accepted | backend, frontend, security, protocol | 2026-08-03 | -| 2026-08-05-server-owned-quick-terminal-descriptors | [Server-Owned Quick Terminal Descriptors](2026-08-05-server-owned-quick-terminal-descriptors.md) | accepted | backend, frontend, protocol, security | 2026-08-05 | -| 2026-08-05-nested-submodules-as-repository-scopes | [Model Nested Submodules as Repository Scopes](2026-08-05-nested-submodules-as-repository-scopes.md) | accepted | backend, frontend, protocol | 2026-08-05 | -| 2026-08-05-homebrew-remote-helper-audit | [Preserve Remote Helpers in Homebrew Installs](2026-08-05-homebrew-remote-helper-audit.md) | accepted | infra, workflow | 2026-08-05 | -| 2026-08-07-model-aware-provider-capability-resolution | [Model-aware provider capability resolution](2026-08-07-model-aware-provider-capability-resolution.md) | accepted | backend, frontend, protocol | 2026-08-07 | -| 2026-08-07-claude-allowlist-label-bridge | [Use the Claude Allowlist as a Trusted Preview Gate](2026-08-07-claude-allowlist-label-bridge.md) | accepted (amended by 2026-08-24-unified-fork-approval-label) | infra, workflow, security | 2026-08-07 | -| 2026-08-08-task-autopilot-contract | [Make Task Autopilot a Creation-Time Runtime Contract](2026-08-08-task-autopilot-contract.md) | accepted | backend, agentctl, frontend, protocol, workflow | 2026-08-08 | -| 2026-08-08-autopilot-mcp-question-capabilities | [Use One Question Capability Per Task Session](2026-08-08-autopilot-mcp-question-capabilities.md) | accepted | backend, agentctl, protocol | 2026-08-08 | -| 2026-08-08-mcp-tool-profiles | [Compose MCP Tool Profiles From Typed Context](2026-08-08-mcp-tool-profiles.md) | accepted | backend, agentctl, protocol, workflow | 2026-08-08 | -| 2026-08-08-agentctl-crash-containment | [Publish Immutable Agent Events and Explicit Runtime Failure State](2026-08-08-agentctl-crash-containment.md) | proposed | backend, frontend, protocol, operations | 2026-08-08 | -| 2026-08-08-workspace-scoped-task-create-workflow-memory | [Remember Task-Create Workflows Per Workspace](2026-08-08-workspace-scoped-task-create-workflow-memory.md) | accepted | backend, frontend | 2026-08-08 | -| 2026-08-08-owned-temp-artifact-cleanup | [Clean only registered Kandev temporary artifacts](2026-08-08-owned-temp-artifact-cleanup.md) | accepted | backend, frontend, infra, security | 2026-08-08 | -| 2026-08-08-task-owned-worktree-lifetime | [Keep Worktree Ownership at the Task Lifecycle](2026-08-08-task-owned-worktree-lifetime.md) | accepted | backend, frontend | 2026-08-08 | -| 2026-08-08-go-launcher-owns-all-launch-modes | [The Go Launcher Owns Every Entrypoint; apps/cli Is a Publish-Only Shim](2026-08-08-go-launcher-owns-all-launch-modes.md) | accepted | backend, cli, infra | 2026-08-08 | -| 2026-08-09-bind-automation-mutations-to-event-targets | [Bind Automation Mutations to Event Targets](2026-08-09-bind-automation-mutations-to-event-targets.md) | accepted | backend, agentctl, protocol, security, workflow | 2026-08-09 | -| 2026-08-09-exclusive-runtime-state-ownership | [Lock Runtime State Before Backend Startup](2026-08-09-exclusive-runtime-state-ownership.md) | accepted | backend, infra | 2026-08-09 | -| 2026-08-10-duration-aware-e2e-sharding | [Duration-aware E2E sharding uses rolling `main` timings](2026-08-10-duration-aware-e2e-sharding.md) | accepted | infra, workflow | 2026-08-10 | -| 2026-08-10-debug-launcher-profile-selection | [Keep Debug Launches on the Production Profile](2026-08-10-debug-launcher-profile-selection.md) | accepted | backend, frontend, cli | 2026-08-10 | -| 2026-08-11-plugin-tools-through-kandev-mcp | [Route Plugin Agent Tools Through Kandev MCP](2026-08-11-plugin-tools-through-kandev-mcp.md) | accepted | backend, agentctl, protocol, plugins, security | 2026-08-11 | -| 2026-08-11-live-agent-permission-authority | [Keep Pending Agent Permission Authority in the Live Runtime](2026-08-11-live-agent-permission-authority.md) | accepted | backend, agentctl, protocol, security | 2026-08-11 | -| 2026-08-10-remote-contribution-head-drift | [Separate Current Contribution and Local Checkout Histories](2026-08-10-remote-contribution-head-drift.md) | accepted (remote-action policy superseded, provider-error presentation amended) | backend, frontend, protocol, GitHub, GitLab | 2026-08-10 | -| 2026-08-12-local-first-contribution-replacement | [Keep Remote Contribution Work Local-First](2026-08-12-local-first-contribution-replacement.md) | accepted | backend, frontend, protocol, security, GitHub, GitLab | 2026-08-12 | -| 2026-08-13-provider-history-changes-enrichment | [Treat Provider History as Changes Enrichment](2026-08-13-provider-history-changes-enrichment.md) | accepted | frontend, GitHub, GitLab | 2026-08-13 | -| 2026-08-13-dynamic-agent-profile-routing | [Unify Provider Routing Behind Dynamic Agent Profiles](2026-08-13-dynamic-agent-profile-routing.md) | accepted (amended 2026-08-17) | backend, frontend, protocol, workflow | 2026-08-13 | -| 2026-08-17-provider-error-classes-and-policies | [Classify Provider Errors Before Applying Candidate Policy](2026-08-17-provider-error-classes-and-policies.md) | accepted | backend, frontend, protocol, workflow | 2026-08-17 | -| 2026-08-11-user-owned-status-bar-visibility | [Make Status Bar Visibility a Portable User Preference](2026-08-11-user-owned-status-bar-visibility.md) | accepted | backend, frontend, protocol | 2026-08-11 | -| 2026-08-12-built-in-utility-default-inheritance | [Built-in Utility Actions Inherit the Global Profile by Default](2026-08-12-built-in-utility-default-inheritance.md) | superseded by 2026-08-12-empty-utility-bindings-inherit-default | backend, frontend | 2026-08-12 | -| 2026-08-12-empty-utility-bindings-inherit-default | [Empty Built-in Utility Bindings Inherit the Default](2026-08-12-empty-utility-bindings-inherit-default.md) | accepted | backend, frontend | 2026-08-12 | -| 2026-08-12-setup-timeout-owns-launch-budget | [One Setup Timeout Owns Launch Budgets](2026-08-12-setup-timeout-owns-launch-budget.md) | accepted | backend | 2026-08-12 | -| 2026-08-10-no-em-dash-public-copy | [Keep Em Dashes Out of Public Copy](2026-08-10-no-em-dash-public-copy.md) | accepted | frontend, infra | 2026-08-10 | -| 2026-08-14-current-turn-clarification-ownership | [Current Turn Owns Active Clarification](2026-08-14-current-turn-clarification-ownership.md) | accepted (amended 2026-08-15, 2026-08-24) | backend, frontend, protocol, workflow | 2026-08-14 | -| 2026-08-12-task-bound-fork-destinations | [Bind Fork Push Destinations to Tasks](2026-08-12-task-bound-fork-destinations.md) | accepted (amended 2026-08-13) | backend, frontend, workflow, security, GitHub | 2026-08-12 | -| 2026-08-13-hard-delete-task-contribution-links | [Hard delete owns task contribution links](2026-08-13-hard-delete-task-contribution-links.md) | accepted | backend | 2026-08-13 | -| 2026-08-15-office-mode-follows-active-workspace | [Office Mode Follows the Active Workspace](2026-08-15-office-mode-follows-active-workspace.md) | accepted | frontend, backend | 2026-08-15 | -| 2026-08-16-session-mcp-tool-catalog | [Keep MCP Tool Catalogs Session Owned](2026-08-16-session-mcp-tool-catalog.md) | superseded by 2026-08-18-session-mcp-tool-definition-details | backend, agentctl, frontend, protocol, security | 2026-08-16 | -| 2026-08-18-session-mcp-tool-definition-details | [Bound MCP Tool Definition Details to Current Sessions](2026-08-18-session-mcp-tool-definition-details.md) | accepted | backend, agentctl, frontend, protocol, security | 2026-08-18 | -| 2026-08-17-separate-task-activity-from-summary-freshness | [Separate Task Activity From Summary Freshness](2026-08-17-separate-task-activity-from-summary-freshness.md) | accepted (amended 2026-08-29) | backend, frontend, protocol | 2026-08-17 | -| 2026-08-17-release-pr-ruleset-bypass | [Give Stable Release PRs an Administrator Token Bypass](2026-08-17-release-pr-ruleset-bypass.md) | accepted | infra, workflow, security | 2026-08-17 | -| 2026-08-18-executor-userns-security-options | [Executor Container Security Options for User Namespace Support](2026-08-18-executor-userns-security-options.md) | accepted | backend, security, docker | 2026-08-18 | -| 2026-08-18-never-started-agent-stall-terminal | [Treat Never-Started Agent Stalls as Terminal](2026-08-18-never-started-agent-stall-terminal.md) | accepted | backend, frontend, protocol | 2026-08-18 | -| 2026-08-18-plugin-task-row-metadata | [Keep Task Row Plugin Metadata Generic](2026-08-18-plugin-task-row-metadata.md) | accepted | frontend | 2026-08-18 | -| 2026-08-20-settings-prompt-editor-provider-ownership | [Settings Prompt Editors Own Monaco Completion Providers](2026-08-20-settings-prompt-editor-provider-ownership.md) | accepted | frontend | 2026-08-20 | -| 2026-08-14-kandev-native-agent-rich-output | [Keep Agent Rich Output Host Native](2026-08-14-kandev-native-agent-rich-output.md) | accepted | backend, frontend, protocol, security | 2026-08-14 | -| 2026-08-24-kubernetes-executor-resource-ownership | [Kubernetes Executor Resource Ownership](2026-08-24-kubernetes-executor-resource-ownership.md) | accepted | backend, frontend, infra, security | 2026-08-24 | -| 2026-08-19-repository-qualified-comparison-targets | [Qualify Git Comparison Targets by Repository](2026-08-19-repository-qualified-comparison-targets.md) | accepted | backend, agentctl, frontend, protocol, GitHub, GitLab | 2026-08-19 | -| 2026-08-31-deterministic-noninteractive-git-transport | [Keep Internal Git Transport Deterministic and Non-interactive](2026-08-31-deterministic-noninteractive-git-transport.md) | accepted | backend, agentctl, protocol, security, operations | 2026-08-31 | -| 2026-08-20-startup-configuration-source-parity | [Startup Configuration Uses One Typed Source Model](2026-08-20-startup-configuration-source-parity.md) | accepted | backend, agentctl, frontend, cli, security, operations | 2026-08-20 | -| 2026-08-20-acp-client-non-underscore-extension-methods | [Route Non-Underscore Inbound Client Methods to the Extension Handler](2026-08-20-acp-client-non-underscore-extension-methods.md) | accepted | backend, protocol | 2026-08-20 | -| 2026-08-22-persistent-fork-approval-labels | [Persist Fork Approval Labels Across Pushes](2026-08-22-persistent-fork-approval-labels.md) | accepted (amended by 2026-08-24-unified-fork-approval-label) | infra, workflow, security | 2026-08-22 | -| 2026-08-22-plugin-version-retention | [Keep Exactly One Superseded Plugin Version](2026-08-22-plugin-version-retention.md) | accepted | backend | 2026-08-22 | -| 2026-08-22-user-configured-automation-continuity | [Let Users Configure Continuity, Not MCP Authority](2026-08-22-user-configured-automation-continuity.md) | accepted (amended by 2026-09-02-automation-self-archive) | backend, agentctl, frontend, protocol, security, workflow | 2026-08-22 | -| 2026-08-23-automation-target-modes | [Give Automations Explicit Hidden and Visible Task Targets](2026-08-23-automation-target-modes.md) | accepted | backend, frontend, protocol, workflow | 2026-08-23 | -| 2026-08-22-preserve-newest-bounded-backend-logs | [Preserve Newest Bounded Backend Logs](2026-08-22-preserve-newest-bounded-backend-logs.md) | accepted | backend, infra, operations | 2026-08-22 | -| 2026-08-12-plugin-webhook-auth-gate | [Require Auth for Plugin Webhooks Unless the Manifest Declares Them Public](2026-08-12-plugin-webhook-auth-gate.md) | accepted | backend, frontend, security | 2026-08-12 | -| 2026-08-22-system-oriented-specifications | [Organize specifications by system](2026-08-22-system-oriented-specifications.md) | accepted | workflow, infra | 2026-08-22 | -| 2026-08-22-pr-walkthrough-r2-hosting | [Host PR walkthrough HTML in Cloudflare R2](2026-08-22-pr-walkthrough-r2-hosting.md) | accepted | infra, workflow, security | 2026-08-22 | -| 2026-08-22-agent-owned-pr-walkthrough-rendering | [Keep PR walkthrough rendering agent owned and provider neutral](2026-08-22-agent-owned-pr-walkthrough-rendering.md) | superseded by 2026-08-22-pr-walkthrough-filesystem-runner | workflow, infra, security | 2026-08-22 | -| 2026-08-22-pr-walkthrough-filesystem-runner | [Use a Filesystem Contract for PR Walkthrough Runners](2026-08-22-pr-walkthrough-filesystem-runner.md) | accepted (amended 2026-08-23) | workflow, infra, security | 2026-08-22 | -| 2026-08-22-pr-walkthrough-description-link | [Own a top-level PR walkthrough callout](2026-08-22-pr-walkthrough-description-link.md) | accepted | workflow, infra, security, GitHub | 2026-08-22 | -| 2026-08-23-pr-walkthrough-short-urls | [Use 12-character SHA prefixes for PR walkthrough URLs](2026-08-23-pr-walkthrough-short-urls.md) | accepted | workflow, infra | 2026-08-23 | -| 2026-08-23-pr-walkthrough-workflow-provenance | [Use the workflow SHA for trusted PR walkthrough inputs](2026-08-23-pr-walkthrough-workflow-provenance.md) | accepted | workflow, infra, security | 2026-08-23 | -| 2026-09-05-pr-walkthrough-description-integrity | [Keep PR walkthrough description updates canonical and race-safe](2026-09-05-pr-walkthrough-description-integrity.md) | accepted | workflow, infra, GitHub | 2026-09-05 | -| 2026-08-24-opt-in-ssh-task-directory-reclamation | [Opt-in reclamation of remote SSH task directories](2026-08-24-opt-in-ssh-task-directory-reclamation.md) | accepted | backend, frontend, operations | 2026-08-24 | -| 2026-08-24-agentctl-local-managed-runtime-cache-repair | [Run cache repair where npm runs](2026-08-24-agentctl-local-managed-runtime-cache-repair.md) | accepted | backend, agentctl, protocol, security | 2026-08-24 | -| 2026-08-24-unified-fork-approval-label | [Use One Maintainer Approval Label for Contributor PR Automation](2026-08-24-unified-fork-approval-label.md) | accepted | infra, workflow, security | 2026-08-24 | -| 2026-08-25-required-worktree-refresh-fails-closed | [Required Worktree Refresh Fails Closed](2026-08-25-required-worktree-refresh-fails-closed.md) | accepted (amended 2026-08-31; local-worktree boundary superseded) | backend, security, operations | 2026-08-25 | -| 2026-08-25-server-owned-declarative-canvases | [Server-owned declarative canvases](2026-08-25-server-owned-declarative-canvases.md) | superseded by 2026-08-26-plugin-backed-web-app-canvases | backend, frontend, protocol, security | 2026-08-25 | -| 2026-08-26-plugin-backed-web-app-canvases | [Use plugin-backed web applications for canvases](2026-08-26-plugin-backed-web-app-canvases.md) | accepted (initial grants amended by 2026-09-10-canvas-creation-authority) | backend, frontend, protocol, plugins, security | 2026-08-26 | -| 2026-09-10-canvas-creation-authority | [Authorize the owner's initial canvas release](2026-09-10-canvas-creation-authority.md) | accepted | backend, protocol, security | 2026-09-10 | -| 2026-08-26-quick-chat-tab-order | [Store Quick Chat Tab Order as a User Preference](2026-08-26-quick-chat-tab-order.md) | accepted | backend, frontend, protocol | 2026-08-26 | -| 2026-08-26-quick-chat-agent-titles | [Apply Agent-Generated Titles to Quick Chat](2026-08-26-quick-chat-agent-titles.md) | accepted | backend, frontend, protocol | 2026-08-26 | -| 2026-08-27-bounded-agent-profile-recency | [Store Agent Profile Recency in Bounded Context Rows](2026-08-27-bounded-agent-profile-recency.md) | accepted | backend, frontend, protocol | 2026-08-27 | -| 2026-08-27-protect-deferred-launch-attribution | [Protect Deferred Launch Attribution](2026-08-27-protect-deferred-launch-attribution.md) | accepted | backend, protocol | 2026-08-27 | -| 2026-08-27-preserve-legacy-sqlite-before-default-initialization | [Preserve Legacy SQLite Data Before Default Initialization](2026-08-27-preserve-legacy-sqlite-before-default-initialization.md) | accepted | backend, cli, operations | 2026-08-27 | -| 2026-08-27-explicit-desktop-repository-discovery-roots | [Use Explicit Roots for Desktop Repository Discovery](2026-08-27-explicit-desktop-repository-discovery-roots.md) | proposed | desktop, backend, frontend, security, operations | 2026-08-27 | -| 2026-08-27-mixed-git-change-facets | [Preserve mixed Git changes as path facets](2026-08-27-mixed-git-change-facets.md) | accepted | backend, agentctl, frontend, protocol | 2026-08-27 | -| 2026-08-28-bind-github-auto-merge-attempts-to-reviewed-head | [Bind GitHub Auto-Merge Attempts to the Reviewed Head](2026-08-28-bind-github-auto-merge-attempts-to-reviewed-head.md) | accepted | backend, frontend, protocol, security, GitHub | 2026-08-28 | -| 2026-08-28-viewport-activation-owns-thread-streams | [Viewport Activation Owns Threads Session Streams](2026-08-28-viewport-activation-owns-thread-streams.md) | proposed | backend, frontend, protocol | 2026-08-28 | -| 2026-08-30-context-reset-quiesces-active-turn | [Quiesce Active Turns Before Context Reset](2026-08-30-context-reset-quiesces-active-turn.md) | accepted | backend, workflow | 2026-08-30 | -| 2026-08-30-empty-remote-bootstrap-publication | [Keep Empty Remote Bootstrap Local Until Publication](2026-08-30-empty-remote-bootstrap-publication.md) | accepted | backend, frontend, protocol, security | 2026-08-30 | -| 2026-08-30-bound-untracked-dependency-enumeration | [Bound Untracked Dependency Enumeration](2026-08-30-bound-untracked-dependency-enumeration.md) | accepted | backend | 2026-08-30 | -| 2026-08-30-dual-era-mcp-protocol | [Use One Dual-Era MCP Endpoint](2026-08-30-dual-era-mcp-protocol.md) | accepted | backend, agentctl, protocol, security | 2026-08-30 | -| 2026-08-30-e2e-browser-cache | [Cache host-runner E2E browser provisioning](2026-08-30-e2e-browser-cache.md) | accepted | infra, workflow | 2026-08-30 | -| 2026-08-31-generic-plugin-host-boundary | [Generic plugin Host boundary](2026-08-31-generic-plugin-host-boundary.md) | proposed | backend, frontend, protocol, security, workflow | 2026-08-31 | -| 2026-08-30-environment-owned-git-status | [Persist Current Git Status with the Task Environment](2026-08-30-environment-owned-git-status.md) | accepted | backend, frontend, protocol | 2026-08-31 | -| 2026-08-31-explicit-new-branch-session-recovery | [Require Explicit User Action Before Continuing a Session on a Replacement Branch](2026-08-31-explicit-new-branch-session-recovery.md) | accepted | backend, frontend, protocol | 2026-08-31 | -| 2026-09-10-worktree-metadata-recovery-boundary | [Bound Automatic Worktree Metadata Recovery](2026-09-10-worktree-metadata-recovery-boundary.md) | proposed | backend | 2026-09-10 | -| 2026-08-31-local-worktree-refresh-best-effort | [Local Worktree Refresh Is Best Effort](2026-08-31-local-worktree-refresh-best-effort.md) | accepted | backend, security, operations | 2026-08-31 | -| 2026-08-31-revoke-merge-approval-after-untrusted-push | [Revoke merge approval after an untrusted pull-request push](2026-08-31-revoke-merge-approval-after-untrusted-push.md) | accepted | workflow, security | 2026-08-31 | -| 2026-08-31-passthrough-running-publication | [Defer Passthrough Running Publication Until Guard Release](2026-08-31-passthrough-running-publication.md) | accepted | backend | 2026-08-31 | -| 2026-08-31-surface-owned-saved-task-views | [Keep Saved Task Views Surface Owned](2026-08-31-surface-owned-saved-task-views.md) | proposed | backend, frontend | 2026-08-31 | -| 2026-08-31-agent-aware-mcp-tool-names | [Preserve Canonical MCP Tool Names Through Agent Namespacing](2026-08-31-agent-aware-mcp-tool-names.md) | accepted | backend, agentctl, protocol | 2026-08-31 | -| 2026-08-31-workflow-profile-session-switch-policy | [Make Workflow Profile-Session Switching Explicit](2026-08-31-workflow-profile-session-switch-policy.md) | accepted | workflow | 2026-08-31 | -| 2026-09-01-server-owned-saved-prompt-expansion | [Keep Saved-Prompt Expansion Server-Owned](2026-09-01-server-owned-saved-prompt-expansion.md) | accepted | backend, frontend, protocol, security | 2026-09-01 | -| 2026-09-01-passthrough-initial-prompt-turn-boundary | [Keep Passthrough Initial Prompt State in Lifecycle](2026-09-01-passthrough-initial-prompt-turn-boundary.md) | accepted | backend, workflow | 2026-09-01 | -| 2026-09-02-automation-self-archive | [Permit Automation Self-Archive as Terminal Completion](2026-09-02-automation-self-archive.md) | accepted | backend, agentctl, protocol, security, workflow | 2026-09-02 | -| 2026-09-02-task-owned-plan-comments | [Persist Pending Plan Comments with the Task Plan](2026-09-02-task-owned-plan-comments.md) | accepted (amended 2026-09-09) | backend, frontend, protocol, persistence | 2026-09-02 | -| 2026-09-02-separate-mcp-startup-and-tool-budgets | [Separate MCP Startup and Tool-Call Budgets](2026-09-02-separate-mcp-startup-and-tool-budgets.md) | proposed | backend, agents | 2026-09-02 | -| 2026-09-03-separate-system-data-storage-pages | [Separate System Data and Storage Pages](2026-09-03-separate-system-data-storage-pages.md) | accepted | frontend | 2026-09-03 | -| 2026-09-04-generation-fenced-task-environment-ownership | [Fence Task Environment Ownership by Generation](2026-09-04-generation-fenced-task-environment-ownership.md) | accepted | backend | 2026-09-04 | -| 2026-09-04-use-repository-token-for-runtime-pin-prs | [Use the built-in Actions token for runtime pin PRs](2026-09-04-use-repository-token-for-runtime-pin-prs.md) | accepted | workflow, security | 2026-09-04 | -| 2026-09-05-required-internal-persistence | [Required internal persistence fails startup](2026-09-05-required-internal-persistence.md) | accepted | backend | 2026-09-05 | -| 2026-09-05-bounded-clarification-response-path | [Bound Clarification Responses with Indexed Lookup](2026-09-05-bounded-clarification-response-path.md) | accepted | backend, frontend, protocol | 2026-09-05 | -| 2026-09-05-agent-owned-credential-file-conflicts | [Agent-owned credential file conflicts](2026-09-05-agent-owned-credential-file-conflicts.md) | accepted | backend | 2026-09-05 | -| 2026-09-06-opt-in-external-e2e-runners | [Opt in selected Linux CI jobs to external runners](2026-09-06-opt-in-external-e2e-runners.md) | accepted | infra, workflow, security | 2026-09-06 | -| 2026-09-06-explicit-pr-auto-fix-outcomes | [Require Explicit Outcomes for PR Auto-Fix Attempts](2026-09-06-explicit-pr-auto-fix-outcomes.md) | proposed | backend, frontend, protocol, workflow, GitHub | 2026-09-06 | -| 2026-09-05-bounded-progressive-storage-analysis | [Use bounded progressive storage analysis](2026-09-05-bounded-progressive-storage-analysis.md) | accepted | backend, frontend, protocol | 2026-09-05 | -| 2026-09-04-inherit-queue-auto-merge-until-overridden | [Inherit Queue Auto-merge Until Overridden](2026-09-04-inherit-queue-auto-merge-until-overridden.md) | accepted | backend, frontend, protocol | 2026-09-04 | -| 2026-09-07-separate-runtime-permissions-and-advisory-actions | [Keep MCP availability separate from runtime permissions](2026-09-07-separate-runtime-permissions-and-advisory-actions.md) | accepted | backend, protocol | 2026-09-07 | -| 2026-09-07-isolate-fork-preview-builds | [Isolate contributor preview builds from deployment credentials](2026-09-07-isolate-fork-preview-builds.md) | accepted | infra, workflow, security | 2026-09-07 | -| 2026-09-05-script-capable-html-preview-isolation | [Capability-Free Runtime for Script-Capable HTML Preview](2026-09-05-script-capable-html-preview-isolation.md) | proposed | frontend, desktop, security | 2026-09-05 | -| 2026-09-05-trusted-browser-html-preview | [Treat HTML Preview as Trusted Workspace Code](2026-09-05-trusted-browser-html-preview.md) | accepted | frontend, backend, agentctl, security | 2026-09-05 | -| 2026-09-07-activate-managed-runtime-defaults | [Activate Shipped Managed Runtime Defaults](2026-09-07-activate-managed-runtime-defaults.md) | accepted | backend, frontend, protocol | 2026-09-07 | -| 2026-09-08-domain-owned-settings-catalog | [Discover settings through domain-owned contracts](2026-09-08-domain-owned-settings-catalog.md) | accepted | backend, frontend, protocol | 2026-09-08 | -| 2026-09-09-task-completion-conversation-availability | [Separate task completion from conversation availability](2026-09-09-task-completion-conversation-availability.md) | accepted | workflow | 2026-09-09 | -| 2026-09-09-count-application-files-for-pr-size | [Count Application Files for Pull Request Size](2026-09-09-count-application-files-for-pr-size.md) | accepted | workflow, infra | 2026-09-09 | -| 2026-09-10-mobile-confirmation-surfaces | [Focus mobile confirmation in one surface](2026-09-10-mobile-confirmation-surfaces.md) | accepted | frontend | 2026-09-10 | -| 2026-09-11-contribution-resume-preflight | [Separate resume admission from push history readiness](2026-09-11-contribution-resume-preflight.md) | proposed | backend, protocol, security | 2026-09-11 | +## Find decisions + +Run the catalog command from the repository root: + + python3 scripts/list-docs.py decisions --format markdown + +Use filters when you need a smaller result: + + python3 scripts/list-docs.py decisions --status accepted --format paths + python3 scripts/list-docs.py decisions --area backend --format markdown + python3 scripts/list-docs.py decisions --text restart --format json + +The command sorts numeric and date-prefixed decision IDs in a stable order. +Use paths for shell tools and JSON for structured consumers. + +## Validate decisions + +Run the repository validation command before you commit documentation changes: + + python3 scripts/list-docs.py validate + +The command reads status, date, and area metadata from each ADR. It reports +invalid metadata and duplicate catalog identities. It does not rewrite files. + +## Create a decision + +Use the record skill or follow the ADR format in +0001-file-based-knowledge-system.md. Use the complete filename stem as the +stable decision ID. New decisions use a date-prefixed filename so branches do +not reserve a shared sequence number. diff --git a/docs/plans/docs-catalog-discovery/plan.md b/docs/plans/docs-catalog-discovery/plan.md new file mode 100644 index 0000000000..c44942b89f --- /dev/null +++ b/docs/plans/docs-catalog-discovery/plan.md @@ -0,0 +1,131 @@ +--- +created: 2026-09-07 +status: complete +requirements: [] +system_design: [] +--- + +# Implementation Plan: On-demand documentation catalogs + +## Overview + +Replace conflict-prone decision and specification lists with one on-demand +catalog command. Keep static entry pages and durable system boundaries in +Markdown. Derive all document listings from filenames, paths, headings, and +metadata. + +This work changes repository authoring only. It does not change Kandev product +behavior. The design package therefore has no product requirement or system +design documents. ADR-2026-09-07-on-demand-document-catalogs records the durable +repository rule. + +All work lands in one pull request. The tasks are sequential because they share +the command contract, documentation, and validation workflow. + +## Scope + +### In scope + +- Add one Python command with `decisions` and `specs` catalog views. +- Filter decisions by status, area, and text. +- Filter specifications by system, document kind, status, and text. +- Support Markdown, path-only, and JSON output. +- Add deterministic sorting, metadata validation, and focused unit tests. +- Replace the decision and specification indexes with static entry pages. +- Remove derived specification maps from every system README. +- Update specification guides, templates, agent guidance, and relevant skills. +- Run catalog validation in pre-commit and CI without rewriting files. + +### Out of scope + +- Generated catalog files committed to the repository. +- A bot or post-merge pull request. +- A complete ADR or specification metadata-format migration. +- Public documentation navigation in `docs/public/meta.json`. +- Public documentation ownership in `docs/public/coverage.json`. +- A repository-wide plans catalog or changes to initiative plan layout. +- Product behavior, application code, or browser end-to-end tests. + +## Technical approach + +Add `scripts/list-docs.py` as the author-facing command. Keep decision and +specification parsing separate inside the command. Share only filtering, +formatting, and error reporting. + +For decisions, derive the identifier from the filename. Read the title from the +first ADR heading. Read status, date, and area from the existing metadata block. +Normalize the leading status class for filtering, but preserve the complete +status text in output. Sort numeric identifiers by number, then sort dated +identifiers by filename. + +For specifications, derive the system and document kind from the path. Read the +title and current frontmatter fields. Keep path classification, frontmatter +parsing, and status sets in the shared `scripts/spec_metadata.py` helper used by +both `scripts/list-docs.py` and `scripts/lint-spec-files.py`. The catalog owns +filtering and output formats. It does not become a second source of +specification policy. Recognized catalog kinds are `system`, `glossary`, +`requirement`, `system-design`, `product`, and `legacy`. + +The command exits with a nonzero status for malformed metadata, duplicate +catalog identities, unsupported filter values, or unreadable source files. An +explicit validation mode checks both trees without printing a catalog. + +Use Markdown for terminal-friendly discovery, paths for shell composition, and +JSON for structured consumers. Escape generated Markdown cells. Keep JSON keys +stable and sort output before formatting. + +Static index pages contain purpose, document format, and command examples. A +system README keeps durable ownership and migration information. It does not +repeat the files below its own directory. + +## Test strategy + +Focused Python tests use temporary document trees. They cover parsing, sorting, +filters, output formats, Markdown escaping, malformed metadata, duplicate +identities, empty results, and parity across all specification source kinds. +Repository validation then proves that the real decision and specification +trees satisfy the command contract. + +The existing specification linter stays authoritative for specification +structure and size rules. Harness lint covers changed agent instructions and +skills. No application or end-to-end tests apply. + +## Work orders + +- [x] [Task 01: Build the documentation catalog command](task-01-build-catalog-command.md) +- [x] [Task 02: Replace tracked derived catalogs](task-02-replace-derived-catalogs.md) +- [x] [Task 03: Wire authoring guidance and validation](task-03-wire-authoring-validation.md) + +## Verification + +```bash +python3 scripts/list-docs.test.py +python3 scripts/list-docs.py validate +python3 scripts/list-docs.py decisions --status accepted --format markdown +python3 scripts/list-docs.py specs --system ui --kind requirement --format paths +python3 scripts/lint-spec-files.test.py +python3 scripts/lint-spec-files.py --all +python3 scripts/lint-harness-files.test.py +python3 .github/scripts/lint-harness-files.py --all +pre-commit run docs-catalog --all-files +git diff --check +``` + +All listed commands passed on 2026-09-07. + +## Risks + +- ADR metadata has older variants. Tests must cover the forms present in the + repository before the tracked table is removed. +- A catalog parser can drift from the linter. Keep path classification, + frontmatter parsing, and status sets in the shared helper. Test all source + kinds against representative files. +- Removing maps can remove useful ownership context. Keep durable boundary and + migration text in every system README. +- Existing links can target table rows or map sections. Search and update these + references before removing the sections. + +## Rollback + +Revert the pull request. The source decision and specification files remain +unchanged, so the previous tracked tables can be restored without data loss. diff --git a/docs/plans/docs-catalog-discovery/task-01-build-catalog-command.md b/docs/plans/docs-catalog-discovery/task-01-build-catalog-command.md new file mode 100644 index 0000000000..6de6852fc8 --- /dev/null +++ b/docs/plans/docs-catalog-discovery/task-01-build-catalog-command.md @@ -0,0 +1,110 @@ +--- +id: "01-build-catalog-command" +title: "Build the documentation catalog command" +status: done +wave: 1 +depends_on: [] +plan: "plan.md" +requirements: [] +acceptance_criteria: [] +system_design: [] +--- + +# Task 01: Build the documentation catalog command + +## Summary + +Add one tested Python command that discovers architecture decisions and +specifications from repository source files. + +## In scope + +- Add `scripts/list-docs.py` with `decisions`, `specs`, and `validate` + subcommands. +- Add decision filters for status, area, and case-insensitive text. +- Add specification filters for system, kind, status, and case-insensitive + text. +- Add Markdown, path-only, and JSON output. +- Add deterministic sorting and actionable validation errors. +- Add focused tests in `scripts/list-docs.test.py`. + +## Out of scope + +- Editing any tracked documentation catalog. +- Changing the metadata format of existing documents. +- Adding a Python package dependency. + +## Implementation details + +Use only the Python standard library. Accept an internal root override in tests +so fixtures use temporary directories. Keep repository paths relative in all +output and errors. + +Decision parsing must support metadata forms already present in the repository. +Use the filename stem as the identifier. Use the first ADR heading as the title. +Read status, date, and area from the metadata block. Filter status by its leading +class, such as `accepted`, while displaying the complete value. + +Specification parsing derives `system` and `kind` from the path. Recognized +kinds are `system`, `glossary`, `requirement`, `system-design`, `product`, and +`legacy`. Both the catalog and the specification linter use +`scripts/spec_metadata.py` for path classification, frontmatter parsing, and +status sets. + +The JSON output contains a top-level schema version and an ordered `documents` +array. Each item contains the common path, title, and type fields plus the +type-specific metadata. Empty filters return an empty successful result. + +## Acceptance + +- The command finds every valid decision and specification source file. +- Repeated runs on the same tree produce byte-identical output. +- Every documented filter works alone and with other filters. +- Each output format represents the same ordered result set. +- Invalid metadata returns a nonzero exit status and identifies the file. +- Tests cover existing ADR metadata variants, every specification source kind, + and specification frontmatter errors. + +## Verification + +```bash +python3 scripts/list-docs.test.py +python3 scripts/list-docs.py validate +python3 scripts/list-docs.py decisions --status accepted --format markdown +python3 scripts/list-docs.py specs --system ui --kind requirement --format paths +``` + +## Files likely touched + +- `scripts/list-docs.py` +- `scripts/list-docs.test.py` +- `scripts/spec_metadata.py` +- `scripts/lint-spec-files.py` + +## Dependencies + +None. + +## Risks + +- Loose ADR parsing can hide malformed files. Keep accepted variants explicit + and reject ambiguous metadata. +- Markdown titles can contain table delimiters. Escape cells in the formatter. + +## Parallelism + +`sequential` + +## Inputs + +- `docs/decisions/*.md` +- `docs/specs/**/*.md` +- `scripts/lint-spec-files.py` +- `docs/decisions/2026-09-07-on-demand-document-catalogs.md` + +## Results + +Done. The catalog command discovers every supported decision and specification +source kind. Product documents and valid glossaries are not legacy sources. +Malformed system README metadata fails validation with the source path. The +focused tests, repository validation, and documented filter examples pass. diff --git a/docs/plans/docs-catalog-discovery/task-02-replace-derived-catalogs.md b/docs/plans/docs-catalog-discovery/task-02-replace-derived-catalogs.md new file mode 100644 index 0000000000..0c4e523c30 --- /dev/null +++ b/docs/plans/docs-catalog-discovery/task-02-replace-derived-catalogs.md @@ -0,0 +1,121 @@ +--- +id: "02-replace-derived-catalogs" +title: "Replace tracked derived catalogs" +status: done +wave: 2 +depends_on: ["01-build-catalog-command"] +plan: "plan.md" +requirements: [] +acceptance_criteria: [] +system_design: [] +--- + +# Task 02: Replace tracked derived catalogs + +## Summary + +Remove tracked lists that the catalog command can derive. Keep static entry +pages and durable system ownership text. + +## In scope + +- Replace `docs/decisions/INDEX.md` with a short decision-log entry page. +- Replace `docs/specs/INDEX.md` with a short specification-catalog entry page. +- Remove exhaustive specification maps from every system README. +- Keep each system README purpose, scope, ownership, exclusions, migration + record, and related-system links. +- Add concise command examples for common catalog searches. +- Update specification guides and the system README template. +- Mark ADR-0001 and ADR-2026-08-22-system-oriented-specifications as amended by + the catalog decision. +- Repair links that target removed table rows or map sections. +- Replace the product README's per-file document list with a catalog command. +- Audit active specification sources for references to removed index rows and + stale "above" list wording. + +## Out of scope + +- Rewriting requirements or system designs. +- Changing public documentation navigation or coverage data. +- Removing curated prose from system README files. + +## Implementation details + +Do not commit command output. The two index files explain how to find current +documents with `scripts/list-docs.py`. + +Identify system README files from their frontmatter, not from a fixed directory +list. Remove only sections that enumerate requirement or system-design files. +Preserve migration history and boundary statements even when those sections +contain links. + +Update these authoring sources where they describe tracked indexes or maps: + +- `docs/specs/README.md` +- `docs/specs/guide/structure-and-ownership.md` +- `docs/specs/guide/requirements.md` +- `docs/specs/guide/traceability-and-lifecycle.md` +- `docs/specs/templates/system-readme.md` + +## Acceptance + +- Adding one ADR does not require an edit to any existing documentation file. +- Adding one requirement or system design does not require an index or map edit. +- Both static index pages show working list and filter examples. +- Every system README retains its durable ownership and migration information. +- No repository guidance points authors to a removed table or map. +- The real repository passes catalog and specification validation. + +## Verification + +```bash +python3 scripts/list-docs.py validate +python3 scripts/list-docs.py decisions --format markdown +python3 scripts/list-docs.py specs --format markdown +python3 scripts/lint-spec-files.test.py +python3 scripts/lint-spec-files.py --all +rg -n "Specification map|add.*INDEX|update.*INDEX" docs AGENTS.md .agents +! rg -n -i "docs/specs/INDEX\.md.*(row|status)|INDEX\.md.*row|the (seven|[0-9]+|current|listed) requirements? above|the (seven|[0-9]+|current|listed) system[- ]designs? above" docs/specs AGENTS.md .agents +git diff --check -- docs/decisions docs/specs docs/plans +``` + +## Files likely touched + +- `docs/decisions/INDEX.md` +- `docs/decisions/0001-file-based-knowledge-system.md` +- `docs/decisions/2026-08-22-system-oriented-specifications.md` +- `docs/specs/INDEX.md` +- `docs/specs/README.md` +- `docs/specs/*/README.md` +- `docs/specs/guide/*.md` +- `docs/specs/templates/system-readme.md` + +## Dependencies + +- Task 01 supplies the command referenced by the static pages. + +## Risks + +- A broad README edit can remove curated context. Review each changed section + and keep all non-derived content. +- Old links can still resolve while pointing to obsolete instructions. Search + both link targets and authoring language. + +## Parallelism + +`sequential` + +## Inputs + +- `docs/decisions/2026-09-07-on-demand-document-catalogs.md` +- `scripts/list-docs.py` +- `docs/decisions/INDEX.md` +- `docs/specs/INDEX.md` +- `docs/specs/*/README.md` + +## Results + +Done. Both root catalog pages are static entry pages, all derived system +README maps and the product per-file list are removed, and active source +references use on-demand discovery. The specification and catalog validation +checks pass. diff --git a/docs/plans/docs-catalog-discovery/task-03-wire-authoring-validation.md b/docs/plans/docs-catalog-discovery/task-03-wire-authoring-validation.md new file mode 100644 index 0000000000..e415655dc0 --- /dev/null +++ b/docs/plans/docs-catalog-discovery/task-03-wire-authoring-validation.md @@ -0,0 +1,114 @@ +--- +id: "03-wire-authoring-validation" +title: "Wire authoring guidance and validation" +status: done +wave: 3 +depends_on: ["02-replace-derived-catalogs"] +plan: "plan.md" +requirements: [] +acceptance_criteria: [] +system_design: [] +--- + +# Task 03: Wire authoring guidance and validation + +## Summary + +Make on-demand discovery the repository authoring rule. Run validation in local +hooks and CI without generating or changing files. + +## In scope + +- Update root agent guidance to use the catalog command. +- Update the record, specification, planning, fix, and context-engineering + skills where they require tracked index edits or reads. +- Add a `docs-catalog` pre-commit hook that runs repository validation. +- Run catalog tests and validation in the existing harness lint workflow. +- Confirm that normal ADR and specification additions do not modify shared + catalog files. + +## Out of scope + +- Automatic file generation or formatting. +- A bot, scheduled job, or post-merge workflow. +- Changes to unrelated skill behavior. + +## Implementation details + +The pre-commit hook uses `python3 scripts/list-docs.py validate`. Configure its +file match for decisions, specifications, the catalog command, the shared +metadata helper, and the specification linter. It must not pass filenames +because validation checks cross-file identities. + +The CI workflow first runs `scripts/list-docs.test.py`, then validates the real +repository. Keep the checks in the existing lightweight harness lint job. + +Update instructions to distinguish discovery from durable navigation. Authors +use the command for ADR and specification lists. They continue to edit curated +public navigation and coverage files when those contracts change. + +## Acceptance + +- Pre-commit rejects invalid catalog metadata and never rewrites files. +- Changes to the specification linter or shared metadata helper run catalog + validation as well. +- CI runs focused catalog tests and full repository validation. +- Agent guidance no longer tells authors to add decision rows or specification + map entries. +- Planning and context skills use filtered catalog commands for discovery. +- Public navigation and coverage guidance remains manual and explicit. +- Harness, specification, and catalog checks all pass. + +## Verification + +```bash +python3 scripts/list-docs.test.py +python3 scripts/list-docs.py validate +python3 scripts/lint-harness-files.test.py +python3 .github/scripts/lint-harness-files.py --all +python3 scripts/lint-spec-files.test.py +python3 scripts/lint-spec-files.py --all +pre-commit run docs-catalog --all-files +git diff --check -- .pre-commit-config.yaml .github AGENTS.md .agents docs +``` + +## Files likely touched + +- `AGENTS.md` +- `.agents/skills/record/SKILL.md` +- `.agents/skills/spec/SKILL.md` +- `.agents/skills/plan/SKILL.md` +- `.agents/skills/fix/SKILL.md` +- `.agents/skills/context-engineering/SKILL.md` +- `.pre-commit-config.yaml` +- `.github/workflows/lint-harness-files.yml` +- `scripts/spec_metadata.py` + +## Dependencies + +- Task 01 supplies validation. +- Task 02 establishes the static documentation model. + +## Risks + +- One stale skill can recreate shared-file edits. Search all harness files for + index and specification-map instructions. +- A narrow hook pattern can miss new document paths. Include both complete + documentation trees and the command files. + +## Parallelism + +`sequential` + +## Inputs + +- `docs/decisions/2026-09-07-on-demand-document-catalogs.md` +- `scripts/list-docs.py` +- `.pre-commit-config.yaml` +- `.github/workflows/lint-harness-files.yml` + +## Results + +Done. Agent guidance, skills, pre-commit, and harness CI use read-only catalog +validation. The specification skill includes the catalog check. Harness, +specification, catalog, reference-audit, and whitespace checks pass. diff --git a/docs/specs/INDEX.md b/docs/specs/INDEX.md index 69b112dbeb..78d9d736a1 100644 --- a/docs/specs/INDEX.md +++ b/docs/specs/INDEX.md @@ -1,59 +1,51 @@ -# Specification catalog +# Specification Catalog -This catalog is the entry point for the system-oriented specification layout. Each system README defines ownership, exclusions, and links to its canonical requirements and system designs. +Kandev specifications describe product intent, required behavior, and system +design. System README files define durable boundaries. Requirement and +system-design files define the owned contracts. -## Systems +This page is a static entry page. It does not contain a generated list of +systems or documents. The specification files are the source of truth. -| System | Index | Migration | Canonical documents | -| ------------ | -------------------------------- | ----------- | ---------------------------- | -| Agents | [README](agents/README.md) | complete | 27 requirements, 17 designs | -| Auth | [README](auth/README.md) | complete | 7 requirements, 2 designs | -| CLI | [README](cli/README.md) | complete | 3 requirements, 1 designs | -| Costs | [README](costs/README.md) | complete | 2 requirements, 0 designs | -| Desktop | [README](desktop/README.md) | complete | 1 requirements, 1 designs | -| Executors | [README](executors/README.md) | complete | 3 requirements, 6 designs | -| Integrations | [README](integrations/README.md) | complete | 18 requirements, 21 designs | -| Office | [README](office/README.md) | complete | 19 requirements, 38 designs | -| Platform | [README](platform/README.md) | complete | 30 requirements, 10 designs | -| Plugins | [README](plugins/README.md) | complete | 7 requirements, 9 designs | -| Release | [README](release/README.md) | complete | 5 requirements, 0 designs | -| System page | [README](system-page/README.md) | complete | 3 requirements, 5 designs | -| Tasks | [README](tasks/README.md) | complete | 69 requirements, 12 designs | -| UI | [README](ui/README.md) | in_progress | 127 requirements, 56 designs | -| Workspaces | [README](workspaces/README.md) | complete | 11 requirements, 3 designs | +## Find specifications -## Migration record +Run the catalog command from the repository root: -The legacy specification sources were migrated from the unstructured root and category directories into the system-oriented layout. Task and workflow sources from PR #2957 remain under `tasks/`; three task-owned sources found outside that tree were folded into the same system during this migration. + python3 scripts/list-docs.py specs --format markdown ---- +Use filters for common discovery tasks: -The former legacy size exceptions for migrated sources were removed. All canonical requirement and system-design documents now pass the repository specification linter. + python3 scripts/list-docs.py specs --system ui --kind requirement --format paths + python3 scripts/list-docs.py specs --status active --format markdown + python3 scripts/list-docs.py specs --text workflow --format json -## Unmigrated additions +The command recognizes these kinds: -The following specifications were added after this migration and remain in the legacy layout until they move into an owning system: +- system: a system boundary README with specification frontmatter. +- glossary: a system glossary.md file. +- requirement: a document under a system requirements directory. +- system-design: a document under a system system-design directory. +- product: a product-wide document under docs/specs/product/. +- legacy: a document that remains outside the migrated layout. -- [Task Cost & Token Ledger](task-cost-ledger/spec.md) (draft) -- [Multi-tenancy](multi-tenancy/spec.md) (draft) -- [Startup listener before recovery](startup-listener-before-recovery/spec.md) (draft) -- [Workflow on_enter action dispatch](workflow-on-enter-action-dispatch/spec.md) (draft) -- [Kubernetes Executor](kubernetes-executor/spec.md) (implemented) -- [Task Delivery Ledger](task-delivery-ledger/spec.md) (draft) -- [Waiting Attribution](disambiguate-waiting/spec.md) (implemented) -- [ACP Form Elicitation](acp-elicitation/spec.md) (draft) -- [Parked-Session Notification Deferral](parked-notification-deferral/spec.md) (draft) -- [Workflow Engine Operation Ledger Lifetime](workflow-engine-operation-ledger-lifetime/spec.md) (draft) +Use paths for shell tools and JSON for structured consumers. The command +sorts results deterministically and searches document text without changing +the source files. + +## Validate specifications + +Run both repository checks before you commit specification changes: + + python3 scripts/list-docs.py validate + python3 scripts/lint-spec-files.py --all + +The catalog validates the metadata it needs for discovery. The specification +linter remains authoritative for IDs, cross-references, migration rules, and +file-size limits. ## Authoring rule -- **Spec layout.** Umbrella specs live as flat `.md` files under the umbrella directory (`docs/specs/office/agents.md`). Standalone specs use a folder (`docs/specs/improve-kandev/spec.md`). -- **Plans are not specs.** Implementation plans are committed under `docs/plans//` with individual sibling task files named `task--.md`. Specs are the durable requirements; plans and task files are implementation records for the current buildout. -- **Bug fixes are not specs.** Bugs produce a regression test plus an ADR if they encoded a new convention. See `/fix` skill. -- **Architecture decisions are not specs.** ADRs live under `docs/decisions/`. See `/record decision`. +Keep system purpose, ownership, exclusions, migration history, and related +links in each system README. Do not add catalog rows to this page or repeat +requirement and system-design lists in a system README. -## Cross-references - -- ADRs: [`../decisions/INDEX.md`](../decisions/INDEX.md) -- Spec workflow: [`.agents/skills/spec/SKILL.md`](../../.agents/skills/spec/SKILL.md) -- Bug-fix workflow: [`.agents/skills/fix/SKILL.md`](../../.agents/skills/fix/SKILL.md) diff --git a/docs/specs/README.md b/docs/specs/README.md index 04d188c6ce..780c1543d4 100644 --- a/docs/specs/README.md +++ b/docs/specs/README.md @@ -19,9 +19,9 @@ docs/specs/ Read the [specification guide](guide/README.md) before you create or change a specification. Use the files in [templates](templates) for new documents. -The [specification catalog](INDEX.md) is the entry point for the completed -system-oriented layout. Each system README names its authoritative requirements -and system designs. +The [specification catalog entry page](INDEX.md) explains how to query current +documents. Run the catalog command instead of maintaining a tracked document +list. Each system README defines its durable boundary and related systems. Plans and work orders are in [`docs/plans`](../plans). Architecture decisions are in [`docs/decisions`](../decisions). Public user documentation is in diff --git a/docs/specs/agents/README.md b/docs/specs/agents/README.md index 27916d2c1a..d4011e84ef 100644 --- a/docs/specs/agents/README.md +++ b/docs/specs/agents/README.md @@ -28,89 +28,16 @@ surface shared by task and Office consumers. system](../office/README.md). - Presentation-only behavior belongs to the [UI system](../ui/README.md). -## Specification map - -### Requirements - -- [Agent Resume and Runtime Recovery](requirements/agent-resume-runtime-recovery.md) -- [Session recovery failures](requirements/session-recovery-failures.md) -- [Agent Rich Output](requirements/agent-rich-output.md) -- [Google Antigravity ACP Agent](requirements/antigravity-acp-agent.md) -- [Agent Stall Recovery](requirements/agent-stall-recovery.md) -- [Collapsible Agent Blocks on the Agents Settings Page](requirements/collapsible-agent-blocks.md) -- [Cursor Subagent Metadata](requirements/cursor-subagent-metadata.md) -- [Dynamic Agent Routing Rollout Blockers](requirements/dynamic-agent-routing-rollout-blockers.md) -- [Dynamic Agent Routing](requirements/dynamic-agent-routing.md) -- [Dynamic Provider Model Options](requirements/dynamic-provider-options.md) -- [External Agent Permission Resolution](requirements/external-permission-resolution.md) -- [Agent Git permission boundary](requirements/git-operations-permission-boundary.md) -- [Agent Creation Governance](requirements/governance.md) -- [Granular Agent Permissions](requirements/granular-permissions.md) -- [Hide Disabled Agent Profiles from Left Panel Navigation](requirements/hide-disabled-profiles-nav.md) -- [Injected Skill Naming](requirements/injected-skill-naming.md) -- [Agent MCP Timeout Budgets](requirements/mcp-timeout-budgets.md) -- [Mock-agent slow command duration syntax](requirements/mock-agent-slow-duration.md) -- [Native Code Review](requirements/native-code-review.md) -- [No Silent Model Fallback](requirements/no-silent-model-fallback.md), including - profile-selector warning placement and executor-authoritative task warnings. -- [Copy agent configuration to isolated executors](requirements/portable-agent-configuration.md) -- [Disable an Agent Profile](requirements/profile-disable.md) -- [Agent Profile Recent Use](requirements/profile-recent-use.md) -- [Duplicate an Agent Profile](requirements/profile-duplicate.md) -- [Agent Roles — Security, QA, and DevOps](requirements/roles.md) -- [Managed npm runtime recovery](requirements/managed-npm-runtime-recovery.md) -- [Managed Agent Runtime Versions and Updates](requirements/runtime-updates.md) -- [MCP Bridge Reliability](requirements/mcp-bridge-reliability.md) -- [MCP Protocol Compatibility](requirements/mcp-protocol-compatibility.md) -- [MCP tool discovery guidance](requirements/mcp-tool-discovery-guidance.md) -- [Simplify the agent settings profile layout](requirements/settings-profile-layout.md) -- [Spawn Session Effective Agent Profile](requirements/spawn-session-effective-profile.md) -- [Subagent context persistence](requirements/subagent-context-persistence.md) -- [Profile-backed Utility Agents](requirements/utility-agent-profiles.md) -- [Plan injection budget](requirements/plan-injection-budget-01.md) - -### System design - -- [Agent Resume and Runtime Recovery](system-design/agent-resume-runtime-recovery.md) -- [Session recovery failures](system-design/session-recovery-failures.md) -- [Google Antigravity ACP Agent](system-design/antigravity-acp-agent.md) -- [Injected Skill Naming](system-design/injected-skill-naming.md) -- [Injected Skill Naming Migration](system-design/injected-skill-naming-migration.md) -- [Dynamic Agent Routing System Design Part 1](system-design/dynamic-agent-routing-01.md) -- [Dynamic Agent Routing System Design Part 2](system-design/dynamic-agent-routing-02.md) -- [Agent Profile Recent Use](system-design/profile-recent-use.md) -- [No Silent Model Fallback System Design Part 1](system-design/no-silent-model-fallback-01.md) -- [No Silent Model Fallback System Design Part 2](system-design/no-silent-model-fallback-02.md) -- [Managed Agent Runtime Versions and Updates System Design Part 1](system-design/runtime-updates-01.md) -- [Managed Agent Runtime Versions and Updates System Design Part 2](system-design/runtime-updates-02.md) -- [Managed Runtime Default Activation](system-design/runtime-default-activation.md) -- [Managed npm runtime recovery](system-design/managed-npm-runtime-recovery.md) -- [MCP Bridge Reliability](system-design/mcp-bridge-reliability.md) -- [Agent MCP Timeout Budgets](system-design/mcp-timeout-budgets.md) -- [MCP Protocol Compatibility](system-design/mcp-protocol-compatibility.md) -- [MCP tool discovery guidance](system-design/mcp-tool-discovery-guidance.md) -- [Subagent context persistence System Design Part 1](system-design/subagent-context-persistence-01.md) -- [Subagent context persistence System Design Part 2](system-design/subagent-context-persistence-02.md) -- [Subagent context persistence System Design Part 3](system-design/subagent-context-persistence-03.md) -- [Subagent context persistence System Design Part 4](system-design/subagent-context-persistence-04.md) -- [Subagent context persistence System Design Part 5](system-design/subagent-context-persistence-05.md) -- [Subagent context persistence System Design Part 6](system-design/subagent-context-persistence-06.md) -- [Subagent context persistence System Design Part 7](system-design/subagent-context-persistence-07.md) -- [Subagent context persistence System Design Part 8](system-design/subagent-context-persistence-08.md) -- [Profile-backed Utility Agents](system-design/utility-agent-profiles.md) -- [Plan injection budget System Design Part 1](system-design/plan-injection-budget-01.md) -- [Plan injection budget System Design Part 2](system-design/plan-injection-budget-02.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find current sources. ## Related systems - [Settings parity](../platform/requirements/agent-settings-parity.md): owns the shared discovery and interface contract. Agents retain profile data ownership. - - [Tasks](../tasks/README.md): consumes agent profiles for task execution. - [Office](../office/README.md): consumes agent identities for autonomous work. - [Platform](../platform/README.md): owns shared process and runtime services. diff --git a/docs/specs/auth/README.md b/docs/specs/auth/README.md index 7f95d69235..406f069f7b 100644 --- a/docs/specs/auth/README.md +++ b/docs/specs/auth/README.md @@ -27,32 +27,10 @@ for user and service requests. [integration system](../integrations/README.md). - Agent permission policy belongs to the [agent system](../agents/README.md). -## Specification map - -### Requirements - - - -- [Opt-in Authentication & Multi-User Segregation](requirements/auth.md) -- [Org Roles and Scopes](requirements/roles-and-scopes.md) -- [Isolate Kandev cookies between instances on one host](requirements/fix-multi-instance-cookie-isolation.md) -- [Public Share Links (v0)](requirements/public-share-links.md) -- [Repair secure-context browser fallbacks](requirements/secure-context-browser-fallbacks.md) -- [Self-Actions Guard in System Users](requirements/self-actions-guard.md) -- [Session IP Refresh](requirements/session-ip-refresh.md) -- [Trusted Proxies for X-Forwarded-For](requirements/trusted-proxies.md) - -### System design - - - -- [Isolate Kandev cookies between instances on one host](system-design/fix-multi-instance-cookie-isolation.md) -- [Public Share Links (v0)](system-design/public-share-links.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to find them. ## Related systems diff --git a/docs/specs/canvases/README.md b/docs/specs/canvases/README.md index 27edb3e52e..34c73a1463 100644 --- a/docs/specs/canvases/README.md +++ b/docs/specs/canvases/README.md @@ -17,22 +17,9 @@ The Plugins system owns the isolated web-application runtime, permissions, Kandev data access, state, events, and package validation. The task system remains authoritative for task data and permissions. -## Requirements - -- [Agent-authored web-app canvases](requirements/agent-authored-web-apps.md) -- [Owner-authorized creation](requirements/local-creation-authority.md) -- [Deprecated collaborative canvases](requirements/collaborative-canvases.md) - -## System design - -- [Agent-authored web-app canvases](system-design/agent-authored-web-apps.md) -- [Owner-authorized creation](system-design/local-creation-authority.md) -- [Superseded collaborative canvases](system-design/collaborative-canvases.md) - ## Related context - [Runtime and permission fix plan](../../plans/canvas-runtime-permission-fixes/plan.md) - - [Agent MCP discovery guidance](../agents/system-design/mcp-tool-discovery-guidance.md) - [MCP discovery and canvas prompt plan](../../plans/mcp-discovery-canvas-prompts/plan.md) - [GitHub Copilot App Canvas reference](../../copilot-canvas-reference.md) diff --git a/docs/specs/ci/README.md b/docs/specs/ci/README.md index c58a163283..5134738b11 100644 --- a/docs/specs/ci/README.md +++ b/docs/specs/ci/README.md @@ -31,20 +31,6 @@ deployment, and pull request walkthrough generation. - The walkthrough skill, renderer, and artifact format. - Kandev application state or user-interface behavior. -## Specification map - -### Requirements - -- [Unified contributor PR automation](requirements/unified-contributor-pr-automation.md) -- [Contributor merge approval revocation](requirements/contributor-merge-approval-revocation.md) -- [Pull request size labels](requirements/pull-request-size-labels.md) - -### System design - -- [Unified contributor PR automation](system-design/unified-contributor-pr-automation.md) -- [Contributor merge approval revocation](system-design/contributor-merge-approval-revocation.md) -- [Pull request size labels](system-design/pull-request-size-labels.md) - ## Migration The new shared trust contract replaces the label portions of the diff --git a/docs/specs/cli/README.md b/docs/specs/cli/README.md index 7ac8ed5787..6e1c58caf0 100644 --- a/docs/specs/cli/README.md +++ b/docs/specs/cli/README.md @@ -24,24 +24,10 @@ and CLI-specific compatibility behavior. - Shared launcher behavior belongs to the [platform system](../platform/README.md). - Desktop shell behavior belongs to the [desktop system](../desktop/README.md). -## Specification map - -### Requirements - -- [CLI-Mode Task Parity (Kanban)](requirements/cli-mode-parity.md) -- [Mobile Passthrough Composer](requirements/mobile-passthrough-composer.md) -- [Native Kandev CLI](requirements/native-kandev-cli.md) -- [Passthrough Launch Defaults](requirements/passthrough-launch-defaults.md) - -### System design - -- [Mobile Passthrough Composer](system-design/mobile-passthrough-composer.md) -- [Passthrough Launch Defaults](system-design/passthrough-launch-defaults.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to find them. ## Related systems diff --git a/docs/specs/costs/README.md b/docs/specs/costs/README.md index 274d48f6fb..1d08669a23 100644 --- a/docs/specs/costs/README.md +++ b/docs/specs/costs/README.md @@ -24,25 +24,11 @@ and cheap-model profiles used by task and Office execution. - Agent profile identity belongs to the [agent system](../agents/README.md). - Office-specific routing policy belongs to the [Office system](../office/README.md). -## Specification map - -### Requirements - - - -- [Cheap Model Profiles](requirements/cheap-model-profiles.md) -- [Subscription Usage Tracking](requirements/subscription-usage.md) - -### System design - - - -- None. - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find them. ## Related systems diff --git a/docs/specs/desktop/README.md b/docs/specs/desktop/README.md index 12fd9f293a..57704efb4d 100644 --- a/docs/specs/desktop/README.md +++ b/docs/specs/desktop/README.md @@ -26,23 +26,11 @@ desktop-specific behavior that is not part of the web UI contract. - Responsive web behavior belongs to the [UI system](../ui/README.md). - Release publication belongs to the [release system](../release/README.md). -## Specification map - -### Requirements - - - -- [Tauri Desktop App](requirements/desktop-tauri-app.md) - -### System design - - - -- [Tauri Desktop App](system-design/desktop-tauri-app.md) - ## Migration record -All legacy sources assigned to this system are now represented by the canonical requirement and system-design documents above. Source detail is retained in those documents or in their linked design parts. +All legacy sources assigned to this system are now represented by the canonical +requirement and system-design documents. Source detail is retained in those +documents or in their linked design parts. ## Related systems diff --git a/docs/specs/disambiguate-waiting/spec.md b/docs/specs/disambiguate-waiting/spec.md index 80aa3460af..b9d29f1620 100644 --- a/docs/specs/disambiguate-waiting/spec.md +++ b/docs/specs/disambiguate-waiting/spec.md @@ -1506,5 +1506,4 @@ Two questions earlier revisions carried are now closed by evidence rather than a - No new i18n surface: the affordance reuses `task-state-background-running` and `task:backgroundWorkIsRunning`, both of which already ship (AC-82). Moving `BackgroundWorkTaskIcon` between files does not change either. -- `docs/specs/INDEX.md` carries a row for this spec, one for the elicitation spec, and one for the - deferral spec. +- The catalog command discovers these specs from their paths and frontmatter. diff --git a/docs/specs/executors/README.md b/docs/specs/executors/README.md index 027a5c60d0..93f1631f27 100644 --- a/docs/specs/executors/README.md +++ b/docs/specs/executors/README.md @@ -27,48 +27,16 @@ failure and recovery contracts. - Task ownership of worktrees belongs to the [task system](../tasks/README.md). - Desktop process supervision belongs to the [desktop system](../desktop/README.md). -## Specification map - -### Requirements - -- [Repository branch resolution](requirements/repository-branch-resolution.md) - - - -- [Executor-Profile Environment Precedence](requirements/executor-profile-env-precedence.md) -- [Port collision and backend ownership safety](requirements/port-collision-safety.md) -- [SSH Executor](requirements/ssh-executor.md) -- [Remote SSH task-directory reclamation](requirements/remote-task-directory-reclamation.md) -- [Kubernetes worker presets](requirements/kubernetes-worker-presets.md) -- [Kubernetes startup timing](requirements/kubernetes-startup-timing.md) -- [Kubernetes retained compute visibility](requirements/kubernetes-retained-compute.md) - -### System design - -- [Repository branch resolution](system-design/repository-branch-resolution.md) - - - -- [Executor-Profile Environment Precedence System Design Part 1](system-design/executor-profile-env-precedence-01.md) -- [Executor-Profile Environment Precedence System Design Part 2](system-design/executor-profile-env-precedence-02.md) -- [Executor-Profile Environment Precedence System Design Part 3](system-design/executor-profile-env-precedence-03.md) -- [Executor-Profile Environment Precedence System Design Part 4](system-design/executor-profile-env-precedence-04.md) -- [Executor-Profile Environment Precedence System Design Part 5](system-design/executor-profile-env-precedence-05.md) -- [SSH Executor](system-design/ssh-executor.md) -- [Remote SSH task-directory reclamation](system-design/remote-task-directory-reclamation.md) -- [Kubernetes worker presets](system-design/kubernetes-worker-presets.md) -- [Kubernetes startup timing](system-design/kubernetes-startup-timing.md) -- [Kubernetes retained compute visibility](system-design/kubernetes-retained-compute.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find current sources. The [Kubernetes executor foundation](../kubernetes-executor/spec.md) remains the current lifecycle contract. The three Kubernetes pairs own additive -presets, launch diagnostics, and retained-compute visibility. They do not replace -the foundation's resource ownership, recovery, or cleanup rules. +presets, launch diagnostics, and retained-compute visibility. They do not +replace the foundation's resource ownership, recovery, or cleanup rules. ## Related systems diff --git a/docs/specs/guide/requirements.md b/docs/specs/guide/requirements.md index e88b4ef6b6..2ea0045646 100644 --- a/docs/specs/guide/requirements.md +++ b/docs/specs/guide/requirements.md @@ -100,10 +100,15 @@ capability through the web application. Create a UI requirement when the UI owns an independent presentation or interaction contract that several features can use without copying feature state. -Before you add a requirement, search all system indexes, requirement files, and -system-design files for the capability and its main nouns. Update the current -owner when the new behavior extends the same outcome. Create another -requirement only when the actor, lifecycle, or contract is independent. +Before you add a requirement, search the catalog and the owning system +documents for the capability and its main nouns: + + python3 scripts/list-docs.py specs --text --format paths + +Update the current owner when the new behavior extends the same outcome. +Create another requirement only when the actor, lifecycle, or contract is +independent. Keep the system README focused on its boundary instead of adding a +requirement list. ## Migration quality diff --git a/docs/specs/guide/structure-and-ownership.md b/docs/specs/guide/structure-and-ownership.md index 149161674d..06bfeea50f 100644 --- a/docs/specs/guide/structure-and-ownership.md +++ b/docs/specs/guide/structure-and-ownership.md @@ -37,14 +37,24 @@ design in the system that owns the behavior. Each requirement has one owning system. Another system can reference the requirement but must not copy it. -Each system has a `README.md`. This file defines the system boundary and links -to its requirements and system designs. Use `glossary.md` only when the system -has terms that need precise definitions. +Each system has a `README.md`. This file defines the system boundary, migration +record, and related systems. Use `glossary.md` only when the system has terms +that need precise definitions. -The system index sets `migration: in_progress` while legacy files remain. Set -it to `complete` only after the index names the new authoritative documents and -all editable legacy sources become links or archives. The linter enforces the -strict system layout after migration is complete. +Use the catalog command to find the documents that a system owns: + + python3 scripts/list-docs.py specs --system --format markdown + python3 scripts/list-docs.py specs --system --kind requirement --format paths + python3 scripts/list-docs.py specs --system --kind system-design --format paths + +The command derives its results from paths and frontmatter. Do not copy its +results into a system README. + +The system README sets `migration: in_progress` while legacy files remain. Set +it to `complete` only after the new authoritative documents exist and all +editable legacy sources become links or archives. The catalog command discovers +the files, and the linter enforces the strict system layout after migration is +complete. A system does not need both artifact directories. A low-level system can have system designs without product requirements. Do not create empty placeholder @@ -93,8 +103,8 @@ and React components. Do not create a second UI requirement or design for those same controls. Create separate cross-system artifacts only when each system owns an independent -contract with a different lifecycle. Link the contracts in both system indexes. -Do not repeat acceptance criteria or technical sections. +contract with a different lifecycle. Link the contracts in both documents. Do +not repeat acceptance criteria or technical sections. ## File names @@ -114,7 +124,7 @@ capability. The specification linter reads the default limits from `docs/specs/spec-lint.json`. The default limits are: -- System index: 16 KiB. +- System README: 16 KiB. - Product or guide document: 16 KiB. - Requirement document: 20 KiB. - System-design document: 32 KiB. diff --git a/docs/specs/guide/traceability-and-lifecycle.md b/docs/specs/guide/traceability-and-lifecycle.md index d9f0226f07..a83df0fa77 100644 --- a/docs/specs/guide/traceability-and-lifecycle.md +++ b/docs/specs/guide/traceability-and-lifecycle.md @@ -26,8 +26,8 @@ commit. ## Status values -System indexes use `draft`, `active`, or `retired`. Their `migration` field uses -`in_progress` or `complete`. +System README files use `draft`, `active`, or `retired`. Their `migration` field +uses `in_progress` or `complete`. Requirement documents use: @@ -64,10 +64,11 @@ Migrate one system at a time. Use this sequence: 3. Extract observable behavior into requirement documents. 4. Extract technical contracts and design into system-design documents. 5. Add stable IDs and cross-references. -6. Name the new documents as authoritative in the system index. +6. Keep the system boundary and migration record in the system `README.md`. 7. Add a short link to the system `README.md`, or archive the legacy document outside `docs/specs//`. -8. Set `migration: complete` and remove obsolete size exceptions. +8. Run the catalog and specification linters. +9. Set `migration: complete` and remove obsolete size exceptions. Do not keep two editable sources of truth during migration. diff --git a/docs/specs/integrations/README.md b/docs/specs/integrations/README.md index 40934c69ec..2f011c1312 100644 --- a/docs/specs/integrations/README.md +++ b/docs/specs/integrations/README.md @@ -29,81 +29,11 @@ outcomes that expose those contracts. - Reusable presentation contracts without provider state belong to the [UI system](../ui/README.md). -## Specification map - -### Requirements - - - -- [Azure DevOps Integration](requirements/azure-devops-integration.md) -- [Bitbucket Connector Plugin](requirements/bitbucket-plugin.md) -- [Claude Fork Review Allowlist](requirements/claude-fork-review-allowlist.md) -- [Clickable integration cards](requirements/clickable-integration-cards.md) -- [Integration Enable/Disable Toggle & Nav Visibility](requirements/enable-disable-toggle.md) -- [External MCP Endpoint](requirements/external-mcp.md) -- [External Question Answering — authorized, discoverable, idempotent clarification resolution](requirements/external-question-answering.md) -- [Workspace GitHub Authentication](requirements/github-authentication.md) -- [GitHub PR Auto-Fix Conflicts](requirements/github-pr-auto-fix-conflicts.md) -- [GitHub PR Merge Queue](requirements/github-pr-merge-queue.md) -- [GitHub PR Merge Queue Recovery](requirements/github-pr-merge-queue-recovery.md) -- [GitHub task pull request sync coordination](requirements/github-task-pr-sync-coordination.md) -- [GitHub PR discovery health](requirements/github-pr-discovery-health.md) -- [GitHub workflow attention](requirements/github-workflow-attention.md) -- [GitHub dashboard mobile](requirements/github-dashboard-mobile.md) -- [GitLab Integration](requirements/gitlab-integration.md) -- [GitLab MR Status Chip](requirements/gitlab-mr-status-chip.md) -- [GitLab MR Badge on the Sidebar and Tasks-List Rows](requirements/gitlab-mr-task-list-badges.md) -- [GitLab Workflow Sync](requirements/gitlab-workflow-sync.md) -- [Jira Watcher Task Prompts](requirements/jira-watcher-task-prompts.md) -- [Jira Ticket Status Filter](requirements/jira-status-filter.md) -- [Watcher Remote Base Branches](requirements/watcher-remote-base-branches.md) -- [MCP Tool Argument Validation](requirements/mcp-tool-argument-validation.md) -- [Pull request outcome attribution](requirements/pr-outcome-attribution.md) -- [Pull request link copy actions](requirements/pr-link-copy-actions.md) -- [Provider-Aware Review Automation Runtime](requirements/provider-aware-review-automation.md) -- [Slack Integration](requirements/slack.md) - -### System design - - - -- [External MCP Saved Prompt Reads](system-design/external-mcp-shared-prompts.md) -- [Azure DevOps Integration System Design Part 1](system-design/azure-devops-integration-01.md) -- [Azure DevOps Integration System Design Part 2](system-design/azure-devops-integration-02.md) -- [Bitbucket Connector Plugin System Design Part 1](system-design/bitbucket-plugin-01.md) -- [Bitbucket Connector Plugin System Design Part 2](system-design/bitbucket-plugin-02.md) -- [External Question Answering — authorized, discoverable, idempotent clarification resolution System Design Part 1](system-design/external-question-answering-01.md) -- [External Question Answering — authorized, discoverable, idempotent clarification resolution System Design Part 2](system-design/external-question-answering-02.md) -- [External Question Answering — authorized, discoverable, idempotent clarification resolution System Design Part 3](system-design/external-question-answering-03.md) -- [External Question Answering — authorized, discoverable, idempotent clarification resolution System Design Part 4](system-design/external-question-answering-04.md) -- [Workspace GitHub Authentication System Design Part 1](system-design/github-authentication-01.md) -- [Workspace GitHub Authentication System Design Part 2](system-design/github-authentication-02.md) -- [Workspace GitHub Authentication System Design Part 3](system-design/github-authentication-03.md) -- [GitHub PR Auto-Fix Conflicts](system-design/github-pr-auto-fix-conflicts.md) -- [GitHub PR Merge Queue](system-design/github-pr-merge-queue.md) -- [GitHub PR Merge Queue Recovery](system-design/github-pr-merge-queue-recovery.md) -- [GitHub task pull request sync coordination](system-design/github-task-pr-sync-coordination.md) -- [GitHub PR discovery health](system-design/github-pr-discovery-health.md) -- [GitHub workflow attention](system-design/github-workflow-attention.md) -- [GitHub dashboard mobile](system-design/github-dashboard-mobile.md) -- [Pull request link copy actions](system-design/pr-link-copy-actions.md) -- [GitLab Integration System Design Part 1](system-design/gitlab-integration-01.md) -- [GitLab Integration System Design Part 2](system-design/gitlab-integration-02.md) -- [GitLab MR Status Chip System Design Part 1](system-design/gitlab-mr-status-chip-01.md) -- [GitLab MR Status Chip System Design Part 2](system-design/gitlab-mr-status-chip-02.md) -- [GitLab MR Status Chip System Design Part 3](system-design/gitlab-mr-status-chip-03.md) -- [GitLab MR Status Chip System Design Part 4](system-design/gitlab-mr-status-chip-04.md) -- [GitLab MR Status Chip System Design Part 5](system-design/gitlab-mr-status-chip-05.md) -- [GitLab MR Badge on the Sidebar and Tasks-List Rows System Design Part 1](system-design/gitlab-mr-task-list-badges-01.md) -- [GitLab MR Badge on the Sidebar and Tasks-List Rows System Design Part 2](system-design/gitlab-mr-task-list-badges-02.md) -- [GitLab MR Badge on the Sidebar and Tasks-List Rows System Design Part 3](system-design/gitlab-mr-task-list-badges-03.md) -- [Jira Watcher Task Prompts](system-design/jira-watcher-task-prompts.md) -- [Watcher Remote Base Branches](system-design/watcher-remote-base-branches.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find current sources. ## Related systems diff --git a/docs/specs/launcher/README.md b/docs/specs/launcher/README.md index 8279f00632..b88d3408c4 100644 --- a/docs/specs/launcher/README.md +++ b/docs/specs/launcher/README.md @@ -30,16 +30,6 @@ handoffs. request. - Agent runtime launch and ACP probes are not backend startup readiness. -## Specification map - -### Requirements - -- [Startup recovery](requirements/startup-recovery.md) - -### System design - -- [Startup recovery](system-design/startup-recovery.md) - ## Migration status The startup-recovery documents are authoritative for bind-aware readiness and diff --git a/docs/specs/office/README.md b/docs/specs/office/README.md index 80fecc905b..75198c8a01 100644 --- a/docs/specs/office/README.md +++ b/docs/specs/office/README.md @@ -26,107 +26,11 @@ dashboard projections, and Office testing contracts. - Shared agent profiles and permissions belong to the [agent system](../agents/README.md). - External provider connections belong to the [integration system](../integrations/README.md). -## Specification map - -### Requirements - - - -- [Office: Agent Comment Reads](requirements/agent-comment-reads.md) -- [Office Agent Recovery](requirements/agent-recovery.md) -- [Office: Agents](requirements/agents.md) -- [Office: Personal Assistant Agent, Channels & Agent Memory](requirements/assistant.md) -- [Automation runs — status-scoped delete all](requirements/automation-runs-delete-all-by-status.md) -- [Automation Runs](requirements/automation-runs.md) -- [Automations — "Pull request merged" trigger](requirements/automations-pr-merged-trigger.md) -- [Automations in Settings](requirements/automations-settings.md) -- [Automation Continuity](requirements/automation-continuity.md) -- [Automation Target Modes](requirements/automation-target-modes.md) -- [Automations YAML Export](requirements/automations-yaml-export.md) -- [Office: Cost Tracking & Budget Management](requirements/costs.md) -- [Office Config Sync](requirements/config-sync.md) -- [Office Config Sync Fetch](requirements/config-sync-fetch.md) -- [Office Config Sync Reconciliation](requirements/config-sync-reconciliation.md) -- [Office Config Sync Surfaces](requirements/config-sync-surfaces.md) -- [Children-Completed Wake Summaries](requirements/children-completed-wake-summaries.md) -- [Office Dashboard](requirements/dashboard.md) -- [Office: Inbox, Approvals & Activity Log](requirements/inbox.md) -- [Office Live Updates](requirements/live-updates.md) -- [Office per-agent and per-role tier selection](requirements/office-agent-tier-routing.md) -- [Office: Overview](requirements/overview.md) -- [Office Participant Seat Provenance](requirements/participant-seat-provenance.md) -- [Office Provider Routing](requirements/routing.md) -- [Office Review Participant Seats](requirements/review-participant-seats.md) -- [Office Agent Runtime — Error Handling Contract](requirements/runtime.md) -- [Office Scheduler](requirements/scheduler.md) -- [Office Stall Visibility](requirements/stall-visibility.md) -- [Office Session Identity Graduation](requirements/session-identity-graduation.md) -- [Step Entry Sequence Execution](requirements/step-entry-sequence-execution.md) -- [Office Task Session Identity](requirements/task-session-identity.md) -- [Office Tasks](requirements/tasks.md) -- [Office: E2E Mock Harness for Task Sessions and Messages](requirements/testing.md) -- [Office: Slack-Style Unread Divider](requirements/unread-divider.md) - -### System design - - - -- [Office: Agent Comment Reads System Design](system-design/agent-comment-reads-01.md) -- [Office Agent Recovery System Design](system-design/agent-recovery.md) -- [Office: Agents System Design Part 1](system-design/agents-01.md) -- [Office: Agents System Design Part 2](system-design/agents-02.md) -- [Office: Agents System Design Part 3](system-design/agents-03.md) -- [Office: Personal Assistant Agent, Channels & Agent Memory](system-design/assistant.md) -- [Automation Runs](system-design/automation-runs.md) -- [Automation Target Modes](system-design/automation-target-modes.md) -- [Automations — "Pull request merged" trigger System Design Part 1](system-design/automations-pr-merged-trigger-01.md) -- [Automations — "Pull request merged" trigger System Design Part 2](system-design/automations-pr-merged-trigger-02.md) -- [Automations — "Pull request merged" trigger System Design Part 3](system-design/automations-pr-merged-trigger-03.md) -- [Automations — "Pull request merged" trigger System Design Part 4](system-design/automations-pr-merged-trigger-04.md) -- [Automations — "Pull request merged" trigger System Design Part 5](system-design/automations-pr-merged-trigger-05.md) -- [Automations — "Pull request merged" trigger System Design Part 6](system-design/automations-pr-merged-trigger-06.md) -- [Automations — "Pull request merged" trigger System Design Part 7](system-design/automations-pr-merged-trigger-07.md) -- [Automations — "Pull request merged" trigger System Design Part 8](system-design/automations-pr-merged-trigger-08.md) -- [Automations in Settings System Design Part 1](system-design/automations-settings-01.md) -- [Automations in Settings System Design Part 2](system-design/automations-settings-02.md) -- [Automations YAML Export System Design Part 1](system-design/automations-yaml-export-01.md) -- [Automations YAML Export System Design Part 2](system-design/automations-yaml-export-02.md) -- [Automations YAML Export System Design Part 3](system-design/automations-yaml-export-03.md) -- [Automations YAML Export System Design Part 4](system-design/automations-yaml-export-04.md) -- [Automations YAML Export System Design Part 5](system-design/automations-yaml-export-05.md) -- [Automations YAML Export System Design Part 6](system-design/automations-yaml-export-06.md) -- [Children-Completed Wake Summaries System Design](system-design/children-completed-wake-summaries.md) -- [Office Config Sync System Design](system-design/config-sync.md) -- [Office Config Sync Reconciliation System Design](system-design/config-sync-reconciliation.md) -- [Office: Cost Tracking & Budget Management System Design Part 1](system-design/costs-01.md) -- [Office: Cost Tracking & Budget Management System Design Part 2](system-design/costs-02.md) -- [Office: Budget Notification Idempotency System Design (Part 3)](system-design/costs-03.md) -- [Office: Budget Notification Idempotency System Design (Part 4)](system-design/costs-04.md) -- [Office Live Updates System Design Part 1](system-design/live-updates-01.md) -- [Office Live Updates System Design Part 2](system-design/live-updates-02.md) -- [Office per-agent and per-role tier selection System Design Part 1](system-design/office-agent-tier-routing-01.md) -- [Office per-agent and per-role tier selection System Design Part 2](system-design/office-agent-tier-routing-02.md) -- [Office per-agent and per-role tier selection System Design Part 3](system-design/office-agent-tier-routing-03.md) -- [Office: Overview System Design Part 1](system-design/overview-01.md) -- [Office: Overview System Design Part 2](system-design/overview-02.md) -- [Office Participant Seat Provenance System Design Part 1](system-design/participant-seat-provenance-01.md) -- [Office Review Participant Seats System Design Part 1](system-design/review-participant-seats-01.md) -- [Office Provider Routing System Design Part 1](system-design/routing-01.md) -- [Office Provider Routing System Design Part 2](system-design/routing-02.md) -- [Office Agent Runtime — Error Handling Contract System Design Part 1](system-design/runtime-01.md) -- [Office Agent Runtime — Error Handling Contract System Design Part 2](system-design/runtime-02.md) -- [Office Scheduler System Design Part 1](system-design/scheduler-01.md) -- [Office Stall Visibility System Design](system-design/stall-visibility.md) -- [Step Entry Sequence Execution System Design](system-design/step-entry-sequence-execution.md) -- [Office Scheduler System Design Part 2](system-design/scheduler-02.md) -- [Office Tasks System Design Part 1](system-design/tasks-01.md) -- [Office Tasks System Design Part 2](system-design/tasks-02.md) -- [Office: Slack-Style Unread Divider System Design](system-design/unread-divider.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find current sources. ## Related systems diff --git a/docs/specs/platform/README.md b/docs/specs/platform/README.md index 810da61692..7f56c5f579 100644 --- a/docs/specs/platform/README.md +++ b/docs/specs/platform/README.md @@ -31,92 +31,11 @@ retains ownership of its values, validation, authority, and persistence. - Agent identity belongs to the [agent system](../agents/README.md). - Desktop shell behavior belongs to the [desktop system](../desktop/README.md). -## Specification map - -### Requirements - -- [Startup lifecycle](requirements/startup-lifecycle.md) - -- [Agent-accessible Kandev settings](requirements/agent-settings-parity.md) - - - -- [Agent process exit and stderr drain](requirements/agent-process-exit-drain.md) -- [Agentctl instance stop idempotency](requirements/agentctl-instance-stop.md) -- [Agent Runtime Availability](requirements/agent-runtime-availability.md) -- [Background Work Liveness](requirements/background-work-liveness.md) -- [Backend restart page recovery](requirements/backend-restart-page-recovery.md) -- [Bounded Task Status Delivery](requirements/bounded-task-status-delivery.md) -- [Viewport-bounded Session Delivery](requirements/viewport-bounded-session-delivery.md) -- [Shared Cron Loop Safety When Office Is Disabled](requirements/cron-office-disabled-safety.md) -- [Environment-specific browser tab title prefixes](requirements/dev-preview-title-prefixes.md) -- [Browser console retention](requirements/browser-console-retention.md) -- [Diagnostic logging](requirements/diagnostic-logging.md) -- [Duration-aware E2E sharding and CI reliability](requirements/e2e-duration-aware-sharding.md) -- [External CI runner capacity](requirements/external-e2e-runner-capacity.md) -- [Expected runtime log severity](requirements/expected-runtime-log-severity.md) -- [Feature Toggles](requirements/feature-toggles.md) -- [Git Credential Lease Reissue](requirements/git-credential-lease-reissue.md) -- [Git Subprocess Admission](requirements/git-subprocess-admission.md) -- [Go dev launcher and minimal Node surface](requirements/go-dev-launcher.md) -- [Health Endpoint — Surface the Running Version](requirements/health-endpoint-version.md) -- [Watcher And Task Fallback Localization](requirements/i18n-audit-watcher-copy.md) -- [Additional I18n Audit Gaps](requirements/i18n-second-audit-gaps.md) -- [Internationalization (i18n)](requirements/i18n.md) -- [LSP File Intelligence](requirements/lsp-file-intelligence.md) -- [Session MCP Attachment Observability](requirements/mcp-session-observability.md) -- [Mid-Turn Steering](requirements/mid-turn-steering.md) -- [Semantic Notifications](requirements/notifications.md) -- [Apprise rescan](requirements/apprise-rescan.md) -- [Required Persisted Store Parity](requirements/postgres-domain-store-parity.md) -- [Provider Error Recovery](requirements/provider-error-recovery.md) -- [Session Config Reconciliation Across Agent Types](requirements/session-config-cross-agent-reconcile.md) -- [Session subscription recovery](requirements/session-subscription-recovery.md) -- [Setup and Launch Timeout](requirements/setup-launch-timeout.md) -- [Quiet benign teardown log noise on shutdown](requirements/shutdown-log-noise.md) -- [Do not surface backend-shutdown turn aborts as agent failures](requirements/shutdown-turn-failure-suppression.md) -- [Startup Configuration Parity](requirements/startup-configuration-parity.md) -- [Prevent Host Sleep During Active Tasks](requirements/task-sleep-inhibition.md) -- [Traditional Chinese locales (Taiwan and Hong Kong)](requirements/traditional-chinese-locales.md) -- [Workspace Git Status](requirements/workspace-git-status.md) - -### System design - -- [Startup lifecycle](system-design/startup-lifecycle.md) - -- [Agent-accessible Kandev settings](system-design/agent-settings-parity.md) -- [Core settings domain adoption](system-design/agent-settings-domains.md) - - - -- [Agent process exit and stderr drain](system-design/agent-process-exit-drain.md) -- [Agentctl instance stop idempotency](system-design/agentctl-instance-stop.md) -- [Apprise rescan](system-design/apprise-rescan.md) -- [Background Work Liveness](system-design/background-work-liveness.md) -- [Backend restart page recovery](system-design/backend-restart-page-recovery.md) -- [Browser console retention](system-design/browser-console-retention.md) -- [Bounded Task Status Delivery](system-design/bounded-task-status-delivery.md) -- [Viewport-bounded Session Delivery](system-design/viewport-bounded-session-delivery.md) -- [Diagnostic logging System Design Part 1](system-design/diagnostic-logging-01.md) -- [Diagnostic logging System Design Part 2](system-design/diagnostic-logging-02.md) -- [Expected runtime log severity](system-design/expected-runtime-log-severity.md) -- [Duration-aware E2E sharding and CI reliability](system-design/e2e-duration-aware-sharding.md) -- [External CI runner capacity](system-design/external-e2e-runner-capacity.md) -- [Health Endpoint — Surface the Running Version](system-design/health-endpoint-version.md) -- [Internationalization (i18n)](system-design/i18n.md) -- [LSP File Intelligence System Design Part 1](system-design/lsp-file-intelligence-01.md) -- [LSP File Intelligence System Design Part 2](system-design/lsp-file-intelligence-02.md) -- [Session MCP Attachment Observability](system-design/mcp-session-observability.md) -- [Required Persisted Store Parity](system-design/postgres-domain-store-parity.md) -- [Provider Error Recovery](system-design/provider-error-recovery.md) -- [Workspace Git Status](system-design/workspace-git-status.md) -- [Go dev launcher and startup version](system-design/go-dev-launcher.md) -- [Startup database selection continuity](system-design/startup-database-selection-continuity.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find current sources. ## Related systems diff --git a/docs/specs/plugins/README.md b/docs/specs/plugins/README.md index d15e2ee8fe..775781f6e1 100644 --- a/docs/specs/plugins/README.md +++ b/docs/specs/plugins/README.md @@ -26,42 +26,10 @@ plugin security boundaries. - External service credentials belong to the [integration system](../integrations/README.md). - Desktop packaging belongs to the [desktop system](../desktop/README.md). -## Specification map - -### Requirements - -- [Plugin-Contributed Agent Tools](requirements/agent-tools.md) -- [Isolated plugin web-application contributions](requirements/isolated-web-app-contributions.md) -- [Plugin-Initiated Workflow Step Transitions](requirements/plugin-initiated-step-transitions.md) -- [Plugin Authoring Experience](requirements/authoring-experience.md) -- [Plugin Marketplace](requirements/marketplace.md) -- [Plugin nav items in the sidebar footer icon row](requirements/plugin-nav-sidebar-footer.md) -- [Plugin Shortcut Settings](requirements/plugin-shortcut-settings.md) -- [Plugin System](requirements/plugins.md) -- [Plugin Repository Task Creation](requirements/repository-provider-task-creation.md) -- [Voice Plugin Host Prerequisites](requirements/voice-extraction-host.md) -- [Voice Mode Leaves Core](requirements/voice-extraction.md) - -### System design - -- [Plugin-Initiated Workflow Step Transitions](system-design/plugin-initiated-step-transitions.md) -- [Plugin Marketplace](system-design/marketplace.md) -- [Isolated plugin web-application contributions](system-design/isolated-web-app-contributions.md) -- [Plugin nav items in the sidebar footer icon row System Design Part 1](system-design/plugin-nav-sidebar-footer-01.md) -- [Plugin nav items in the sidebar footer icon row System Design Part 2](system-design/plugin-nav-sidebar-footer-02.md) -- [Plugin nav items in the sidebar footer icon row System Design Part 3](system-design/plugin-nav-sidebar-footer-03.md) -- [Plugin nav items in the sidebar footer icon row System Design Part 4](system-design/plugin-nav-sidebar-footer-04.md) -- [Plugin Shortcut Settings](system-design/plugin-shortcut-settings.md) -- [Plugin System System Design Part 1](system-design/plugins-01.md) -- [Plugin System System Design Part 2](system-design/plugins-02.md) -- [Plugin System System Design Part 3](system-design/plugins-03.md) -- [Plugin System System Design Part 4](system-design/plugins-04.md) -- [Plugin Repository Task Creation](system-design/repository-provider-task-creation.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to find them. ## Related systems diff --git a/docs/specs/plugins/system-design/plugin-nav-sidebar-footer-01.md b/docs/specs/plugins/system-design/plugin-nav-sidebar-footer-01.md index 44a5a89f7f..d198c6036f 100644 --- a/docs/specs/plugins/system-design/plugin-nav-sidebar-footer-01.md +++ b/docs/specs/plugins/system-design/plugin-nav-sidebar-footer-01.md @@ -33,8 +33,8 @@ that replaces the original. Status returns to `draft` because the amended contract is not implemented. The already-merged-into-the-branch first version is implemented; the amendment is not. The -status returns to `shipped` when PR #2562 merges carrying this contract, and -`docs/specs/INDEX.md` tracks the same value. +status returns to `shipped` when PR #2562 merges carrying this contract. The catalog +command reads the current status from this document's frontmatter. **Amendment 1, spec-review round 1 corrections (2026-08-12).** The amended contract went through an adversarial spec review (cross-vendor and cross-model legs) and came back @@ -109,9 +109,10 @@ feature were specific to one (private, unreleased) Insights plugin rather than a any plugin can request. The new slug matches the plugin-facing value `"sidebar-footer"` exactly, so the spec slug, the public token and the authoring docs all use one word. Moved with it: `docs/plans/plugin-nav-insights-section/` → `docs/plans/plugin-nav-sidebar-footer/` -(plan plus three task files) and the `docs/specs/INDEX.md` row. The internal section is -still named `insights` in `apps/web/lib/navigation/types.ts` and this document still calls -it that; only the plugin-facing and document-facing names changed. +(plan plus three task files). The catalog command discovers this document from its path +and frontmatter. The internal section is still named `insights` in +`apps/web/lib/navigation/types.ts` and this document still calls it that; only the +plugin-facing and document-facing names changed. ## Why diff --git a/docs/specs/product/README.md b/docs/specs/product/README.md index 0a9bca996e..859ba5c577 100644 --- a/docs/specs/product/README.md +++ b/docs/specs/product/README.md @@ -18,15 +18,12 @@ The expected subjects are: System-specific behavior belongs in the owning system under `requirements/`. Technical implementation belongs in `system-design/`. -## Product document index +## Find product documents + +Run the catalog command to find the current product documents: + + python3 scripts/list-docs.py specs --kind product --format markdown These documents form the current proposed product baseline. They synthesize the existing system specifications, ADRs, and public documentation. Statements marked as open questions still need explicit product confirmation. - -- [Product overview](overview.md): purpose, boundary, and the supported product loop. -- [Actors](actors.md): people, agents, services, and extensions that interact with Kandev. -- [Product map](product-map.md): product surfaces, system relationships, and authority boundaries. -- [Principles](principles.md): durable product principles inferred from current decisions. -- [Success measures](success-measures.md): proposed measures and the targets that remain to be set. -- [Product constraints](product-constraints.md): cross-system safety, support, and compatibility constraints. diff --git a/docs/specs/release/README.md b/docs/specs/release/README.md index 1b88a756a2..3f4f412eaf 100644 --- a/docs/specs/release/README.md +++ b/docs/specs/release/README.md @@ -24,28 +24,10 @@ container, and desktop release publication contracts. - Desktop runtime lifecycle belongs to the [desktop system](../desktop/README.md). - Agent runtime update behavior belongs to the [agent system](../agents/README.md). -## Specification map - -### Requirements - - - -- [Homebrew Core Submission](requirements/homebrew-core.md) -- [npm nightly channel](requirements/npm-nightly-channel.md) -- [Resilient GHCR release publishing](requirements/release-ghcr-secondary-limit.md) -- [Stable release PR queue bypass](requirements/release-pr-queue-bypass.md) -- [Scoop Stable Release Automation](requirements/scoop-release-automation.md) - -### System design - - - -- None. - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to find them. ## Related systems diff --git a/docs/specs/spec-lint-exceptions.tsv b/docs/specs/spec-lint-exceptions.tsv index 90bbbd48b4..f6f6d9670e 100644 --- a/docs/specs/spec-lint-exceptions.tsv +++ b/docs/specs/spec-lint-exceptions.tsv @@ -1,5 +1,5 @@ docs/specs/acp-elicitation/spec.md 68010 -docs/specs/disambiguate-waiting/spec.md 101594 +docs/specs/disambiguate-waiting/spec.md 101556 docs/specs/gitlab-issue-milestone-filter/spec.md 80514 docs/specs/office-task-content-editing/spec.md 84103 docs/specs/parked-notification-deferral/spec.md 33612 diff --git a/docs/specs/system-page/README.md b/docs/specs/system-page/README.md index 9a9528cbc9..258d9f6ded 100644 --- a/docs/specs/system-page/README.md +++ b/docs/specs/system-page/README.md @@ -25,37 +25,11 @@ feedback. - Backend diagnostic events belong to the [platform system](../platform/README.md). - General settings presentation belongs to the [UI system](../ui/README.md). -## Specification map - -### Requirements - - - -- [Backup location and action guidance](requirements/backup-location-actions.md) -- [System Data and Storage Pages](requirements/system-data-storage-pages.md) -- [Storage Maintenance](requirements/storage-maintenance.md) -- [Storage maintenance scan, capacity, and dependency cleanup](requirements/storage-overview-parallel-scan.md) -- [System pages](requirements/system-page.md) - -### System design - -- [Database Storage Analysis System Design](system-design/storage-database-footprint.md) - - - -- [Backup location and action guidance](system-design/backup-location-actions.md) -- [System Data and Storage Pages](system-design/system-data-storage-pages.md) -- [Storage Maintenance System Design Part 1](system-design/storage-maintenance-01.md) -- [Storage Maintenance System Design Part 2](system-design/storage-maintenance-02.md) -- [Storage Maintenance System Design Part 3](system-design/storage-maintenance-03.md) -- [Progressive storage analysis](system-design/storage-analysis-progress.md) -- [System pages System Design Part 1](system-design/system-page-01.md) -- [System pages System Design Part 2](system-design/system-page-02.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find current sources. ## Related systems diff --git a/docs/specs/tasks/README.md b/docs/specs/tasks/README.md index e8ba60318c..94f6feca72 100644 --- a/docs/specs/tasks/README.md +++ b/docs/specs/tasks/README.md @@ -32,175 +32,12 @@ signals, and task-scoped scheduling contracts. [Office system](../office). - Presentation-only behavior belongs to the [UI specifications](../ui). -## Specification map - -### Requirements - -- [Task completion, conversation follow-ups, and workspace access](requirements/task-completion.md) - -- [Agent-Generated Task Titles](requirements/agent-generated-titles.md) -- [Additional Session Workspace Reuse](requirements/additional-session-workspace-reuse.md) -- [Task Archive Confirmation](requirements/archive-confirmation.md) -- [Task removal navigation](requirements/removal-navigation.md) -- [Attach Workspace Sources](requirements/attach-workspace-sources.md) -- [Task Autopilot Mode](requirements/autopilot-mode.md) -- [Blocked Task Escalation](requirements/blocked-task-escalation.md) -- [Command-panel archived task results](requirements/command-panel-archived-task-results.md) -- [Active clarification lifecycle scenarios](requirements/clarification-active-lifecycle-scenarios.md) -- [Active clarification lifecycle](requirements/clarification-active-lifecycle.md) -- [Clarification response reliability](requirements/clarification-response-reliability.md) -- [Task Documents](requirements/documents.md) -- [Detached Workspace Continuity](requirements/detached-workspace-continuity.md) -- [Task plan append-mode write](requirements/plan-write-append-mode.md) -- [Task Execution Stages](requirements/execution-stages.md) -- [External task ID idempotency boundaries](requirements/external-id-idempotency-boundaries.md) -- [External task ID idempotency scenarios](requirements/external-id-idempotency-scenarios.md) -- [External task ID idempotency](requirements/external-id-idempotency.md) -- [Interrupted Task Indicator](requirements/interrupted-task-indicator.md) -- [Kanban task cache preserves executor fields across merges](requirements/kanban-task-executor-cache-staleness.md) -- [Task Labels](requirements/labels.md) -- [Link Existing Task to External References](requirements/link-existing-task-github-issue.md) -- [MCP-Created Task Agent Profile Default](requirements/mcp-task-agent-profile-default.md) -- [MCP Tool Name Stability](requirements/mcp-tool-name-stability.md) -- [MCP workspace modes](requirements/mcp-workspace-mode.md) -- [Missing task route recovery](requirements/missing-task-route-recovery.md) -- [Task model unification](requirements/model-unification.md) -- [Multi-branch tasks](requirements/multi-branch.md) -- [Parent-Child Message Interrupt](requirements/parent-child-message-interrupt.md) -- [Parent-Child Task Stop](requirements/parent-child-task-stop.md) -- [Passthrough Queued Prompt Dispatch](requirements/passthrough-queued-prompt-dispatch.md) -- [Task plan content size limit](requirements/plan-content-size-limit.md) -- [Task Plan Comments](requirements/plan-comments.md) -- [Task plan write consistency](requirements/plan-write-consistency.md) -- [Passthrough Initial Prompt Turn Boundary](requirements/passthrough-initial-prompt-turn-boundary.md) -- [Prevent Agent Auto-Start On Open](requirements/prevent-agent-autostart-on-open.md) -- [Prompt attachments](requirements/prompt-attachments.md) -- [Saved Prompt Delivery](requirements/saved-prompt-delivery.md) -- [Quick Chat Sessions, Persistence, and Expiration](requirements/quick-chat-expiration.md) -- [Quick Chat Agent Titles](requirements/quick-chat-agent-titles.md) -- [Quick Chat Repository Context](requirements/quick-chat-repository-context.md) -- [Remote Contribution Tasks](requirements/remote-contribution-tasks.md) -- [Rich task title previews](requirements/rich-task-title-previews.md) -- [Queued run scheduling](requirements/run-scheduling.md) -- [Resume prompt queue](requirements/resume-prompt-queue.md) -- [Task Runtime Cleanup](requirements/runtime-cleanup.md) -- [Task Terminal Persistence](requirements/task-terminal-persistence.md) -- [Runtime Task-State Publication Order](requirements/runtime-state-publication-order.md) -- [Session Delete Preserves Task Workspaces](requirements/session-delete-resource-cleanup.md) -- [Sidebar Task Editing](requirements/sidebar-task-edit.md) -- [Task Actions Menu on Preview and Detail Surfaces](requirements/task-actions-menu.md) -- [Task menu grouping](requirements/task-menu-grouping.md) -- [Task Actions Menu In-Flight and Concurrency](requirements/task-actions-menu-concurrency.md) -- [Task Actions Menu Action Outcomes](requirements/task-actions-menu-outcomes.md) -- [Subtasks as Workflow Checklist](requirements/subtask-checklist.md) -- [Subtask Completion Trigger](requirements/subtask-completion-trigger.md) -- [Subtask detachment](requirements/subtask-detachment.md) -- [Subtask re-parenting by drag and drop](requirements/subtask-reparenting-drag-drop.md) -- [Task Subtree Controls](requirements/subtree-controls.md) -- [Create Task Escape Dismissal](requirements/task-create-escape-dismissal.md) -- [Task Create Agent Compatibility Recovery](requirements/task-create-agent-executor-compatibility.md) -- [Task Create Executor Default](requirements/task-create-executor-default.md) -- [Task Create Launch Preview](requirements/task-create-launch-preview.md) -- [Task Create Workflow Memory](requirements/task-create-workflow-memory.md) -- [Task-create advanced settings disclosure](requirements/task-dependencies-create-dialog-advanced-settings.md) -- [Task-create dependency selector refinement](requirements/task-dependencies-create-dialog-dependency-selector.md) -- [Edit task dependencies](requirements/task-dependency-detail-editing.md) -- [Task Dependencies and Auto-Start Chains](requirements/task-dependencies.md) -- [Session Launch Repository Resolution](requirements/launch-repository-resolution.md) -- [Task Launch Failure Recovery](requirements/task-launch-failure-recovery.md) -- [Worktree metadata recovery](requirements/worktree-metadata-recovery.md) -- [Task priority visibility](requirements/task-priority-visibility.md) -- [Threads task actions](requirements/threads-task-actions.md) -- [Task Title Length Limit](requirements/title-length-limit.md) -- [User Question Turn Boundary](requirements/user-question-turn-boundary.md) -- [WIP Limits and Visible Overflow Queues](requirements/wip-limit-pull-system.md) -- [Tasks Without Repositories](requirements/without-repositories.md) -- [Workflow completion-signal payload delivery](requirements/workflow-completion-signal-payload-delivery.md) -- [Cancelled Turn Completion](requirements/workflow-cancelled-turn-completion.md) -- [Workflow Cycle Guardrails](requirements/workflow-cycle-guardrails.md) -- [Workflow Duplication](requirements/workflow-duplication.md) -- [Explicit Workflow-Step Completion Signal](requirements/workflow-explicit-completion-signal.md) -- [Workflow Profile Session Lifecycle and Recipients](requirements/workflow-profile-session-lifecycle.md) -- [Agent decision recording](requirements/workflow-quorum-decision-recording-agent-surface.md) -- [Quorum ordering and concurrency](requirements/workflow-quorum-decision-recording-concurrency.md) -- [Quorum diagnostics](requirements/workflow-quorum-decision-recording-diagnostics.md) -- [Quorum participant slate](requirements/workflow-quorum-decision-recording-participant-slate.md) -- [Decision-triggered quorum re-evaluation](requirements/workflow-quorum-decision-recording-reevaluation.md) -- [Quorum regression behavior](requirements/workflow-quorum-decision-recording-regression.md) -- [Quorum step binding and thresholds](requirements/workflow-quorum-decision-recording-step-binding.md) -- [Quorum verdict vocabulary](requirements/workflow-quorum-decision-recording-verdict-vocabulary.md) -- [Workflow quorum decision recording](requirements/workflow-quorum-decision-recording.md) -- [Conditional Workflow Session Settings](requirements/workflow-session-settings.md) -- [Workflow Settings Autosave](requirements/workflow-settings-autosave.md) -- [Workflow Step Agent Start Ownership](requirements/workflow-step-agent-start-ownership.md) -- [Workflow Sync — Per-User Workspace Authorization](requirements/workflow-sync-workspace-authz.md) -- [Workflow task-step transition ledger scenarios](requirements/workflow-task-step-transition-ledger-scenarios.md) -- [Workflow task-step transition ledger](requirements/workflow-task-step-transition-ledger.md) -- [Human Assignee and Actor Attribution](requirements/human-assignee.md) - -### System design - -- [Task completion, conversation follow-ups, and workspace access](system-design/task-completion.md) - -- [Additional Session Workspace Reuse](system-design/additional-session-workspace-reuse.md) -- [Environment-Owned Git Status](system-design/environment-owned-git-status.md) -- [Attach Workspace Sources](system-design/attach-workspace-sources.md) -- [Command-panel archived task results](system-design/command-panel-archived-task-results.md) -- [Detached Workspace Continuity](system-design/detached-workspace-continuity.md) -- [Quick Chat Agent Titles](system-design/quick-chat-agent-titles.md) -- [Quick Chat Session Resumption](system-design/quick-chat-session-resumption.md) -- [Active clarification lifecycle](system-design/clarification-active-lifecycle.md) -- [Clarification response reliability](system-design/clarification-response-reliability.md) -- [External task ID idempotency operations](system-design/external-id-idempotency-operations.md) -- [External task ID idempotency](system-design/external-id-idempotency.md) -- [Task model unification](system-design/model-unification.md) -- [MCP Tool Name Stability](system-design/mcp-tool-name-stability.md) -- [MCP workspace modes](system-design/mcp-workspace-mode.md) -- [Remote Contribution Tasks](system-design/remote-contribution-tasks.md) -- [Passthrough Queued Prompt Dispatch](system-design/passthrough-queued-prompt-dispatch.md) -- [Saved Prompt Delivery](system-design/saved-prompt-delivery.md) -- [Passthrough Initial Prompt Turn Boundary](system-design/passthrough-initial-prompt-turn-boundary.md) -- [Prompt attachments](system-design/prompt-attachments.md) -- [Task Actions Menu on Preview and Detail Surfaces](system-design/task-actions-menu.md) -- [Task menu grouping](system-design/task-menu-grouping.md) -- [Task Archive Confirmation](system-design/archive-confirmation.md) -- [Task removal navigation](system-design/removal-navigation.md) -- [Task plan content size limit](system-design/plan-content-size-limit.md) -- [Task Plan Comments](system-design/plan-comments.md) -- [Task plan write consistency](system-design/plan-write-consistency.md) -- [Task plan write lifecycle](system-design/plan-write-lifecycle.md) -- [Task plan append-mode write](system-design/plan-write-append-mode.md) -- [Task plan append-mode agent text](system-design/plan-write-append-mode-agent-text.md) -- [Task Runtime Cleanup](system-design/runtime-cleanup.md) -- [Task Cleanup Preparation](system-design/runtime-cleanup-preparation.md) -- [Task Terminal Persistence](system-design/task-terminal-persistence.md) -- [Runtime Task-State Publication Order](system-design/runtime-state-publication-order.md) -- [Queued Run Scheduling](system-design/run-scheduling.md) -- [Resume prompt queue](system-design/resume-prompt-queue.md) -- [Session Delete Preserves Task Workspaces](system-design/session-delete-resource-cleanup.md) -- [Task Dependencies and Auto-Start Chains](system-design/task-dependencies.md) -- [Edit task dependencies](system-design/task-dependency-detail-editing.md) -- [Session Launch Repository Resolution](system-design/launch-repository-resolution.md) -- [Task Launch Failure Recovery](system-design/task-launch-failure-recovery.md) -- [Worktree metadata recovery](system-design/worktree-metadata-recovery.md) -- [Task Create Launch Preview](system-design/task-create-launch-preview.md) -- [Task priority visibility](system-design/task-priority-visibility.md) -- [Threads task actions](system-design/threads-task-actions.md) -- [WIP Limits and Visible Overflow Queues](system-design/wip-limit-pull-system.md) -- [Workflow completion-signal payload delivery](system-design/workflow-completion-signal-payload-delivery.md) -- [Signal-Gated Manual Move Visibility](system-design/workflow-signal-gated-manual-move-visibility.md) -- [Workflow quorum decision recording](system-design/workflow-quorum-decision-recording.md) -- [Workflow Step Agent Start Ownership](system-design/workflow-step-agent-start-ownership.md) -- [Workflow Step Fixed-Profile Routing](system-design/workflow-step-fixed-profile-routing.md) -- [Workflow Profile Session Lifecycle and Recipients](system-design/workflow-profile-session-lifecycle.md) -- [Workflow task-step transition ledger](system-design/workflow-task-step-transition-ledger.md) -- [Human Assignee](system-design/human-assignee.md) -- [Task Create Agent Compatibility Recovery](system-design/task-create-agent-executor-compatibility.md) - ## Migration record -Migration remains in progress. Files that retain migration wrappers still need -extraction before this system can return to a complete migration state. +Migration remains in progress. Use the catalog command to find the current +requirement and system-design documents for this system. Other migrated files +still need the same extraction before this system can return to a complete +migration state. ## Related systems diff --git a/docs/specs/templates/system-readme.md b/docs/specs/templates/system-readme.md index aa06094801..0e6207cf3d 100644 --- a/docs/specs/templates/system-readme.md +++ b/docs/specs/templates/system-readme.md @@ -21,15 +21,16 @@ List the concepts, behavior, data, and contracts that this system owns. List adjacent concepts that another system owns. Link to that system. -## Specification map +## Find specifications -### Requirements +Use the catalog command to list this system's current documents: -- [Capability](requirements/capability.md) + python3 scripts/list-docs.py specs --system --format markdown + python3 scripts/list-docs.py specs --system --kind requirement --format paths + python3 scripts/list-docs.py specs --system --kind system-design --format paths -### System design - -- [Capability](system-design/capability.md) +Do not copy the command output into this README. Keep this file focused on the +system boundary, migration record, and related systems. ## Related systems diff --git a/docs/specs/ui/README.md b/docs/specs/ui/README.md index e23c54be09..218ff1efde 100644 --- a/docs/specs/ui/README.md +++ b/docs/specs/ui/README.md @@ -15,218 +15,6 @@ UI owns responsive behavior and reusable presentation preferences, including task-listing modes and Home destination choices. Other systems retain task, runtime, and workspace lifecycle/state ownership. -## Map - -### Requirements - -- [Mobile task-view access](requirements/mobile-task-view-access.md) - -- [Control sizing](requirements/control-sizing.md) -- [ACP model summary](requirements/acp-model-configuration-summary.md) -- [ACP Shell Command Output](requirements/acp-shell-command-output.md) -- [Adaptive Kanban](requirements/adaptive-kanban.md) -- [Task Add-Panel PR Submenu](requirements/add-panel-pr-submenu.md) -- [Agent Launch Prompt Composer](requirements/agent-launch-prompt-composer.md) -- [Dialog containment](requirements/dialog-content-containment.md) -- [Descriptive select options](requirements/descriptive-select-options.md) -- [Surface text](requirements/surface-text-hierarchy.md) -- [Message comments](requirements/agent-message-comments.md) -- [Agent Todo List Panel](requirements/agent-todo-list-panel.md) -- [App Status Bar](requirements/app-status-bar.md) -- [Column visibility](requirements/board-step-visibility-filter.md) -- [Inspect annotation submission](requirements/browser-inspect-annotations-save.md) -- [Cancel-turn progress](requirements/cancel-turn-progress.md) -- [Action feedback](requirements/changes-file-action-feedback.md) -- [File-row containment](requirements/changes-file-row-containment.md) -- [Changes walkthrough](requirements/changes-walkthrough-toolbar-width.md) -- [Task PR Automation Controls](requirements/ci-pr-automation.md) -- [Merge Queue Recovery Controls](requirements/ci-pr-merge-queue-recovery-controls.md) -- [Clarification context](requirements/clarification-context.md) -- [Clarification submit feedback](requirements/clarification-submit-feedback.md) -- [Command-panel task reveal](requirements/command-panel-sidebar-task-reveal.md) -- [Task activity icons](requirements/command-panel-task-activity-icons.md) -- [Workflow step navigation](requirements/compact-workflow-step-navigation.md) -- [Preview panel step navigation](requirements/kanban-preview-workflow-step-navigation.md) -- [Comment Markdown Rendering](requirements/comment-markdown.md) -- [Mention recency](requirements/composer-mention-recency.md) -- [Composer Suggestion Overlays](requirements/composer-suggestion-overlays.md) -- [Context Compaction Count](requirements/context-compaction-count.md) -- [Context Window Reset Freshness](requirements/context-window-reset-freshness.md) -- [Context Window Unmeasured State](requirements/context-window-unmeasured-state.md) -- [Embedded VS Code Executor Availability](requirements/embedded-vscode-executor-availability.md) -- [VS Code windows](requirements/embedded-vscode-windows-availability.md) -- [Empty-Turn Notice and Slash-Command Hint](requirements/empty-turn-notice.md) -- [Entity Reference Composer](requirements/entity-reference-composer.md) -- [Executor settings card spacing](requirements/executor-settings-card-spacing.md) -- [VCS File Links](requirements/external-vcs-file-links.md) -- [File Tree Chat Context](requirements/file-tree-chat-context.md) -- [File Tree Keyboard Scope](requirements/file-tree-keyboard-scope.md) -- [Reload Kandev after frozen-tab restore](requirements/fix-duplicated-tab-stale-data.md) -- [GitHub PR Review Actions](requirements/github-pr-review-actions.md) -- [GitHub Saved-Query Default Views](requirements/github-saved-query-defaults.md) -- [Kandev MCP Tool Results](requirements/kandev-mcp-tool-results.md) -- [Native HTML File Preview](requirements/native-html-preview.md) -- [Auto-hide empty workflow steps](requirements/kanban-auto-hide-empty-columns.md) -- [Repair last-prompt transcript pinning](requirements/last-prompt-pinning-regressions.md) -- [Repair merge commit details](requirements/merge-commit-details.md) -- [Mermaid Rendering](requirements/mermaid-rendering.md) -- [Message favorite star mobile sizing](requirements/message-favorite-star-mobile-size.md) -- [Metadata dialog](requirements/message-metadata-overflow.md) -- [Queue auto-merge (deprecated)](requirements/message-queue-auto-merge.md) -- [Queue auto-merge session overrides (active)](requirements/message-queue-auto-merge-session-overrides.md) -- [Message queue automation controls (active)](requirements/message-queue-automation-controls.md) -- [Message queue management](requirements/message-queue-management.md) -- [Merge queued](requirements/message-queue-merge.md) -- [Pin the Message Queue Panel](requirements/message-queue-pin.md) -- [Reorder Queued Messages](requirements/message-queue-reorder.md) -- [Pending auto-run (deprecated)](requirements/message-queue-run.md) -- [Send Queued Messages Now](requirements/message-queue-send-now.md) -- [Mobile topbar actions](requirements/mobile-quick-chat-topbar.md) -- [Mobile Task Chrome](requirements/mobile-task-chrome.md) -- [Mobile Task Navigation](requirements/mobile-task-navigation.md) -- [Mobile Action Confirmations](requirements/mobile-action-confirmations.md) -- [Plan comments](requirements/plan-comment-drafts.md) -- [Plan Editor Task-Switch Stability](requirements/plan-editor-task-switch-stability.md) -- [Port-forwarding discovery](requirements/port-forwarding-discovery.md) -- [Open proxy URLs in the browser panel](requirements/port-proxy-browser-panel.md) -- [Responsive PR Detail Header](requirements/pr-detail-header-width.md) -- [Repair PR-only commit details](requirements/pr-only-commit-details.md) -- [PR Task Status Summary](requirements/pr-task-status-summary.md) -- [PR walkthrough](requirements/pr-walkthrough.md) -- [Preview Sprites Transient Retry](requirements/preview-sprites-transient-retry.md) -- [Persistent status motion](requirements/persistent-status-motion.md) -- [Prompt History Panel](requirements/prompt-history-panel.md) -- [Prompt paste: Nerd Font glyphs](requirements/prompt-paste-nerd-font-glyphs.md) -- [Prompt turn duration](requirements/prompt-turn-duration.md) -- [Docs preview](requirements/published-docs-preview-reliability.md) -- [Quick Chat elevation](requirements/quick-chat-elevation.md) -- [Quick Chat viewport layout](requirements/quick-chat-viewport-layout.md) -- [Quick Chat Idle Dot](requirements/quick-chat-idle-dot.md) -- [Quick Chat and Terminal Tabs](requirements/quick-terminal.md) -- [Relative last seen](requirements/relative-last-seen.md) -- [Responsive Plan Formatting](requirements/responsive-plan-formatting.md) -- [Resizable Markdown Table Columns](requirements/resizable-markdown-tables.md) -- [Review File Status Cues](requirements/review-file-status.md) -- [Review Markdown Preview](requirements/review-markdown-preview.md) -- [Search/filter dropdown scroll reset](requirements/search-filter-scroll-reset.md) -- [Saved Task View Deletion Confirmation](requirements/saved-task-view-deletion-confirmation.md) -- [Selected option prominence](requirements/selected-option-picker-prominence.md) -- [Session](requirements/session-start-composer-readiness.md) -- [Session tab delete feedback](requirements/session-tab-delete-feedback.md) -- [Settings Discovery](requirements/settings-discovery.md) -- [Settings Menu Default](requirements/settings-menu-default.md) -- [Settings Manual Save](requirements/settings-manual-save.md) -- [Settings Prompt Editor](requirements/settings-prompt-editor.md) -- [Consistent settings typography](requirements/settings-typography.md) -- [Sidebar Automatic Task Colors](requirements/sidebar-automatic-task-colors.md) -- [Sidebar Archived Task Views](requirements/sidebar-archived-filter.md) -- [Sidebar Diff Stat Priority](requirements/sidebar-diff-stat-priority.md) -- [Sidebar empty task alignment](requirements/sidebar-empty-task-alignment.md) -- [Sidebar Effective Task Tree State](requirements/sidebar-effective-task-tree-state.md) -- [Sidebar Last Activity Sort](requirements/sidebar-last-activity-sort.md) -- [Sidebar Queued Prompt Count Badge](requirements/sidebar-queued-prompt-count.md) -- [Repository Groups](requirements/sidebar-repository-grouping.md) -- [Sidebar Task Focus](requirements/sidebar-task-focus.md) -- [Sidebar Task Completion Icons](requirements/sidebar-task-completion-icons.md) -- [Sidebar Task Row Presentation](requirements/sidebar-task-row-presentation.md) -- [Direct Sidebar View Creation](requirements/sidebar-view-creation.md) -- [Slash Command Composer Selection](requirements/slash-command-composer.md) -- [Subagent Observability](requirements/subagent-observability.md) -- [Nested Submodule Review](requirements/submodule-review.md) -- [Confirmations](requirements/confirmation-warning-hierarchy.md) -- [Task Layout Profiles](requirements/task-layout-profiles.md) -- [Task Agent Tab Reconciliation](requirements/task-agent-tab-reconciliation.md) -- [Threads Deck](requirements/threads-conversation-deck.md) -- [Task Listing Display Preferences](requirements/task-listing-display-preferences.md) -- [Task transcript history visibility](requirements/task-prompt-transcript-visibility.md) -- [Task Review Shortcut Switcher](requirements/task-review-shortcut.md) -- [Task Surface Refresh](requirements/task-surface-refresh.md) -- [Workspace Search](requirements/task-workspace-content-search.md) -- [Terminal close feedback](requirements/terminal-close-feedback.md) -- [Terminal Rendering](requirements/terminal-rendering.md) -- [Terminal Touch Scrolling](requirements/terminal-touch-scrolling.md) -- [Toast theme](requirements/toast-theme.md) -- [Thinking Message Preview](requirements/thinking-message-preview.md) -- [Transcript Auto-scroll Stability](requirements/transcript-auto-scroll.md) -- [Transcript Navigation Settings](requirements/transcript-navigation-settings.md) -- [Voice Mode In Task Behavior](requirements/voice-mode-task-behavior.md) -- [Walkthrough Feedback Controls](requirements/walkthrough-feedback-controls.md) -- [Walkthrough nav](requirements/walkthrough-navigation-layout.md) -- [WebKit Task Dialog Rendering](requirements/webkit-task-dialog-rendering.md) -- [Active workspace first in settings](requirements/workspace-active-first-order.md) -- [WebSocket Connectivity Warning](requirements/ws-connectivity-warning.md) - -### Design - -- [Mobile task-view access](system-design/mobile-task-view-access.md) -- [Agent launch prompt composer](system-design/agent-launch-prompt-composer.md) -- [Control sizing](system-design/control-sizing.md) -- [Adaptive Kanban](system-design/adaptive-kanban.md) -- [Clarification submit feedback](system-design/clarification-submit-feedback.md) -- [Dialog containment](system-design/dialog-content-containment.md) -- [Descriptive select options](system-design/descriptive-select-options.md) -- [Surface text](system-design/surface-text-hierarchy.md) -- [Agent Todo List Panel](system-design/agent-todo-list-panel.md) -- [App Status Bar](system-design/app-status-bar.md) -- [Action feedback](system-design/changes-file-action-feedback.md) -- [File-row containment](system-design/changes-file-row-containment.md) -- [Mention recency](system-design/composer-mention-recency.md) -- [Composer Suggestion Overlays](system-design/composer-suggestion-overlays.md) -- [Compact step navigation](system-design/compact-workflow-step-navigation.md) -- [Kanban preview navigation](system-design/kanban-preview-workflow-step-navigation.md) -- [Comment Markdown Rendering](system-design/comment-markdown.md) -- [Workflow column visibility (Part 1)](system-design/board-step-visibility-filter-01.md) -- [Workflow column visibility (Part 2)](system-design/board-step-visibility-filter-02.md) -- [Task PR auto 1](system-design/ci-pr-automation-01.md) -- [Task PR auto 2](system-design/ci-pr-automation-02.md) -- [Task PR auto 3](system-design/ci-pr-automation-03.md) -- [Merge Queue Recovery Controls](system-design/ci-pr-merge-queue-recovery-controls.md) -- [Entity Reference Composer](system-design/entity-reference-composer.md) -- [File Tree Keyboard Scope](system-design/file-tree-keyboard-scope.md) -- [File Tree Chat](system-design/file-tree-chat-context.md) -- [MCP results](system-design/kandev-mcp-tool-results.md) -- [Message queue row controls](system-design/message-queue-row-controls.md) -- [Message Queue Automation Controls (current)](system-design/message-queue-automation-controls.md) -- [Native HTML File Preview](system-design/native-html-preview.md) -- [Mobile Task Chrome](system-design/mobile-task-chrome.md) -- [Mobile Action Confirmations](system-design/mobile-action-confirmations.md) -- [Mobile workspace topbar](system-design/mobile-quick-chat-topbar.md) -- [Mobile Menu Backdrops System Design](system-design/mobile-menu-backdrops.md) -- [Persistent status motion](system-design/persistent-status-motion.md) -- [Repository Groups](system-design/sidebar-repository-grouping.md) -- [Sidebar Automatic Task Colors](system-design/sidebar-automatic-task-colors.md) -- [Sidebar Effective Task Tree State](system-design/sidebar-effective-task-tree-state.md) -- [Sidebar Task Focus](system-design/sidebar-task-focus.md) -- [Sidebar task row](system-design/sidebar-task-row-presentation.md) -- [PR walkthrough](system-design/pr-walkthrough.md) -- [PR Task Status Summary](system-design/pr-task-status-summary.md) -- [Queued message editing](system-design/message-queue-edit.md) -- [Prompt History Panel](system-design/prompt-history-panel.md) -- [Quick Chat and terminal elevation](system-design/quick-chat-elevation.md) -- [Quick Chat viewport layout](system-design/quick-chat-viewport-layout.md) -- [Quick Chat and Terminal Tabs](system-design/quick-terminal.md) -- [Plan comments](system-design/plan-comment-drafts.md) -- [Plan Editor Task-Switch Stability](system-design/plan-editor-task-switch-stability.md) -- [Responsive Plan Formatting](system-design/responsive-plan-formatting.md) -- [Confirmations](system-design/confirmation-warning-hierarchy.md) -- [Resizable Markdown Table Columns](system-design/resizable-markdown-tables.md) -- [Saved Task View Deletion Confirmation](system-design/saved-task-view-deletion-confirmation.md) -- [Session](system-design/session-start-composer-readiness.md) -- [Task Layout Profiles](system-design/task-layout-profiles.md) -- [Task Listing Display Preferences](system-design/task-listing-display-preferences.md) -- [Task surface](system-design/task-surface-render-isolation.md) -- [Task Agent Tab Reconciliation](system-design/task-agent-tab-reconciliation.md) -- [Threads Deck](system-design/threads-conversation-deck.md) -- [Command-panel Sidebar Task Reveal](system-design/command-panel-sidebar-task-reveal.md) -- [Command-panel activity icons](system-design/command-panel-task-activity-icons.md) -- [Terminal Rendering](system-design/terminal-rendering.md) -- [Terminal Touch Scrolling](system-design/terminal-touch-scrolling.md) -- [Toast theme](system-design/toast-theme.md) -- [Thinking Message Preview](system-design/thinking-message-preview.md) -- [Settings Menu Default](system-design/settings-menu-default.md) -- [Transcript history visibility](system-design/task-prompt-transcript-visibility.md) -- [Transcript Auto-scroll Stability](system-design/transcript-auto-scroll.md) - ## Related - [Platform](../platform/README.md) diff --git a/docs/specs/workspaces/README.md b/docs/specs/workspaces/README.md index cdb967ff90..1297637624 100644 --- a/docs/specs/workspaces/README.md +++ b/docs/specs/workspaces/README.md @@ -26,42 +26,11 @@ Git state. - Provider credentials belong to the [integration system](../integrations/README.md). - Workspace settings presentation belongs to the [UI system](../ui/README.md). -## Specification map - -### Requirements - -- [Branch Policies](requirements/branch-policies.md) -- [Create a Local Repository During Task Creation](requirements/create-local-repository.md) -- [Empty Remote Repositories](requirements/empty-remote-repositories.md) -- [Kanban workspace creation](requirements/creation.md) -- [Workspace Deletion](requirements/deletion.md) -- [Improve Kandev](requirements/improve-kandev.md) -- [Local Workspace Repositories](requirements/local-repositories.md) -- [Organization Units](requirements/org-units.md) -- [Repository and Workspace Secrets](requirements/repository-secrets.md) -- [Repository Sets](requirements/repository-sets.md) -- [Copy and Move Secrets Between Scopes](requirements/secret-scope-transfer.md) -- [Workspace Base-Branch Propagation](requirements/workspace-base-branch-propagation.md) -- [Worktree Base Refresh](requirements/worktree-base-refresh.md) -- [Worktree Branch Templates](requirements/worktree-branch-templates.md) - -### System design - -- [Local repository creation](system-design/create-local-repository.md) -- [Secret reference protection](system-design/repository-secrets.md) -- [Empty Remote Repositories](system-design/empty-remote-repositories.md) -- [Improve Kandev](system-design/improve-kandev.md) -- [Copy and Move Secrets Between Scopes](system-design/secret-scope-transfer.md) -- [Branch Policies](system-design/branch-policies.md) -- [Worktree Base Refresh](system-design/worktree-base-refresh.md) -- [Local Workspace Repositories](system-design/local-repositories.md) -- [Organization Units](system-design/org-units.md) -- [Repository Sets](system-design/repository-sets.md) - ## Migration record Migration remains in progress while legacy source detail is extracted from the -canonical requirement and system-design documents above. +canonical requirement and system-design documents. Use the catalog command to +find current sources. ## Related systems diff --git a/scripts/lint-spec-files.py b/scripts/lint-spec-files.py index 531dbbc08f..7bef88741b 100644 --- a/scripts/lint-spec-files.py +++ b/scripts/lint-spec-files.py @@ -9,6 +9,27 @@ import sys from dataclasses import dataclass from pathlib import Path +try: + from spec_metadata import ( + VALID_DESIGN_STATUSES, + VALID_MIGRATION_STATUSES, + VALID_REQUIREMENT_STATUSES, + VALID_SYSTEM_STATUSES, + classify_path, + parse_frontmatter as parse_metadata_frontmatter, + validate_metadata, + ) +except ModuleNotFoundError: + from scripts.spec_metadata import ( + VALID_DESIGN_STATUSES, + VALID_MIGRATION_STATUSES, + VALID_REQUIREMENT_STATUSES, + VALID_SYSTEM_STATUSES, + classify_path, + parse_frontmatter as parse_metadata_frontmatter, + validate_metadata, + ) + @dataclass(frozen=True) class Violation: @@ -18,10 +39,6 @@ class Violation: message: str -VALID_REQUIREMENT_STATUSES = {"draft", "active", "deprecated"} -VALID_DESIGN_STATUSES = {"draft", "current", "superseded"} -VALID_SYSTEM_STATUSES = {"draft", "active", "retired"} -VALID_MIGRATION_STATUSES = {"in_progress", "complete"} SIZE_EXCEPTIONS_PATH = "docs/specs/spec-lint-exceptions.tsv" REQ_ID_PATTERN = r"REQ-[A-Z0-9]+(?:-[A-Z0-9]+)*-\d{3}" AC_ID_PATTERN = r"AC-[A-Z0-9]+(?:-[A-Z0-9]+)*-\d{3}\.\d+" @@ -141,19 +158,8 @@ def lint_specs( continue assert metadata is not None - declared_system = metadata.get("system") - if declared_system != system: - violations.append( - Violation( - "system-owner", - path, - 1, - f"frontmatter system must be `{system}`, found `{declared_system or ''}`", - ) - ) - if kind == "requirement": - violations.extend(check_requirement_metadata(path, metadata)) + violations.extend(check_requirement_metadata(path, metadata, system)) reqs, criteria = collect_requirement_ids(path, text) if not reqs: violations.append( @@ -191,7 +197,7 @@ def lint_specs( ) ) else: - violations.extend(check_design_metadata(path, metadata)) + violations.extend(check_design_metadata(path, metadata, system)) references = metadata.get("requirements", []) if isinstance(references, list): for reference in references: @@ -406,30 +412,6 @@ def load_previous_size_exceptions(root: Path) -> dict[str, int] | None: return None -def classify_path(relative: Path) -> tuple[str, str | None]: - parts = relative.parts - try: - spec_index = parts.index("specs") - except ValueError: - return "unknown", None - inside = parts[spec_index + 1 :] - if not inside: - return "unknown", None - if inside[0] == "guide": - return "guide", None - if inside[0] == "templates": - return "template", None - if inside[0] == "product": - return "product", None - if len(inside) >= 3 and inside[1] == "requirements": - return "requirement", inside[0] - if len(inside) >= 3 and inside[1] == "system-design": - return "system-design", inside[0] - if len(inside) == 2 and inside[1] in {"README.md", "glossary.md"}: - return "system-index", inside[0] - return "legacy", None - - def is_safe_regular_file(path: Path, root: Path) -> bool: if path.is_symlink() or not path.is_file(): return False @@ -575,120 +557,35 @@ def check_legacy_size_ratchet( def parse_frontmatter(text: str) -> tuple[dict | None, int, str | None]: - lines = text.splitlines() - if not lines or lines[0] != "---": - return None, 1, "new specification document must start with YAML frontmatter" - try: - end = lines.index("---", 1) - except ValueError: - return None, 1, "YAML frontmatter has no closing delimiter" - - metadata: dict[str, str | list[str]] = {} - current_list: str | None = None - for line_number, line in enumerate(lines[1:end], start=2): - if re.match(r"^\s+-\s+", line) and current_list: - value = re.sub(r"^\s+-\s+", "", line).strip().strip('"\'`') - current_value = metadata.setdefault(current_list, []) - if not isinstance(current_value, list): - return None, line_number, f"frontmatter field `{current_list}` mixes scalar and list values" - current_value.append(value) - continue - match = re.match(r"^(?P[a-z][a-z0-9_-]*):(?:\s*(?P.*))?$", line) - if not match: - if not line.strip(): - continue - return None, line_number, "frontmatter contains unsupported YAML" - key = match.group("key") - value = (match.group("value") or "").strip() - if value == "[]": - metadata[key] = [] - current_list = None - elif value: - metadata[key] = value.strip('"\'`') - current_list = None - else: - metadata[key] = [] - current_list = key - return metadata, 1, None + parsed = parse_metadata_frontmatter(text, require=True) + return parsed.metadata, parsed.line, parsed.error -def check_requirement_metadata(path: Path, metadata: dict) -> list[Violation]: - status = metadata.get("status") - if status in VALID_REQUIREMENT_STATUSES: - return [] +def metadata_violations( + path: Path, kind: str, system: str | None, metadata: dict +) -> list[Violation]: return [ - Violation( - "requirement-status", - path, - 1, - f"requirement status must be one of {sorted(VALID_REQUIREMENT_STATUSES)}, found `{status or ''}`", - ) + Violation(issue.code, path, 1, issue.message) + for issue in validate_metadata(kind, system, metadata) ] -def check_system_index_metadata(path: Path, metadata: dict, system: str | None) -> list[Violation]: - violations = [] - if metadata.get("status") not in VALID_SYSTEM_STATUSES: - violations.append( - Violation( - "system-index-status", - path, - 1, - f"system status must be one of {sorted(VALID_SYSTEM_STATUSES)}", - ) - ) - if metadata.get("system") != system: - violations.append( - Violation( - "system-owner", - path, - 1, - f"frontmatter system must be `{system}`, found `{metadata.get('system', '')}`", - ) - ) - if metadata.get("specification_version") != "1": - violations.append( - Violation( - "system-index-version", - path, - 1, - "system index must set `specification_version: 1`", - ) - ) - if metadata.get("migration") not in VALID_MIGRATION_STATUSES: - violations.append( - Violation( - "system-index-migration", - path, - 1, - f"migration must be one of {sorted(VALID_MIGRATION_STATUSES)}", - ) - ) - return violations +def check_requirement_metadata( + path: Path, metadata: dict, system: str | None = None +) -> list[Violation]: + return metadata_violations(path, "requirement", system, metadata) -def check_design_metadata(path: Path, metadata: dict) -> list[Violation]: - violations = [] - status = metadata.get("status") - if status not in VALID_DESIGN_STATUSES: - violations.append( - Violation( - "system-design-status", - path, - 1, - f"system-design status must be one of {sorted(VALID_DESIGN_STATUSES)}, found `{status or ''}`", - ) - ) - if not isinstance(metadata.get("requirements"), list): - violations.append( - Violation( - "system-design-requirements", - path, - 1, - "system design must declare `requirements` as a YAML list, including an explicit empty list", - ) - ) - return violations +def check_system_index_metadata( + path: Path, metadata: dict, system: str | None +) -> list[Violation]: + return metadata_violations(path, "system-index", system, metadata) + + +def check_design_metadata( + path: Path, metadata: dict, system: str | None = None +) -> list[Violation]: + return metadata_violations(path, "system-design", system, metadata) def collect_requirement_ids(path: Path, text: str) -> tuple[list[tuple[str, int]], list[tuple[str, int]]]: diff --git a/scripts/list-docs.py b/scripts/list-docs.py new file mode 100644 index 0000000000..b919780dba --- /dev/null +++ b/scripts/list-docs.py @@ -0,0 +1,589 @@ +#!/usr/bin/env python3 +"""List and validate architecture decisions and specifications.""" + +from __future__ import annotations + +import argparse +import json +import re +import sys +from dataclasses import dataclass +from pathlib import Path +from typing import Iterable + +try: + from spec_metadata import ( + classify_path, + metadata_text as spec_metadata_text, + parse_frontmatter as parse_spec_frontmatter, + validate_metadata, + ) +except ModuleNotFoundError: + from scripts.spec_metadata import ( + classify_path, + metadata_text as spec_metadata_text, + parse_frontmatter as parse_spec_frontmatter, + validate_metadata, + ) + + +SCHEMA_VERSION = 1 +DECISION_METADATA_KEYS = {"status", "date", "area", "scope", "tags"} +SPEC_KINDS = ("system", "glossary", "requirement", "system-design", "product", "legacy") +SPEC_KIND_ORDER = {kind: index for index, kind in enumerate(SPEC_KINDS)} +FIELD_LINE = re.compile( + r"^\*{0,2}(?PStatus|Date|Area|Scope|Tags)" + r"(?::\s*\*{0,2}\s*|\*{0,2}\s*:\s*)(?P.*?)\s*$", + re.IGNORECASE, +) +HEADING_FIELD = re.compile(r"^##\s+(?PStatus|Date|Area|Scope|Tags)\s*$", re.IGNORECASE) +FIRST_HEADING = re.compile(r"^#\s+(?P\S.*)$") +DECISION_ID_PREFIX = re.compile( + r"^(?:ADR-)?(?:\d{4}|(?:\d{4}-\d{2}-\d{2}(?:-[a-z0-9-]+)?))\s*(?::|[—–])\s+", + re.IGNORECASE, +) + + +class CatalogError(Exception): + """A source file cannot be represented in the catalog.""" + + +class SkipSource(Exception): + """A Markdown file is an authoring entry page, not a catalog source.""" + + +@dataclass(frozen=True) +class Document: + type: str + path: str + title: str + text: str + id: str + status: str | None = None + area: str | None = None + date: str | None = None + system: str | None = None + kind: str | None = None + + +def repository_path(root: Path, path: Path) -> str: + try: + return path.resolve().relative_to(root.resolve()).as_posix() + except ValueError as exc: + raise CatalogError(f"{path}: path is outside the repository root") from exc + + +def read_source(root: Path, path: Path) -> tuple[str, str]: + relative = repository_path(root, path) + if path.is_symlink() or not path.is_file(): + raise CatalogError(f"{relative}: source must be a regular file") + try: + return relative, path.read_text(encoding="utf-8") + except (OSError, UnicodeDecodeError) as exc: + raise CatalogError(f"{relative}: cannot read source file: {exc}") from exc + + +def first_heading(lines: list[str], start: int, relative: str) -> str: + for line in lines[start:]: + match = FIRST_HEADING.match(line) + if match: + return match.group("title").strip() + raise CatalogError(f"{relative}: source must contain a level-one title heading") + + +def decision_title(heading: str) -> str: + return DECISION_ID_PREFIX.sub("", heading, count=1).strip() + + +def normalize_field_value(value: str) -> str: + return value.strip().strip("|").strip() + + +def metadata_key(raw_key: str) -> str: + key = raw_key.strip().strip("*").lower() + return "area" if key in {"scope", "tags"} else key + + +def add_metadata_value( + fields: dict[str, str], + raw_key: str, + raw_value: str, + relative: str, +) -> None: + key = metadata_key(raw_key) + value = normalize_field_value(raw_value) + if not value: + return + if key == "area" and raw_key.strip().lower() != "area" and "area" in fields: + return + if key in fields: + raise CatalogError(f"{relative}: duplicate {key} metadata in the ADR header") + fields[key] = value + + +def parse_metadata_line(line: str) -> tuple[str, str] | None: + stripped = line.strip() + stripped = re.sub(r"^[-*]\s+", "", stripped) + if stripped.startswith("|"): + cells = [cell.strip() for cell in stripped.strip("|").split("|")] + if len(cells) >= 2: + key = cells[0].strip().strip("*") + if key.lower() in DECISION_METADATA_KEYS: + return key, cells[1] + return None + match = FIELD_LINE.match(stripped) + if match: + return match.group("key"), match.group("value") + return None + + +def parse_decision_metadata( + lines: list[str], start: int, frontmatter: dict[str, object], relative: str +) -> dict[str, str]: + fields: dict[str, str] = {} + for key in ("status", "date", "area"): + value = frontmatter.get(key) + if isinstance(value, list): + value = ", ".join(str(item) for item in value) + if isinstance(value, str): + add_metadata_value(fields, key, value, relative) + + pending_key: str | None = None + pending_value: list[str] = [] + + def flush_pending() -> None: + nonlocal pending_key, pending_value + if pending_key is not None: + add_metadata_value(fields, pending_key, " ".join(pending_value), relative) + pending_key = None + pending_value = [] + + index = start + while index < len(lines): + line = lines[index] + heading_match = HEADING_FIELD.match(line.strip()) + if heading_match: + flush_pending() + value_index = index + 1 + while value_index < len(lines) and not lines[value_index].strip(): + value_index += 1 + if value_index < len(lines) and not lines[value_index].lstrip().startswith("#"): + pending_key = heading_match.group("key") + pending_value = [lines[value_index].strip()] + index = value_index + 1 + continue + elif re.match(r"^##\s+", line): + flush_pending() + break + + parsed = parse_metadata_line(line) + if parsed: + flush_pending() + pending_key = parsed[0] + pending_value = [parsed[1]] + elif not line.strip(): + flush_pending() + elif pending_key is not None: + pending_value.append(line.strip()) + index += 1 + flush_pending() + if not fields.get("status"): + raise CatalogError(f"{relative}: ADR metadata must define a non-empty status") + date = fields.get("date") + if date and not re.match(r"^\d{4}-\d{2}-\d{2}\b", date): + raise CatalogError(f"{relative}: ADR date must start with YYYY-MM-DD") + return fields + + +def parse_decision(root: Path, path: Path) -> Document: + relative, text = read_source(root, path) + lines = text.splitlines() + parsed_frontmatter = parse_spec_frontmatter(text) + if parsed_frontmatter.error: + raise CatalogError( + f"{relative}:{parsed_frontmatter.line}: {parsed_frontmatter.error}" + ) + frontmatter = parsed_frontmatter.metadata or {} + frontmatter_end = parsed_frontmatter.end + heading = first_heading(lines, frontmatter_end, relative) + fields = parse_decision_metadata(lines, frontmatter_end, frontmatter, relative) + return Document( + type="decision", + path=relative, + title=decision_title(heading), + text=text, + id=path.stem, + status=fields.get("status"), + area=fields.get("area"), + date=fields.get("date"), + ) + + +def decision_files(root: Path) -> Iterable[Path]: + directory = root / "docs" / "decisions" + if not directory.exists(): + return () + return (path for path in sorted(directory.rglob("*.md")) if path.name != "INDEX.md") + + +def spec_files(root: Path) -> Iterable[Path]: + directory = root / "docs" / "specs" + if not directory.exists(): + return () + return ( + path + for path in sorted(directory.rglob("*.md")) + if path.name != "INDEX.md" + and path != directory / "README.md" + and "guide" not in path.relative_to(directory).parts + and "templates" not in path.relative_to(directory).parts + ) + + +def parse_spec_kind( + relative: str, frontmatter: dict[str, object] | None = None +) -> tuple[str, str | None]: + del frontmatter + inside = Path(relative).relative_to("docs/specs").parts + if not inside: + raise CatalogError(f"{relative}: specification path has no system directory") + source_kind, source_system = classify_path(Path(relative)) + if source_kind in {"guide", "template"}: + raise CatalogError(f"{relative}: authoring support files are not catalog sources") + if source_kind == "system-index": + if inside[-1] == "README.md": + return "system", source_system + return "glossary", source_system + if source_kind in {"requirement", "system-design", "product", "legacy"}: + return source_kind, source_system + raise CatalogError(f"{relative}: unsupported specification source") + + +def validate_spec_metadata( + relative: str, + kind: str, + system: str | None, + metadata: dict[str, object], + has_frontmatter: bool, +) -> None: + issues = validate_metadata(kind, system, metadata, has_frontmatter) + if issues: + raise CatalogError(f"{relative}: {issues[0].message}") + + +def parse_spec(root: Path, path: Path) -> Document: + relative, text = read_source(root, path) + if relative == "docs/specs/product/README.md": + raise SkipSource + parsed_frontmatter = parse_spec_frontmatter(text) + if parsed_frontmatter.error: + raise CatalogError( + f"{relative}:{parsed_frontmatter.line}: {parsed_frontmatter.error}" + ) + metadata = parsed_frontmatter.metadata or {} + frontmatter_end = parsed_frontmatter.end + kind, system = parse_spec_kind(relative, metadata) + has_frontmatter = bool(text.splitlines() and text.splitlines()[0] == "---") + validate_spec_metadata(relative, kind, system, metadata, has_frontmatter) + title = spec_metadata_text(metadata, "title") + if not title: + try: + title = first_heading(text.splitlines(), frontmatter_end, relative) + except CatalogError: + title = " ".join( + word.capitalize() + for word in re.split(r"[-_]+", Path(relative).stem) + if word + ) + identifier = spec_metadata_text(metadata, "id") or relative.removesuffix(".md") + return Document( + type="specification", + path=relative, + title=title, + text=text, + id=identifier, + status=spec_metadata_text(metadata, "status"), + system=system, + kind=kind, + ) + + +def load_documents( + root: Path, files: Iterable[Path], parser +) -> tuple[list[Document], list[str]]: + documents: list[Document] = [] + errors: list[str] = [] + identities: dict[str, str] = {} + for path in files: + try: + document = parser(root, path) + except SkipSource: + continue + except CatalogError as exc: + errors.append(str(exc)) + continue + identity = document.id if document.type == "decision" else f"{document.type}:{document.id}" + if identity in identities: + errors.append( + f"{document.path}: duplicate catalog identity {document.id} " + f"(already used by {identities[identity]})" + ) + continue + identities[identity] = document.path + documents.append(document) + return documents, sorted(errors) + + +def decision_sort_key(document: Document) -> tuple[int, int | str, str]: + if re.match(r"^\d{4}-\d{2}-\d{2}-", document.id): + return (1, document.id, document.path) + numeric = re.match(r"^(\d+)(?:-|$)", document.id) + if numeric: + return (0, int(numeric.group(1)), document.path) + return (2, document.id, document.path) + + +def spec_sort_key(document: Document) -> tuple[str, int, str]: + assert document.kind is not None + return (document.system or "", SPEC_KIND_ORDER[document.kind], document.path) + + +def filter_decisions( + documents: Iterable[Document], + status: str | None, + area: str | None, + text: str | None, +) -> list[Document]: + result = [] + for document in documents: + if status and leading_status_class(document.status) != status.lower(): + continue + if area and not area_matches(document.area, area): + continue + if text and text.lower() not in document.text.lower(): + continue + result.append(document) + return sorted(result, key=decision_sort_key) + + +def leading_status_class(value: str | None) -> str: + if not value: + return "" + match = re.match(r"^\s*([a-z][a-z0-9_-]*)", value, re.IGNORECASE) + return match.group(1).lower() if match else "" + + +def area_matches(value: str | None, requested: str) -> bool: + if not value: + return False + wanted = requested.strip().lower() + if value.lower() == wanted: + return True + tokens = [token.strip().lower() for token in value.split(",") if token.strip()] + if wanted in tokens: + return True + return wanted in { + token.lower() for token in re.findall(r"[a-z0-9][a-z0-9_-]*", value) + } + + +def filter_specs( + documents: Iterable[Document], + system: str | None, + kind: str | None, + status: str | None, + text: str | None, +) -> list[Document]: + result = [] + for document in documents: + if system and (not document.system or document.system.lower() != system.lower()): + continue + if kind and document.kind != kind: + continue + if status and (not document.status or document.status.lower() != status.lower()): + continue + if text and text.lower() not in document.text.lower(): + continue + result.append(document) + return sorted(result, key=spec_sort_key) + + +def markdown_escape(value: object) -> str: + return ( + str(value if value is not None else "") + .replace("\\", "\\\\") + .replace("|", "\\|") + .replace("\n", " ") + ) + + +def markdown_table(documents: list[Document], document_type: str) -> str: + if document_type == "decision": + headers = ("ID", "Title", "Status", "Area", "Date", "Path") + rows = [ + ( + document.id, + document.title, + document.status, + document.area, + document.date, + document.path, + ) + for document in documents + ] + else: + headers = ("System", "Kind", "Status", "Title", "Path") + rows = [ + ( + document.system, + document.kind, + document.status, + document.title, + document.path, + ) + for document in documents + ] + lines = [ + "| " + " | ".join(headers) + " |", + "| " + " | ".join("---" for _ in headers) + " |", + ] + lines.extend( + "| " + " | ".join(markdown_escape(value) for value in row) + " |" + for row in rows + ) + return "\n".join(lines) + "\n" + + +def json_output(documents: list[Document]) -> str: + items = [] + for document in documents: + item = { + "id": document.id, + "path": document.path, + "title": document.title, + "type": document.type, + } + if document.type == "decision": + item.update( + { + "area": document.area, + "date": document.date, + "status": document.status, + } + ) + else: + item.update( + { + "kind": document.kind, + "status": document.status, + "system": document.system, + } + ) + items.append(item) + return ( + json.dumps( + {"schema_version": SCHEMA_VERSION, "documents": items}, + ensure_ascii=False, + indent=2, + ) + + "\n" + ) + + +def format_documents( + documents: list[Document], output_format: str, document_type: str +) -> str: + if output_format == "paths": + return "".join(f"{document.path}\n" for document in documents) + if output_format == "json": + return json_output(documents) + return markdown_table(documents, document_type) + + +def add_common_arguments(parser: argparse.ArgumentParser) -> None: + parser.add_argument( + "--format", + choices=("markdown", "paths", "json"), + default="markdown", + help="output format", + ) + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="List and validate Kandev documentation sources." + ) + parser.add_argument( + "--root", + type=Path, + default=Path.cwd(), + help="repository root (defaults to the current directory)", + ) + subparsers = parser.add_subparsers(dest="command", required=True) + + decisions = subparsers.add_parser("decisions", help="list architecture decisions") + decisions.add_argument("--status") + decisions.add_argument("--area") + decisions.add_argument("--text") + add_common_arguments(decisions) + + specs = subparsers.add_parser("specs", help="list specifications") + specs.add_argument("--system") + specs.add_argument("--kind", choices=SPEC_KINDS) + specs.add_argument("--status") + specs.add_argument("--text") + add_common_arguments(specs) + + subparsers.add_parser("validate", help="validate both documentation catalogs") + return parser + + +def run(args: argparse.Namespace) -> int: + root = args.root.resolve() + if not root.is_dir(): + print(f"error: repository root does not exist: {root}", file=sys.stderr) + return 2 + + if args.command == "decisions": + documents, errors = load_documents(root, decision_files(root), parse_decision) + if errors: + for error in errors: + print(f"error: {error}", file=sys.stderr) + return 1 + selected = filter_decisions(documents, args.status, args.area, args.text) + print(format_documents(selected, args.format, "decision"), end="") + return 0 + + if args.command == "specs": + documents, errors = load_documents(root, spec_files(root), parse_spec) + if errors: + for error in errors: + print(f"error: {error}", file=sys.stderr) + return 1 + selected = filter_specs(documents, args.system, args.kind, args.status, args.text) + print(format_documents(selected, args.format, "specification"), end="") + return 0 + + decisions, decision_errors = load_documents(root, decision_files(root), parse_decision) + specs, spec_errors = load_documents(root, spec_files(root), parse_spec) + errors = sorted(decision_errors + spec_errors) + if errors: + for error in errors: + print(f"error: {error}", file=sys.stderr) + return 1 + print(f"Validated {len(decisions)} decisions and {len(specs)} specifications.") + return 0 + + +def main() -> int: + parser = build_parser() + try: + args = parser.parse_args() + return run(args) + except CatalogError as exc: + print(f"error: {exc}", file=sys.stderr) + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/list-docs.test.py b/scripts/list-docs.test.py new file mode 100644 index 0000000000..23f77ffb59 --- /dev/null +++ b/scripts/list-docs.test.py @@ -0,0 +1,420 @@ +#!/usr/bin/env python3 +import json +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +SCRIPT = ROOT / "scripts" / "list-docs.py" + + +class ListDocsTest(unittest.TestCase): + def setUp(self) -> None: + self.tmp = tempfile.TemporaryDirectory() + self.addCleanup(self.tmp.cleanup) + self.root = Path(self.tmp.name) + + def write(self, relative: str, content: str) -> Path: + path = self.root / relative + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") + return path + + def run_cli(self, *args: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [sys.executable, str(SCRIPT), "--root", str(self.root), *args], + cwd=ROOT, + text=True, + capture_output=True, + check=False, + ) + + def add_decisions(self) -> None: + self.write( + "docs/decisions/0010-pipe.md", + """# 0010: Pipe | choice + +**Status:** accepted (amended) +**Date:** 2026-01-02 (amended) +**Area:** backend, frontend + +## Context + +The searchable needle is here. +""", + ) + self.write( + "docs/decisions/0002-bullet.md", + """# 0002 — Bullet metadata + +- Status: Proposed +- Date: 2025-12-01 +- Area: workflow, infra + +## Context + +This decision uses bullet metadata. +""", + ) + self.write( + "docs/decisions/2026-01-03-frontmatter.md", + """--- +status: accepted +date: 2026-01-03 +area: protocol +--- + +# Frontmatter decision + +## Context + +This decision uses YAML metadata. +""", + ) + self.write( + "docs/decisions/0019-status-section.md", + """# 0019: Status section + +## Status + +accepted + +## Context + +Older decisions can omit date and area metadata. +""", + ) + self.write( + "docs/decisions/2026-01-04-table.md", + """# Table metadata + +| Metadata | Value | +| --- | --- | +| Date | 2026-01-04 | +| Status | superseded by another decision | +| Tags | backend, security | + +## Context + +This decision uses a metadata table. +""", + ) + self.write( + "docs/decisions/2026-01-05-wrapped-status.md", + """# Wrapped status metadata + +**Status:** accepted (amended by +2026-01-05) +**Date:** 2026-01-05 +**Area:** workflow + +## Context + +This decision wraps one metadata value. +""", + ) + self.write( + "docs/decisions/0028-status-punctuation.md", + """# 0028: Status punctuation + +**Status:** accepted; browser-cache portion superseded +**Date:** 2026-01-06 +**Area:** backend + +## Context + +This decision uses punctuation after the status class. +""", + ) + + def add_specs(self) -> None: + self.write( + "docs/specs/ui/README.md", + """--- +status: active +system: ui +specification_version: 1 +migration: complete +--- + +# UI system +""", + ) + self.write( + "docs/specs/ui/requirements/first.md", + """--- +id: ui-first +title: Frontmatter requirement title +status: `active` +system: `ui` +created: 2026-01-01 +--- + +# Heading requirement title + +The specification body contains the Searchable Spec Term. +""", + ) + self.write( + "docs/specs/ui/system-design/first.md", + """--- +id: ui-design +status: current +system: ui +requirements: [] +--- + +# UI system design +""", + ) + self.write( + "docs/specs/legacy/spec.md", + """# Legacy specification + +This file has no frontmatter and remains in the legacy layout. +""", + ) + self.write( + "docs/specs/product/overview.md", + """# Product overview + +This document describes the product boundary. +""", + ) + self.write( + "docs/specs/ui/glossary.md", + """# UI glossary + +This document defines UI terms. +""", + ) + + def test_decisions_support_variants_filters_and_stable_sorting(self) -> None: + self.add_decisions() + + result = self.run_cli("decisions", "--status", "accepted", "--format", "paths") + + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual( + result.stdout.splitlines(), + [ + "docs/decisions/0010-pipe.md", + "docs/decisions/0019-status-section.md", + "docs/decisions/0028-status-punctuation.md", + "docs/decisions/2026-01-03-frontmatter.md", + "docs/decisions/2026-01-05-wrapped-status.md", + ], + ) + + area_result = self.run_cli("decisions", "--area", "FRONTEND", "--format", "paths") + self.assertEqual(area_result.returncode, 0, area_result.stderr) + self.assertEqual(area_result.stdout.splitlines(), ["docs/decisions/0010-pipe.md"]) + + text_result = self.run_cli("decisions", "--text", "NEEDLE", "--format", "paths") + self.assertEqual(text_result.returncode, 0, text_result.stderr) + self.assertEqual(text_result.stdout.splitlines(), ["docs/decisions/0010-pipe.md"]) + + wrapped = self.run_cli("decisions", "--format", "json") + self.assertEqual(wrapped.returncode, 0, wrapped.stderr) + wrapped_document = next( + document + for document in json.loads(wrapped.stdout)["documents"] + if document["id"] == "2026-01-05-wrapped-status" + ) + self.assertEqual(wrapped_document["status"], "accepted (amended by 2026-01-05)") + + punctuation = self.run_cli( + "decisions", "--status", "accepted", "--format", "paths" + ) + self.assertEqual(punctuation.returncode, 0, punctuation.stderr) + self.assertIn( + "docs/decisions/0028-status-punctuation.md", punctuation.stdout.splitlines() + ) + + def test_decision_outputs_escape_markdown_and_preserve_metadata_in_json(self) -> None: + self.add_decisions() + + markdown = self.run_cli("decisions", "--format", "markdown") + self.assertEqual(markdown.returncode, 0, markdown.stderr) + self.assertIn("Pipe \\| choice", markdown.stdout) + self.assertIn("| 0010-pipe |", markdown.stdout) + + first = self.run_cli("decisions", "--format", "json") + second = self.run_cli("decisions", "--format", "json") + self.assertEqual(first.returncode, 0, first.stderr) + self.assertEqual(first.stdout, second.stdout) + payload = json.loads(first.stdout) + self.assertEqual(payload["schema_version"], 1) + self.assertEqual(payload["documents"][0]["id"], "0002-bullet") + self.assertEqual(payload["documents"][0]["status"], "Proposed") + self.assertEqual(payload["documents"][0]["area"], "workflow, infra") + + def test_specs_support_kinds_filters_json_and_empty_results(self) -> None: + self.add_specs() + + result = self.run_cli( + "specs", + "--system", + "ui", + "--kind", + "requirement", + "--status", + "active", + "--text", + "searchable spec term", + "--format", + "json", + ) + + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertEqual(len(payload["documents"]), 1) + document = payload["documents"][0] + self.assertEqual(document["kind"], "requirement") + self.assertEqual(document["system"], "ui") + self.assertEqual(document["title"], "Frontmatter requirement title") + self.assertEqual(document["id"], "ui-first") + + paths = self.run_cli("specs", "--kind", "legacy", "--format", "paths") + self.assertEqual(paths.returncode, 0, paths.stderr) + self.assertEqual(paths.stdout.splitlines(), ["docs/specs/legacy/spec.md"]) + + product_paths = self.run_cli("specs", "--kind", "product", "--format", "paths") + self.assertEqual(product_paths.returncode, 0, product_paths.stderr) + self.assertEqual(product_paths.stdout.splitlines(), ["docs/specs/product/overview.md"]) + + glossary_paths = self.run_cli("specs", "--kind", "glossary", "--format", "paths") + self.assertEqual(glossary_paths.returncode, 0, glossary_paths.stderr) + self.assertEqual(glossary_paths.stdout.splitlines(), ["docs/specs/ui/glossary.md"]) + + empty = self.run_cli("specs", "--system", "missing", "--format", "json") + self.assertEqual(empty.returncode, 0, empty.stderr) + self.assertEqual(json.loads(empty.stdout)["documents"], []) + + def test_spec_kind_filters_cover_each_linter_source_category(self) -> None: + self.add_specs() + expected = { + "system": "docs/specs/ui/README.md", + "glossary": "docs/specs/ui/glossary.md", + "requirement": "docs/specs/ui/requirements/first.md", + "system-design": "docs/specs/ui/system-design/first.md", + "product": "docs/specs/product/overview.md", + "legacy": "docs/specs/legacy/spec.md", + } + + for kind, path in expected.items(): + with self.subTest(kind=kind): + result = self.run_cli("specs", "--kind", kind, "--format", "paths") + + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout.splitlines(), [path]) + + def test_empty_markdown_keeps_the_catalog_type(self) -> None: + self.add_decisions() + result = self.run_cli("decisions", "--status", "missing", "--format", "markdown") + + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn("| ID | Title | Status | Area | Date | Path |", result.stdout) + + def test_specs_skip_entry_readmes_and_derive_titles_without_level_one_headings(self) -> None: + self.write("docs/specs/product/README.md", "# Product Specifications\n") + self.write( + "docs/specs/ui/README.md", + """--- +status: active +system: ui +specification_version: 1 +migration: complete +--- + +# UI system +""", + ) + self.write( + "docs/specs/ui/requirements/no-level-one.md", + """--- +status: active +system: ui +--- + +## Overview + +This requirement has no level-one heading. +""", + ) + + result = self.run_cli("specs", "--system", "ui", "--format", "json") + + self.assertEqual(result.returncode, 0, result.stderr) + documents = json.loads(result.stdout)["documents"] + requirement = next( + document + for document in documents + if document["path"].endswith("no-level-one.md") + ) + self.assertEqual(requirement["title"], "No Level One") + self.assertNotIn("docs/specs/product/README.md", result.stdout) + + def test_validate_rejects_malformed_metadata_and_duplicate_spec_ids(self) -> None: + self.write( + "docs/decisions/bad.md", + """# Bad decision + +**Date:** 2026-01-01 +**Area:** backend +""", + ) + self.write( + "docs/specs/ui/README.md", + """--- +status: active +system: ui +specification_version: 1 +migration: complete +--- + +# UI system +""", + ) + requirement = """--- +id: duplicate +status: active +system: ui +--- + +# Requirement +""" + self.write("docs/specs/ui/requirements/one.md", requirement) + self.write("docs/specs/ui/requirements/two.md", requirement) + + result = self.run_cli("validate") + + self.assertNotEqual(result.returncode, 0) + combined = result.stdout + result.stderr + self.assertIn("docs/decisions/bad.md", combined) + self.assertIn("docs/specs/ui/requirements/two.md", combined) + self.assertIn("duplicate", combined.lower()) + + def test_validate_rejects_system_readmes_without_valid_frontmatter(self) -> None: + for content in ("# UI system\n", "---\nstatus: active\n---\n# UI system\n"): + with self.subTest(content=content): + self.write("docs/specs/ui/README.md", content) + + result = self.run_cli("validate") + + self.assertNotEqual(result.returncode, 0) + combined = result.stdout + result.stderr + self.assertIn("docs/specs/ui/README.md", combined) + + def test_invalid_kind_is_an_actionable_cli_error(self) -> None: + result = self.run_cli("specs", "--kind", "unknown") + + self.assertNotEqual(result.returncode, 0) + self.assertIn("invalid choice", result.stderr) + + +if __name__ == "__main__": + unittest.main() diff --git a/scripts/spec_metadata.py b/scripts/spec_metadata.py new file mode 100644 index 0000000000..69f0c698ed --- /dev/null +++ b/scripts/spec_metadata.py @@ -0,0 +1,194 @@ +"""Shared specification path, frontmatter, and status metadata rules.""" + +from __future__ import annotations + +import re +from dataclasses import dataclass +from pathlib import Path + + +VALID_REQUIREMENT_STATUSES = {"draft", "active", "deprecated"} +VALID_DESIGN_STATUSES = {"draft", "current", "superseded"} +VALID_SYSTEM_STATUSES = {"draft", "active", "retired"} +VALID_MIGRATION_STATUSES = {"in_progress", "complete"} + + +@dataclass(frozen=True) +class FrontmatterResult: + """The parsed frontmatter and the source location of any parse error.""" + + metadata: dict[str, object] | None + end: int + line: int + error: str | None + + +@dataclass(frozen=True) +class MetadataIssue: + """A specification metadata contract violation.""" + + code: str + message: str + + +def metadata_text(metadata: dict[str, object], key: str) -> str | None: + """Return a scalar or list frontmatter value in catalog form.""" + value = metadata.get(key) + if isinstance(value, str): + return value.strip() + if isinstance(value, list) and value: + return ", ".join(str(item) for item in value) + return None + + +def validate_metadata( + kind: str, + system: str | None, + metadata: dict[str, object], + has_frontmatter: bool = True, +) -> list[MetadataIssue]: + """Validate the metadata contract shared by the catalog and spec linter.""" + contract_kind = "system-index" if kind == "system" else kind + if contract_kind not in {"requirement", "system-design", "system-index"}: + return [] + if not has_frontmatter: + return [ + MetadataIssue( + "frontmatter", "new specification document must start with YAML frontmatter" + ) + ] + + issues: list[MetadataIssue] = [] + if system is not None and metadata_text(metadata, "system") != system: + issues.append( + MetadataIssue( + "system-owner", + f"frontmatter system must be `{system}`, found `{metadata_text(metadata, 'system') or ''}`", + ) + ) + + status = metadata_text(metadata, "status") + if contract_kind == "requirement" and status not in VALID_REQUIREMENT_STATUSES: + issues.append( + MetadataIssue( + "requirement-status", + f"requirement status must be one of {sorted(VALID_REQUIREMENT_STATUSES)}, found `{status or ''}`", + ) + ) + elif contract_kind == "system-design" and status not in VALID_DESIGN_STATUSES: + issues.append( + MetadataIssue( + "system-design-status", + f"system-design status must be one of {sorted(VALID_DESIGN_STATUSES)}, found `{status or ''}`", + ) + ) + elif contract_kind == "system-index" and status not in VALID_SYSTEM_STATUSES: + issues.append( + MetadataIssue( + "system-index-status", + f"system status must be one of {sorted(VALID_SYSTEM_STATUSES)}", + ) + ) + + if contract_kind == "system-index": + if metadata_text(metadata, "specification_version") != "1": + issues.append( + MetadataIssue( + "system-index-version", "system index must set `specification_version: 1`" + ) + ) + migration = metadata_text(metadata, "migration") + if migration not in VALID_MIGRATION_STATUSES: + issues.append( + MetadataIssue( + "system-index-migration", + f"migration must be one of {sorted(VALID_MIGRATION_STATUSES)}", + ) + ) + elif contract_kind == "system-design" and not isinstance(metadata.get("requirements"), list): + issues.append( + MetadataIssue( + "system-design-requirements", + "system design must declare `requirements` as a YAML list, including an explicit empty list", + ) + ) + return issues + + +def parse_frontmatter(text: str, *, require: bool = False) -> FrontmatterResult: + """Parse the small YAML subset used by specification files.""" + lines = text.splitlines() + if not lines or lines[0] != "---": + if require: + return FrontmatterResult( + None, 0, 1, "new specification document must start with YAML frontmatter" + ) + return FrontmatterResult({}, 0, 1, None) + + try: + end = lines.index("---", 1) + except ValueError: + return FrontmatterResult(None, 0, 1, "YAML frontmatter has no closing delimiter") + + metadata: dict[str, object] = {} + current_list: str | None = None + for line_number, line in enumerate(lines[1:end], start=2): + if re.match(r"^\s+-\s+", line) and current_list: + value = re.sub(r"^\s+-\s+", "", line).strip().strip('"\'`') + current_value = metadata.setdefault(current_list, []) + if not isinstance(current_value, list): + return FrontmatterResult( + None, + end + 1, + line_number, + f"frontmatter field `{current_list}` mixes scalar and list values", + ) + current_value.append(value) + continue + + match = re.match(r"^(?P<key>[a-z][a-z0-9_-]*):(?:\s*(?P<value>.*))?$", line) + if not match: + if not line.strip(): + continue + return FrontmatterResult( + None, end + 1, line_number, "frontmatter contains unsupported YAML" + ) + + key = match.group("key") + value = (match.group("value") or "").strip() + if value == "[]": + metadata[key] = [] + current_list = None + elif value: + metadata[key] = value.strip('"\'`') + current_list = None + else: + metadata[key] = [] + current_list = key + + return FrontmatterResult(metadata, end + 1, 1, None) + + +def classify_path(relative: Path) -> tuple[str, str | None]: + """Classify a specification path using the authoritative linter layout.""" + parts = relative.parts + try: + spec_index = parts.index("specs") + except ValueError: + return "unknown", None + inside = parts[spec_index + 1 :] + if not inside: + return "unknown", None + if inside[0] == "guide": + return "guide", None + if inside[0] == "templates": + return "template", None + if inside[0] == "product": + return "product", None + if len(inside) >= 3 and inside[1] == "requirements": + return "requirement", inside[0] + if len(inside) >= 3 and inside[1] == "system-design": + return "system-design", inside[0] + if len(inside) == 2 and inside[1] in {"README.md", "glossary.md"}: + return "system-index", inside[0] + return "legacy", None