From 34e156a160145e3cd7632e9d82c7ba1ba59ccc14 Mon Sep 17 00:00:00 2001 From: "Wesley O. Nichols" Date: Thu, 28 May 2026 15:04:27 +0200 Subject: [PATCH] feat(spec-anchored-development): switch back-link identifier from slug to repo-relative path The spec frontmatter `spec:` field and every code-side `// Spec:` back-link now use the spec file's repo-relative path (e.g. `docs/specs/agent/executor.md`) instead of a decoupled slug id. The path doubles as a navigable link target in IDE plugins and Markdown renderers, at the cost of making spec renames a graph-wide rewrite. Touches SKILL.md (frontmatter, back-link format, gate checklist, anti-pattern table) plus the matching paragraphs in references/existing-codebase.md and references/maintenance.md. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../skills/spec-anchored-development/SKILL.md | 42 +++++++++---------- .../references/existing-codebase.md | 4 +- .../references/maintenance.md | 6 +-- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/plugins/spec-anchored-development/skills/spec-anchored-development/SKILL.md b/plugins/spec-anchored-development/skills/spec-anchored-development/SKILL.md index d92f671..2ce611b 100644 --- a/plugins/spec-anchored-development/skills/spec-anchored-development/SKILL.md +++ b/plugins/spec-anchored-development/skills/spec-anchored-development/SKILL.md @@ -75,31 +75,31 @@ If a topic spans multiple packages or introduces new entities, it's system-level ## Spec frontmatter -Every spec begins with YAML frontmatter. The schema is locked so tooling and back-links can resolve specs by stable id rather than filename. +Every spec begins with YAML frontmatter. The `spec:` value is the spec file's repo-relative path so back-links and the index resolve via that path — the same string is also the navigable link target. ```yaml --- -spec: agent-executor # stable id, used by back-links and the index +spec: docs/specs/agent/executor.md # repo-relative path; used by back-links and the index title: Agent Executor -status: current # see status enum below +status: current # see status enum below version: 1.2 last_updated: 2026-04-14 -level: system # application | system | cross-cutting | feature | plan -owners: # primary code paths this spec governs +level: system # application | system | cross-cutting | feature | plan +owners: # primary code paths this spec governs - server/src/agent/executor.ts - server/src/agent/usage.ts -adjacent: # related specs, by id - - agent-tools - - lifecycle-hooks - - scheduler -tests: # primary verification anchors +adjacent: # related specs, by repo-relative path + - docs/specs/agent/tools.md + - docs/specs/agent/lifecycle-hooks.md + - docs/specs/agent/scheduler.md +tests: # primary verification anchors - server/src/agent/executor.test.ts --- ``` Rules: -- `spec` is the stable id. Back-links and the spec index resolve by id, not filename, so spec files can be renamed without breaking the graph. +- `spec` is the spec's repo-relative path. The same path is the back-link target in code and the link target in Markdown renderers. Renaming a spec file is therefore a graph-wide change — update `spec:`, all `adjacent:` entries elsewhere, and every code-side `// Spec:` backlink together (the maintenance audit will surface stragglers). - `owners` lists *primary* implementing files. Most files appear under exactly one spec's `owners`. **Seam files** — plugin bootstrap, route registration, shared event normalization, schemas spanning multiple domains — may legitimately appear under several specs' `owners` lists. When they do, every owning spec must list the file, and the file's `// Spec:` comments must use the multi-link form with scope qualifiers so it is unambiguous which sections (or which symbols) belong to which spec. - `adjacent` declares known coupling. Used to rank impact when one spec changes. - `last_updated` must be bumped on any substantive change. The maintenance audit flags specs whose `last_updated` falls behind the most recent commit on any `owners` file. @@ -149,31 +149,31 @@ The format is deliberate: name a *concrete* change, list the *concrete* files an ## Code-to-spec back-link format -Every owning code file references its governing spec via a `Spec:` comment using the spec id, optional section anchor, and optional scope/intent note. +Every owning code file references its governing spec via a `Spec:` comment whose value is the spec's repo-relative path, with an optional section anchor and optional scope/intent note. The path doubles as a navigable link target (IDE plugins, Markdown renderers, `$EDITOR $(grep -oE '^.+\.md' …)`). -**Format:** `// Spec: [#section] [— description]` +**Format:** `// Spec: [#section] [— description]` -The `` is the `spec:` field from the target spec's frontmatter, **not** a filename. This survives spec renames. +The `` is the spec file's path from the repo root (the same string as the spec's `spec:` frontmatter value). **Simple** — file implements the full spec: ``` -// Spec: agent-executor +// Spec: docs/specs/agent/executor.md ``` **Scoped** — file implements only part. **Section anchor is mandatory** when scope is partial: ``` -// Spec: agent-executor#5-model-resolution — Provider/model resolution and custom model lookup +// Spec: docs/specs/agent/executor.md#5-model-resolution — Provider/model resolution and custom model lookup ``` **Intent** — captures a constraint not obvious from the code: ``` -// Spec: agent-executor#6-subagent-spawning — Depth-limited to 3; do not raise without revising the spec +// Spec: docs/specs/agent/executor.md#6-subagent-spawning — Depth-limited to 3; do not raise without revising the spec ``` **Multiple specs (seam files only)** — file truly sits between systems. Each line carries a scope qualifier so it is unambiguous which lines or symbols belong to which spec: ``` -// Spec: agent-executor#3-execution-flow — Run loop and bounds enforcement -// Spec: scheduler#4-trigger-resume — Cron resume path only (function: resumeFromCron) +// Spec: docs/specs/agent/executor.md#3-execution-flow — Run loop and bounds enforcement +// Spec: docs/specs/agent/scheduler.md#4-trigger-resume — Cron resume path only (function: resumeFromCron) ``` Use multi-link sparingly. Most files belong to exactly one spec. @@ -299,7 +299,7 @@ Run before finalizing any spec: - [ ] Edit-impact section names concrete files and sections (not "related docs") - [ ] Code map links every spec section to implementing files, with symbols where helpful - [ ] Test map links every section to primary tests -- [ ] Owning files have `// Spec:` comments using the spec id (code → spec) +- [ ] Owning files have `// Spec:` comments using the spec's repo-relative path (code → spec) - [ ] Section anchors used in back-links whenever scope is partial - [ ] Multi-link only on true seam files, with scope qualifiers - [ ] Known deltas populated if status is `drifted`; empty otherwise @@ -331,7 +331,7 @@ If any gate fails, fix it or surface it explicitly. Do not silently ship a half- | Generic edit-impact | "Be careful when editing this" | Name the concrete files and sections to inspect | | Back-link spam | Every utility file has back-links, often to multiple specs | Restrict to core/route/stateful/schema/UI-state files; prefer single-link | | Pseudocode entities | A spec with implementing code defines a stylized type that does not match source | For specs with code on disk, paste the real type. For `draft` specs the canonical declaration is allowed; replace it with the pasted form once code lands | -| Filename back-links | `// Spec: specs/agent-executor.md` | Use the spec id: `// Spec: agent-executor` | +| Slug-style back-links | `// Spec: agent-executor` | Use the spec's repo-relative path: `// Spec: docs/specs/agent/executor.md` | | Why-as-summary | Why section restates what the code does | Replace with the constraint, incident, or product reason that motivated the system | ## Guardrails diff --git a/plugins/spec-anchored-development/skills/spec-anchored-development/references/existing-codebase.md b/plugins/spec-anchored-development/skills/spec-anchored-development/references/existing-codebase.md index 71a41a6..dbd53a2 100644 --- a/plugins/spec-anchored-development/skills/spec-anchored-development/references/existing-codebase.md +++ b/plugins/spec-anchored-development/skills/spec-anchored-development/references/existing-codebase.md @@ -25,7 +25,7 @@ Map and record: Group related code into logical systems by domain, not by directory. Each system with its own data model, API surface, or lifecycle is a candidate for a spec. Reserve cross-cutting specs for the concerns surfaced in step 1; do not invent them. -Present the proposed breakdown to the developer for validation. Include the proposed spec id for each system (the value that will go into `spec:` frontmatter) since back-links will use that id, not the filename. +Present the proposed breakdown to the developer for validation. Include the proposed spec file path for each system (the value that will go into `spec:` frontmatter and into every code-side `// Spec:` back-link). ### 3. For each system: extract then interview @@ -113,7 +113,7 @@ This step is not optional. Both directions must be created in the same pass. Add the Code map and Test map sections. Link spec sections to implementing files. Use symbol names (`AgentExecutor.run`) for stable anchors; line numbers may augment but should not stand alone. **Code → spec (`Spec:` comments in code files):** -Add a `Spec:` comment to every owning file using the **spec id** from the target spec's frontmatter (not the filename). Section anchors are mandatory when scope is partial. Multi-link only on true seam files identified during the survey, with scope qualifiers on each line. See SKILL.md for the locked format. +Add a `Spec:` comment to every owning file using the spec's **repo-relative path** (the value of `spec:` in the target's frontmatter). Section anchors are mandatory when scope is partial. Multi-link only on true seam files identified during the survey, with scope qualifiers on each line. See SKILL.md for the locked format. ### 6. Build the spec index and conventions file diff --git a/plugins/spec-anchored-development/skills/spec-anchored-development/references/maintenance.md b/plugins/spec-anchored-development/skills/spec-anchored-development/references/maintenance.md index ac0216f..03e97ce 100644 --- a/plugins/spec-anchored-development/skills/spec-anchored-development/references/maintenance.md +++ b/plugins/spec-anchored-development/skills/spec-anchored-development/references/maintenance.md @@ -94,9 +94,9 @@ Report findings before making changes. Let the developer decide whether spec or **Back-link convention:** ``` -// Spec: [#section] [— description] +// Spec: [#section] [— description] ``` -Use the spec **id** from frontmatter, not the filename. See SKILL.md for the full format and rules on multi-link seam files. +Use the spec's repo-relative path (the same string as the `spec:` field in frontmatter). The path is both the identifier and the navigable link target. See SKILL.md for the full format and rules on multi-link seam files. ### 4. Prune @@ -141,6 +141,6 @@ When drift is ambiguous, ask: After any maintenance operation, run the gates from SKILL.md. Specifically: - All touched specs have valid frontmatter and a status from the enum -- Every owning file has a back-link using the spec id +- Every owning file has a back-link using the spec's repo-relative path - `SPEC_INDEX.md` is regenerated if frontmatter changed - The drift report is included in the run summary, even if all checks passed (so the user knows what was checked)