dld-kit 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: dld-audit
3
+ description: Scan for drift between decisions and code. Finds orphaned annotations, stale references, and undocumented changes.
4
+ compatibility: Requires Node.js 20+ and git.
5
+ ---
6
+
7
+ # /dld-audit — Audit Decision-Code Drift
8
+
9
+ You are scanning the codebase for drift between decision records and code annotations. This helps catch situations where code evolved but decisions weren't updated.
10
+
11
+ ## Commands
12
+
13
+ {{dld-setup}}
14
+
15
+ This skill uses: `find-annotations`, `find-missing-amends`, `update-audit-state`.
16
+
17
+ ## Prerequisites
18
+
19
+ Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
20
+
21
+ ## Audit Steps
22
+
23
+ ### 1. Collect all annotations in code
24
+
25
+ Run `find-annotations`:
26
+ ```bash
27
+ {{dld}} find-annotations
28
+ ```
29
+
30
+ This outputs lines in the format `<file>:<line>:<DL-NNN>`, one per annotation occurrence.
31
+
32
+ ### 2. Collect all decision records
33
+
34
+ Read all `DL-*.md` files in the records subdirectory (`decisions/records/`). For each, note:
35
+ - The ID
36
+ - The status
37
+ - The code references listed in the frontmatter
38
+
39
+ ### 3. Check for issues
40
+
41
+ Perform these drift checks:
42
+
43
+ #### a) Orphaned annotations
44
+
45
+ Annotations in code that reference non-existent decision IDs. These indicate decisions that were deleted or IDs that were mistyped.
46
+
47
+ #### b) Annotations referencing non-accepted decisions
48
+
49
+ Annotations referencing decisions with status `deprecated` or `superseded`. Code is still tied to a decision that's no longer active.
50
+
51
+ #### b2) Annotations referencing amended decisions
52
+
53
+ Annotations referencing decisions that have been amended by a newer decision (check all decisions for `amends` fields that reference this ID). This is **informational, not an error** — the original decision is still active, but the developer should be aware of the amendment. Surface these as notes, not issues.
54
+
55
+ #### c) Stale references in decisions
56
+
57
+ Decision records whose `references` list code paths that no longer exist in the repository. Use file existence checks.
58
+
59
+ #### d) Unreferenced code changes (if previous audit exists)
60
+
61
+ If `decisions/.dld-state.yaml` exists and has an `audit.commit_hash`, find files that:
62
+ 1. Contain `@decision` annotations
63
+ 2. Were modified since the last audit commit
64
+
65
+ First, verify the commit is reachable:
66
+ ```bash
67
+ git cat-file -t <commit_hash> 2>/dev/null
68
+ ```
69
+
70
+ If the commit is unreachable (e.g., after a rebase or shallow clone), skip this check and note it in the report:
71
+ > **Note:** Previous audit commit `<hash>` is not reachable in current history. Skipping changed-file detection. This can happen after a rebase or shallow clone.
72
+
73
+ If the commit is reachable:
74
+ ```bash
75
+ git diff --name-only <commit_hash>..HEAD
76
+ ```
77
+
78
+ Cross-reference this list with annotated files. Files that changed but whose associated decisions weren't updated may indicate undocumented drift.
79
+
80
+ #### e) Missing amendment relationships
81
+
82
+ **This check is mandatory — do not skip it.** Run `find-missing-amends` to get initial candidates:
83
+
84
+ ```bash
85
+ {{dld}} find-missing-amends
86
+ ```
87
+
88
+ This outputs lines in the format `<source-id>:<referenced-id>` — decisions whose body references another decision ID that isn't listed in their `supersedes` or `amends` fields. Not every candidate is a missing amendment — some are just informational references (e.g., "this is similar to DL-005").
89
+
90
+ By default the command only emits candidates whose source decision file changed since the last audit (recorded in `.dld-state.yaml`), so references the agent has already evaluated and judged informational don't keep resurfacing. To force a full rescan — useful for cold starts or manual deep audits — pass `--all`:
91
+
92
+ ```bash
93
+ {{dld}} find-missing-amends --all
94
+ ```
95
+
96
+ For each candidate, read the source decision's body and evaluate whether the reference describes a partial modification of the referenced decision. Look for language like: "supersedes the X portions of", "changes the Y behavior from DL-Z", "replaces the approach in DL-Z for...", "modifies how DL-Z handles...". If so, flag it as a missing amendment.
97
+
98
+ #### f) Decisions without annotations
99
+
100
+ `accepted` decisions that have code references in their frontmatter but no corresponding `@decision` annotations found in the code. The references claim code is linked, but the annotations are missing.
101
+
102
+ ### 4. Report findings
103
+
104
+ Present findings grouped by severity:
105
+
106
+ ```
107
+ ## Audit Report
108
+
109
+ ### Issues Found
110
+
111
+ #### Orphaned Annotations
112
+ - `src/billing/vat.ts:42` references `DL-099` — decision does not exist
113
+
114
+ #### Stale References
115
+ - **DL-012** references `src/billing/old-vat.ts` — file does not exist
116
+
117
+ #### Deprecated/Superseded References
118
+ - `src/auth/login.ts:15` references `DL-003` (status: superseded by DL-012)
119
+
120
+ #### Amended Decisions (informational)
121
+ - `src/billing/vat.ts:42` references `DL-003` — amended by DL-012. Verify code aligns with the amendment.
122
+
123
+ #### Modified Annotated Files (since last audit)
124
+ - `src/billing/vat.ts` — modified, contains `@decision(DL-012)`. Review if decision needs updating.
125
+
126
+ ### Summary
127
+ - **X** orphaned annotations
128
+ - **Y** stale references
129
+ - **Z** annotated files modified since last audit
130
+
131
+ ### Suggested Remediation
132
+ - Fix orphaned annotation at `src/billing/vat.ts:42` — update to correct ID or remove
133
+ - Update DL-012 references — remove `src/billing/old-vat.ts`
134
+ - Review `src/billing/vat.ts` changes — consider `/dld-decide` if behavior changed
135
+ ```
136
+
137
+ If no issues are found:
138
+ ```
139
+ ## Audit Report
140
+
141
+ No drift detected. All annotations reference valid, accepted decisions. All decision references point to existing code.
142
+ ```
143
+
144
+ ### 5. Update audit state
145
+
146
+ After the audit completes (regardless of findings):
147
+ ```bash
148
+ {{dld}} update-audit-state
149
+ ```
150
+
151
+ ### 6. Suggest next steps
152
+
153
+ > Audit complete. **N** issue(s) found.
154
+ >
155
+ > Next steps:
156
+ > - Fix any orphaned or stale references identified above
157
+ > - `/dld-decide` — record new decisions for undocumented changes
158
+ > - `/dld-snapshot` — regenerate the spec projection
159
+ > - `/dld-status` — view overall decision log state
@@ -0,0 +1,169 @@
1
+ ---
2
+ name: dld-audit-auto
3
+ description: Autonomous audit — detects drift, fixes issues, and opens a PR. Designed for scheduled/CI execution without human interaction.
4
+ compatibility: Requires Node.js 20+ and git.
5
+ ---
6
+
7
+ # /dld-audit-auto — Autonomous Audit & Fix
8
+
9
+ You are running an autonomous audit of the decision-code relationship. Unlike the interactive `/dld-audit`, you **detect issues and fix them** without asking for human input. Your output is a branch with fixes and a PR for review.
10
+
11
+ **This skill is designed for unattended execution** — scheduled runs, CI pipelines, or autonomous agent sessions. Do not ask questions or wait for user input.
12
+
13
+ ## Commands
14
+
15
+ {{dld-setup}}
16
+
17
+ This skill uses: `find-annotations`, `find-missing-amends`, `regenerate-index`, `update-audit-state`.
18
+
19
+ ## Prerequisites
20
+
21
+ 1. Check that `dld.config.yaml` exists at the repo root. If not, exit with a clear error message.
22
+ 2. Verify the working tree is clean (`git status --porcelain` should be empty). If not, exit — do not mix audit fixes with uncommitted work.
23
+
24
+ ## Step 1: Create audit branch
25
+
26
+ ```bash
27
+ git checkout -b dld/audit-$(date +%Y%m%d-%H%M%S)
28
+ ```
29
+
30
+ ## Step 2: Run the full audit
31
+
32
+ Perform all the same checks as `/dld-audit`:
33
+
34
+ ### a) Collect annotations and decision records
35
+
36
+ ```bash
37
+ {{dld}} find-annotations
38
+ ```
39
+
40
+ Read all `DL-*.md` files in the records subdirectory (`decisions/records/`). Note each decision's ID, status, and code references.
41
+
42
+ ### b) Detect issues
43
+
44
+ Check for all drift categories:
45
+
46
+ 1. **Orphaned annotations** — annotations referencing non-existent decision IDs
47
+ 2. **Annotations referencing non-accepted decisions** — code tied to deprecated or superseded decisions
48
+ 3. **Stale references in decisions** — frontmatter references to files that no longer exist
49
+ 4. **Unreferenced code changes** — annotated files modified since last audit (if previous audit state exists)
50
+ 5. **Decisions without annotations** — accepted decisions with code references but no corresponding annotations in code
51
+ 6. **Missing amendment relationships** — decisions whose body references modifying part of a previous decision but have an empty `amends` field
52
+
53
+ For check (4), if `decisions/.dld-state.yaml` exists with an `audit.commit_hash`, first verify reachability:
54
+ ```bash
55
+ git cat-file -t <commit_hash> 2>/dev/null
56
+ ```
57
+ If unreachable (e.g., after rebase or shallow clone), skip check (4) and note it in the PR description. If reachable, use `git diff --name-only <commit_hash>..HEAD` to find changed files and cross-reference with annotated files.
58
+
59
+ ## Step 3: Fix issues
60
+
61
+ Apply fixes for each issue category. Use judgment on what can be safely fixed automatically vs. what should only be flagged in the PR description.
62
+
63
+ ### Hard rule: never edit the body of an accepted decision
64
+
65
+ The narrative body of an accepted decision (Context, Decision, Rationale, Consequences, and any other prose sections) is **immutable**. An audit must never rewrite, refine, "clean up", or otherwise modify it.
66
+
67
+ The only changes an audit may make to an accepted decision are housekeeping updates to specific frontmatter fields — `references`, `amends`, `superseded_by`, and similar relational metadata — plus adding or fixing `@decision` annotations in code.
68
+
69
+ If drift suggests the substance of an accepted decision is no longer accurate, or that code has evolved beyond what the decision describes, **do not modify the original record**. Instead, create a **new decision** (status `accepted`, since the code already exists) that captures the new rationale and uses `supersedes` or `amends` to link back to the prior one. The original stays as-is to preserve the historical record of why things were done that way at the time.
70
+
71
+ ### Auto-fixable (apply these directly):
72
+
73
+ **Orphaned annotations** — If the annotation has an obvious typo (e.g., `DL-01` where `DL-001` exists), fix it. If the referenced ID is completely unknown, remove the annotation and note the removal in the commit message.
74
+
75
+ **Stale references in decisions** — Remove file paths from the decision's `references` field that no longer exist. If the file was renamed/moved (detectable via `git log --follow --diff-filter=R`), update the path instead of removing.
76
+
77
+ **Annotations referencing superseded decisions** — Update the annotation to reference the superseding decision (read the `supersedes` field of the newer decision to find the chain). For deprecated decisions, remove the annotation.
78
+
79
+ **Annotations referencing amended decisions** — Do **not** rewrite or remove these annotations. The original decision is still active. Instead, note the amendment relationship in the PR description so reviewers can verify the code aligns with the amendment.
80
+
81
+ **Missing amendment relationships** — Run `{{dld}} find-missing-amends` to get candidates. The command only emits candidates whose source decision changed since the last audit, so re-runs stay focused on new work. For each candidate, read the source decision's body and determine if it describes a partial modification. If so, add the referenced ID to the `amends` field. Flag prominently in the PR for review, since this is an inferred relationship.
82
+
83
+ **Decisions without annotations** — If an accepted decision has code references but no annotations, and the referenced files exist, add the missing `@decision(DL-NNN)` annotations to the referenced code locations.
84
+
85
+ ### Best-effort fixes (apply, but flag prominently for review):
86
+
87
+ **Unreferenced code changes** — Annotated files that were modified since the last audit without a corresponding decision update. These represent changes made outside the DLD process. Try to resolve them:
88
+
89
+ 1. **Check commit messages** — Read the commits that modified the file (`git log --oneline <last_audit_hash>..HEAD -- <file>`). Look for context about what changed and why.
90
+ 2. **Look up referenced tickets** — If commit messages reference a ticket (e.g., Jira, Linear, GitHub issue), try to look it up using available tools (MCP servers, `gh` CLI, etc.) to gather additional context about the change.
91
+ 3. **Assess the impact** — Read the current code and the associated decision(s). Determine whether:
92
+ - The existing decision is still accurate (the change was compatible — no action needed)
93
+ - The change introduced new or different behavior/rationale that is not fully captured by the existing decision (a **new decision** is needed)
94
+ 4. **Create a new decision when needed** — Per the hard rule above, never edit the body of the existing accepted decision to absorb the new behavior. Instead, create a new decision using the standard scripts, mark it `accepted` (the code already exists), and link it to the prior decision via `supersedes` or `amends` as appropriate. Add `@decision` annotations to the new/changed code pointing at the new decision.
95
+
96
+ **Important:** These best-effort fixes are inferred, not authoritative. In the PR description, clearly mark each one under a **"Inferred Decisions — Review Required"** section. Explain what changed, what context was found (commit messages, tickets), and what new decision was created. Reviewers should prioritize checking these for accuracy.
97
+
98
+ ## Step 4: Regenerate INDEX.md
99
+
100
+ If any decision records were modified:
101
+ ```bash
102
+ {{dld}} regenerate-index
103
+ ```
104
+
105
+ ## Step 5: Update audit state
106
+
107
+ ```bash
108
+ {{dld}} update-audit-state
109
+ ```
110
+
111
+ ## Step 6: Commit, push, and open PR
112
+
113
+ If there are changes (fixes were applied or audit state was updated):
114
+
115
+ ```bash
116
+ git add -A
117
+ ```
118
+
119
+ Commit with a descriptive message summarizing the fixes:
120
+
121
+ ```bash
122
+ git commit -m "fix: resolve DLD audit drift
123
+
124
+ - [list each fix applied]
125
+ - Audit state updated"
126
+ ```
127
+
128
+ Push and open a PR:
129
+
130
+ ```bash
131
+ git push -u origin HEAD
132
+ ```
133
+
134
+ Create a PR with the following structure:
135
+
136
+ ```markdown
137
+ ## DLD Audit — Automated Drift Fixes
138
+
139
+ **Audit date:** YYYY-MM-DD
140
+ **Issues found:** N
141
+ **Auto-fixed:** M
142
+ **Needs review:** K
143
+
144
+ ### Fixes Applied
145
+
146
+ - [Description of each fix, grouped by category]
147
+
148
+ ### Inferred Decisions — Review Required
149
+
150
+ These decisions were created or updated based on code changes made outside the DLD process. The rationale was inferred from commit messages and available ticket context. **Please verify accuracy.**
151
+
152
+ - **DL-NNN: [Title]** (new/updated) — [What changed in the code, what context was found, what was inferred]
153
+
154
+ ### Audit Summary
155
+
156
+ | Check | Result |
157
+ |-------|--------|
158
+ | Orphaned annotations | N found, M fixed |
159
+ | Stale references | N found, M fixed |
160
+ | Superseded/deprecated refs | N found, M fixed |
161
+ | Missing annotations | N found, M added |
162
+ | Modified annotated files | N flagged for review |
163
+ ```
164
+
165
+ If no issues were found (only audit state updated), still commit and push the state update but **do not open a PR**. Instead, exit with a message:
166
+
167
+ ```
168
+ Audit complete. No drift detected. Audit state updated.
169
+ ```
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: dld-common
3
+ description: The dld CLI shared by the DLD skills. Not intended for direct invocation — the other DLD skills run it.
4
+ internal: true
5
+ compatibility: Requires Node.js 20+ and git.
6
+ ---
7
+
8
+ # DLD Common
9
+
10
+ This skill ships `scripts/dld.mjs`, the bundled `dld` command-line tool the other DLD skills run for mechanical operations: assigning IDs, creating records, updating status, regenerating the index, scanning annotations, and reindexing. Do not invoke this skill directly.
11
+
12
+ `{{dld}} --help` lists the commands, where `<skill-dir>` is the absolute path of this skill's directory.
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: dld-decide
3
+ description: Record a single development decision as a markdown file with YAML frontmatter. Collects context, rationale, and code references interactively.
4
+ compatibility: Requires Node.js 20+ and git.
5
+ ---
6
+
7
+ # /dld-decide — Record a Decision
8
+
9
+ You are helping the developer record a development decision. This should be a focused, low-ceremony conversation — not an interrogation.
10
+
11
+ ## Interaction style
12
+
13
+ Use the `AskUserQuestion` tool for all questions and prompts. This provides a structured input experience for the user rather than waiting for freeform replies.
14
+
15
+ ## Commands
16
+
17
+ {{dld-setup}}
18
+
19
+ This skill uses: `next-id`, `create-decision`, `update-status`, `regenerate-index`.
20
+
21
+ ## Prerequisites
22
+
23
+ Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
24
+
25
+ ## Read project context
26
+
27
+ 1. Read `dld.config.yaml` to understand the project structure (flat vs namespaced, decisions directory, namespaces list)
28
+ 2. Read `decisions/PRACTICES.md` if it exists — be aware of project conventions when helping structure the decision
29
+ 3. For namespaced projects, also read `decisions/records/<namespace>/PRACTICES.md` if it exists for the relevant namespace
30
+
31
+ ## Conversation flow
32
+
33
+ ### 1. Collect the decision
34
+
35
+ If the user provided context with the skill invocation, use it. Otherwise ask:
36
+
37
+ > What decision are you recording? Tell me what you decided, why, and what code it affects.
38
+
39
+ Listen for:
40
+ - **What** was decided (the decision itself)
41
+ - **Why** (the rationale — what problem it solves, what alternatives were considered)
42
+ - **What it affects** (code areas, components, modules)
43
+
44
+ ### 2. Ask clarifying questions (if needed)
45
+
46
+ Only ask follow-up questions if the rationale or scope is genuinely unclear. Maximum 3-5 questions total. Don't interrogate — if the developer gave enough context, move on.
47
+
48
+ Good reasons to ask:
49
+ - The rationale is missing or unclear
50
+ - There might be alternatives worth noting
51
+ - The scope of affected code isn't clear
52
+ - There are obvious consequences worth recording
53
+
54
+ ### 3. Check for related decisions
55
+
56
+ Scan existing decision files for potential relationships:
57
+ - Decisions that reference the same code paths
58
+ - Decisions with overlapping tags
59
+ - Decisions that this one might supersede or amend
60
+
61
+ If you find related decisions, mention them and ask whether this decision **supersedes** (fully replaces) or **amends** (partially modifies) any of them. A superseded decision gets marked as `superseded` and is no longer active. An amended decision stays `accepted` — the amendment changes part of its scope while the rest remains in effect.
62
+
63
+ ### 4. Determine namespace (namespaced projects only)
64
+
65
+ If the project is namespaced, determine which namespace this decision belongs to. Infer from the code references if possible, otherwise ask.
66
+
67
+ ### 5. Assign ID
68
+
69
+ Run `next-id`:
70
+ ```bash
71
+ {{dld}} next-id
72
+ ```
73
+
74
+ This outputs the next available ID (e.g., `DL-004`).
75
+
76
+ ### 6. Create the decision record
77
+
78
+ Compose the markdown body with the relevant sections (Context, Decision, Rationale, Consequences). Omit sections that aren't relevant, but always include Context and Decision.
79
+
80
+ Then run `create-decision`, piping the body via `printf` with `\n` for newlines (do **not** use literal newlines in the body argument — use `\n` escape sequences so the entire command stays on one logical line):
81
+ ```bash
82
+ printf "## Context\n\nWhat prompted this decision.\n\n## Decision\n\nWhat was decided.\n\n## Rationale\n\nWhy this choice.\n\n## Consequences\n\nWhat becomes easier or harder." | {{dld}} create-decision \
83
+ --id "DL-NNN" \
84
+ --title "Short descriptive title" \
85
+ --namespace "billing" \
86
+ --tags "tag1, tag2" \
87
+ --supersedes "DL-003, DL-007" \
88
+ --amends "DL-005" \
89
+ --body-stdin
90
+ ```
91
+
92
+ Flags `--namespace`, `--tags`, `--supersedes`, `--amends` are optional. The command creates the file with YAML frontmatter and the body content, and outputs the file path.
93
+
94
+ > **Note:** If the body contains literal `%` characters, escape them as `%%` (printf format string requirement).
95
+
96
+ If this decision supersedes others, also update their status:
97
+ ```bash
98
+ {{dld}} update-status DL-003 superseded
99
+ ```
100
+
101
+ **Do not** update the status of amended decisions — they stay `accepted`.
102
+
103
+ ### 7. Regenerate INDEX.md
104
+
105
+ ```bash
106
+ {{dld}} regenerate-index
107
+ ```
108
+
109
+ ### 8. Suggest next steps
110
+
111
+ > Decision **DL-NNN** recorded as `proposed`.
112
+ >
113
+ > Next steps:
114
+ > - `/dld-adjust` — refine the decision before implementing
115
+ > - `/dld-implement DL-NNN` — implement this decision
116
+ > - `/dld-decide` — record another decision
@@ -0,0 +1,213 @@
1
+ ---
2
+ name: dld-implement
3
+ description: Implement one or more proposed decisions. Makes code changes, adds `@decision` annotations, and updates decision status.
4
+ compatibility: Requires Node.js 20+ and git.
5
+ ---
6
+
7
+ # /dld-implement — Implement Decisions
8
+
9
+ You are implementing one or more `proposed` decisions by making code changes, adding `@decision` annotations, and updating the decision records.
10
+
11
+ ## Commands
12
+
13
+ {{dld-setup}}
14
+
15
+ This skill uses: `update-status`, `verify-annotations`, `regenerate-index`.
16
+
17
+ ## Prerequisites
18
+
19
+ 1. Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
20
+ 2. Parse the user's input to identify which decision(s) to implement:
21
+ - Specific IDs: `DL-005`, `DL-005 DL-006`
22
+ - By tag: `tag:payment-gateway`
23
+ - **No arguments:** If the user runs `/dld-implement` without specifying decisions, find all decisions with `status: proposed` in the records subdirectory (`decisions/records/`) and implement all of them.
24
+ 3. Read each referenced decision file. Verify they exist and have `status: proposed`. If a decision is already `accepted`, tell the user and skip it. If it doesn't exist, report the error.
25
+
26
+ ## Read project context
27
+
28
+ 1. Read `dld.config.yaml` for project structure
29
+ 2. Read `decisions/PRACTICES.md` if it exists — **this is where practices guidance is most important**. Apply the project's testing approach, code style, error handling patterns, and architecture conventions when writing code.
30
+ 3. For namespaced projects, also read `decisions/records/<namespace>/PRACTICES.md` for namespace-specific practices
31
+
32
+ ## Implementation
33
+
34
+ ### Batch vs. single implementation
35
+
36
+ When multiple decisions are requested, decide whether to implement them individually or as a batch:
37
+
38
+ - **Batch together** decisions that are tightly coupled — they touch the same code, share types, or depend on each other so heavily that implementing one without the others would produce incomplete or throwaway code (e.g., a data model + its validation + its state machine).
39
+ - **Implement separately** decisions that are independent — they touch different areas of the codebase and can stand on their own.
40
+
41
+ When batching, implement all the code together, add annotations for all decisions, then update each decision record and status individually in step 4.
42
+
43
+ ### 1. Understand the decision(s)
44
+
45
+ Read each decision record carefully. Understand:
46
+ - What was decided
47
+ - The rationale and constraints
48
+ - The code areas referenced
49
+ - Any superseded or amended decisions (read those too for context on what changed)
50
+
51
+ ### 2. Make code changes
52
+
53
+ Implement the decision(s) by modifying the codebase. Follow the practices manifest if one exists.
54
+
55
+ **Refining decisions during implementation:** While implementing, you may discover details that weren't anticipated during planning — a specific threshold value, an edge case handling approach, or a refinement to the original design. Since the decision is still in `proposed` status, it is **mutable** and can be updated:
56
+
57
+ - **Small refinements** (implementation details, specific values, edge cases that don't change the decision's intent) — update the decision record inline. Amend the Decision, Rationale, or Consequences sections as needed. This is expected and encouraged.
58
+ - **Major discoveries** (a fundamentally different approach is needed, or an entirely new design concern surfaces) — stop and suggest the user run `/dld-decide` to record a separate decision. If the new discovery invalidates the current decision, it may need to be superseded instead.
59
+
60
+ The boundary: if the discovery changes the *intent* of the decision, it's a new decision. If it refines the *implementation details*, update the current one.
61
+
62
+ ### 3. Add `@decision` annotations
63
+
64
+ **This step is mandatory.** Every implemented decision MUST have at least one `@decision(DL-NNN)` annotation in the source code. Updating the decision record's `references` field alone is not sufficient. The annotation in code is what triggers AI agents to look up the decision before modifying the annotated code.
65
+
66
+ Add `@decision(DL-NNN)` annotations to the code you modified or created. Place annotations in comments near the relevant code.
67
+
68
+ **Where to annotate:**
69
+ - Functions, methods, or classes that embody the decision
70
+ - Configuration or constants that were chosen based on the decision
71
+ - Key logic branches where the decision's rationale matters
72
+
73
+ **Annotation format** (adapt comment syntax to the language):
74
+ ```typescript
75
+ // @decision(DL-012)
76
+ function calculateVAT(order: Order): Money {
77
+ // ...
78
+ }
79
+ ```
80
+
81
+ ```python
82
+ # @decision(DL-012)
83
+ def calculate_vat(order: Order) -> Money:
84
+ ...
85
+ ```
86
+
87
+ **Guidelines:**
88
+ - Annotate at the declaration level, not every line
89
+ - One annotation per decision per code location
90
+ - Multiple decisions can annotate the same code: `// @decision(DL-012) @decision(DL-015)`
91
+ - Use the `annotation_prefix` from `dld.config.yaml` (default: `@decision`)
92
+
93
+ **Keep annotations lean — the decision record is the single source of truth.**
94
+
95
+ The point of `@decision(DL-NNN)` is to keep the rich context (rationale, constraints, alternatives, consequences) in the decision record, *not* scattered through the code. The annotation is a pointer, not a summary. Do not let implementing a decision turn into a comment-writing exercise.
96
+
97
+ - **Default to the bare annotation.** `// @decision(DL-012)` on its own is the norm and is usually all you need.
98
+ - **Do not restate the decision's context.** Don't paraphrase the rationale, the alternatives considered, or the "why" in comments. That duplicates the record, creates a second source of truth, and drifts the moment the decision is adjusted.
99
+ - **Avoid "because" comments paired with the annotation.** `// @decision(DL-012)` already means "the reasoning lives in DL-012." Writing `// We use X because Y (see DL-012)` defeats the purpose — drop the "because Y."
100
+ - **Only add a further comment when the *code itself* is genuinely non-obvious** — a subtle invariant, a non-intuitive workaround, a non-local ordering dependency. Such a comment should explain *what the code is doing*, never *why the decision was made* (that's the record's job).
101
+
102
+ When in doubt, leave it out — a reader who wants the "why" follows the annotation to the decision record.
103
+
104
+ ### 4. Update decision records
105
+
106
+ For each implemented decision:
107
+
108
+ 1. **Update the `references` field** in the decision record's YAML frontmatter. Edit the file directly — add the code paths and symbols that were annotated. Example:
109
+ ```yaml
110
+ references:
111
+ - path: src/billing/vat.ts
112
+ symbol: calculateVAT
113
+ - path: src/billing/vat.test.ts
114
+ ```
115
+
116
+ 2. **Update status** from `proposed` to `accepted`:
117
+ ```bash
118
+ {{dld}} update-status DL-NNN accepted
119
+ ```
120
+
121
+ ### 5. Verify annotations
122
+
123
+ After updating all decision records, run `verify-annotations` to confirm every implemented decision has at least one `@decision` annotation in the codebase:
124
+
125
+ ```bash
126
+ {{dld}} verify-annotations DL-005 DL-006
127
+ ```
128
+
129
+ Pass all the decision IDs that were implemented. If any are missing annotations, the command will report them and exit with an error. Go back and add the missing annotations before proceeding.
130
+
131
+ ### 6. Review code changes
132
+
133
+ Check `dld.config.yaml` for the `implement_review` key. If it is set to `false`, skip this step entirely. If it is `true` or absent (default: enabled), proceed.
134
+
135
+ Launch a subagent to review all code changes for correctness and security. Use the `Agent` tool (also called `AgentTool`) with a prompt constructed from the template below, replacing all `{{placeholders}}` with actual values:
136
+
137
+ ```
138
+ You are reviewing code changes for the {{project_name}} project before committing. The changes implement {{decision_count}} decisions ({{decision_range}}) covering:
139
+
140
+ {{decision_summaries}}
141
+
142
+ The project uses:
143
+ {{tech_stack_summary}}
144
+
145
+ Review these files for:
146
+ - Correctness (logic errors, edge cases)
147
+ - Security (SQL injection, directory traversal, XSS, etc.)
148
+ - Consistency with existing patterns and conventions
149
+ - Type safety issues
150
+ - Missing error handling
151
+ - Any code that could be simplified
152
+
153
+ Files to review (read all of them):
154
+ {{file_list}}
155
+
156
+ Also read the practices doc at {{practices_path}}
157
+
158
+ Focus on the changes made for these decisions; report pre-existing issues only where the new code interacts with them. Before reporting consistency findings, examine similar existing code in the repo to learn its conventions.
159
+
160
+ Do NOT make any changes. Only report findings. Be concise — focus on actual issues, not style preferences ({{linter_name}} handles style).
161
+
162
+ Report each finding in this format:
163
+
164
+ ### [SEVERITY] Short title
165
+ - Location: `path/to/file.ext:42`
166
+ - Description: what is wrong and why it matters
167
+ - Recommendation: specific, actionable fix
168
+
169
+ Group findings by severity:
170
+ - Critical (must fix): incorrect behavior, data loss, or an exploitable vulnerability
171
+ - Moderate (should fix): bugs in edge cases, missing error handling that can plausibly trigger
172
+ - Minor (nice to have): simplifications and small improvements
173
+ ```
174
+
175
+ **Filling in the placeholders:**
176
+ - `{{project_name}}` — from `dld.config.yaml` or the repo directory name
177
+ - `{{decision_count}}` and `{{decision_range}}` — count and IDs of the decisions just implemented (e.g., "3 decisions (DL-005 – DL-007)")
178
+ - `{{decision_summaries}}` — one-line summary of each decision's title and intent
179
+ - `{{tech_stack_summary}}` — languages, frameworks, and key libraries from the project (infer from `dld.config.yaml`, `package.json`, or equivalent)
180
+ - `{{file_list}}` — all files you created or modified during steps 2–4
181
+ - `{{practices_path}}` — path to `decisions/PRACTICES.md` (or namespace-specific practices if applicable). Omit the line if no practices file exists.
182
+ - `{{linter_name}}` — the project's linter (e.g., ESLint, Ruff). If unknown, use "the project linter"
183
+
184
+ **Launching the subagent is requested by the user.** Some agent harnesses carry a standing instruction not to spawn subagents unless the user asked for one. That condition is met here: the user asked by running this skill in a project whose `implement_review` setting is enabled. The request does not need to be repeated in conversation, and this step is not an unprompted fan-out — it is one review agent, at a fixed point, that the project opted into.
185
+
186
+ **If the subagent genuinely cannot run** — the tool is unavailable, or the user denies the call — do not silently skip the review. Do it inline instead, and make it a deliberate pass rather than a recollection: re-read each changed file from disk and work through the checklist above against what is actually written. Then state in your final report that the review ran inline rather than in a subagent, and why. An inline review is the author checking their own work; it is weaker than a fresh-context review at catching assumptions baked in while implementing, and the user needs to know which one they got.
187
+
188
+ **Acting on findings:**
189
+ - **Critical** — fix before proceeding
190
+ - **Moderate** — fix unless you disagree with the finding (use your judgment)
191
+ - **Minor** — skip unless trivial to address
192
+
193
+ **Note:** The review subagent operates with limited context and may flag false positives or misunderstand project-specific patterns. Use your own judgment — you have fuller context from having just written the code. If you're uncertain whether a finding warrants a fix, ask the user before making changes.
194
+
195
+ If you made fixes, re-run `verify-annotations` from step 5 to ensure annotations are still intact.
196
+
197
+ ### 7. Regenerate INDEX.md
198
+
199
+ ```bash
200
+ {{dld}} regenerate-index
201
+ ```
202
+
203
+ ### 8. Suggest next steps
204
+
205
+ > Implemented and accepted: **DL-NNN** (<title>)
206
+ >
207
+ > Code changes:
208
+ > - `src/billing/vat.ts` — modified `calculateVAT` (annotated with `@decision(DL-NNN)`)
209
+ > - `src/billing/vat.test.ts` — added tests
210
+ >
211
+ > Next steps:
212
+ > - `/dld-decide` — record another decision
213
+ > - `/dld-audit` — check for drift between decisions and code