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.
- package/LICENSE +21 -0
- package/README.md +420 -0
- package/dist/dld.mjs +10379 -0
- package/package.json +64 -0
- package/skills/dld-adjust/SKILL.md +142 -0
- package/skills/dld-audit/SKILL.md +162 -0
- package/skills/dld-audit-auto/SKILL.md +172 -0
- package/skills/dld-common/SKILL.md +14 -0
- package/skills/dld-common/scripts/dld.mjs +10379 -0
- package/skills/dld-decide/SKILL.md +119 -0
- package/skills/dld-implement/SKILL.md +216 -0
- package/skills/dld-init/SKILL.md +133 -0
- package/skills/dld-lookup/SKILL.md +76 -0
- package/skills/dld-plan/SKILL.md +135 -0
- package/skills/dld-reindex/SKILL.md +173 -0
- package/skills/dld-retrofit/SKILL.md +181 -0
- package/skills/dld-snapshot/SKILL.md +284 -0
- package/skills/dld-status/SKILL.md +127 -0
- package/templates/rules/dld-workflow.md +22 -0
- package/templates/skills/dld-adjust/SKILL.md +139 -0
- package/templates/skills/dld-audit/SKILL.md +159 -0
- package/templates/skills/dld-audit-auto/SKILL.md +169 -0
- package/templates/skills/dld-common/SKILL.md +12 -0
- package/templates/skills/dld-decide/SKILL.md +116 -0
- package/templates/skills/dld-implement/SKILL.md +213 -0
- package/templates/skills/dld-init/SKILL.md +130 -0
- package/templates/skills/dld-lookup/SKILL.md +73 -0
- package/templates/skills/dld-plan/SKILL.md +132 -0
- package/templates/skills/dld-reindex/SKILL.md +170 -0
- package/templates/skills/dld-retrofit/SKILL.md +178 -0
- package/templates/skills/dld-snapshot/SKILL.md +281 -0
- package/templates/skills/dld-status/SKILL.md +124 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dld-plan
|
|
3
|
+
description: Break down a feature into multiple decisions interactively. Creates a set of decision records grouped by a shared tag.
|
|
4
|
+
compatibility: Requires Node.js 20+ and git.
|
|
5
|
+
metadata:
|
|
6
|
+
dld-kit-version: "1.0.0-rc.1"
|
|
7
|
+
---
|
|
8
|
+
<!-- Generated by dld-kit from templates/skills/dld-plan/SKILL.md. Do not edit: updating the skills overwrites this file. -->
|
|
9
|
+
|
|
10
|
+
# /dld-plan — Plan a Feature as Multiple Decisions
|
|
11
|
+
|
|
12
|
+
You are helping the developer break down a larger feature into discrete decisions. Each decision gets its own record, and they're grouped by a shared tag.
|
|
13
|
+
|
|
14
|
+
## Interaction style
|
|
15
|
+
|
|
16
|
+
Use the `AskUserQuestion` tool for all questions and prompts. This provides a structured input experience for the user rather than waiting for freeform replies.
|
|
17
|
+
|
|
18
|
+
## Commands
|
|
19
|
+
|
|
20
|
+
The commands below run the `dld` CLI bundled with the dld-common skill, and need Node.js 20+. `<skill-dir>` stands for the absolute path of this skill's directory. If `<skill-dir>/../dld-common/scripts/dld.mjs` does not exist, stop and tell the user to install the dld-common skill: `npx skills add jimutt/dld-kit --skill dld-common`.
|
|
21
|
+
|
|
22
|
+
This skill uses: `next-id`, `create-decision`, `update-status`, `regenerate-index`.
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
|
|
27
|
+
|
|
28
|
+
## Read project context
|
|
29
|
+
|
|
30
|
+
1. Read `dld.config.yaml` to understand the project structure
|
|
31
|
+
2. Read `decisions/PRACTICES.md` if it exists — consider project conventions when breaking down the feature
|
|
32
|
+
|
|
33
|
+
## Conversation flow
|
|
34
|
+
|
|
35
|
+
### 1. Collect the feature description
|
|
36
|
+
|
|
37
|
+
If the user provided context with the skill invocation, use it. Otherwise ask:
|
|
38
|
+
|
|
39
|
+
> What feature are you planning? Describe what you want to build and why.
|
|
40
|
+
|
|
41
|
+
### 2. Determine namespace (namespaced projects only)
|
|
42
|
+
|
|
43
|
+
If the project is namespaced, determine which namespace(s) this feature belongs to early — infer from the description if possible, otherwise ask. They can span multiple namespaces if the feature crosses boundaries.
|
|
44
|
+
|
|
45
|
+
Once determined, also read `decisions/records/<namespace>/PRACTICES.md` if it exists for namespace-specific conventions.
|
|
46
|
+
|
|
47
|
+
### 3. Check for related existing decisions
|
|
48
|
+
|
|
49
|
+
Before proposing the breakdown, scan existing decision files for:
|
|
50
|
+
- Decisions that reference the same code areas
|
|
51
|
+
- Decisions with overlapping tags or topics
|
|
52
|
+
- Decisions that the new feature might supersede or amend
|
|
53
|
+
|
|
54
|
+
Mention any related decisions to the developer so the breakdown accounts for them.
|
|
55
|
+
|
|
56
|
+
### 4. Break it down
|
|
57
|
+
|
|
58
|
+
Analyze the feature and propose a breakdown into discrete decisions. Each decision should be:
|
|
59
|
+
- **Independent enough** to stand on its own as a rationale record
|
|
60
|
+
- **Concrete enough** that it captures a specific choice, not just "build X"
|
|
61
|
+
- **Ordered** by dependency where relevant (which decisions depend on others)
|
|
62
|
+
|
|
63
|
+
Present the proposed breakdown:
|
|
64
|
+
|
|
65
|
+
> I'd suggest breaking this into the following decisions:
|
|
66
|
+
>
|
|
67
|
+
> 1. **Choose payment gateway adapter pattern** — How to abstract the gateway interface
|
|
68
|
+
> 2. **Define retry strategy for failed payments** — Backoff logic and max attempts
|
|
69
|
+
> 3. **Idempotency key format** — How to prevent duplicate charges
|
|
70
|
+
>
|
|
71
|
+
> Does this look right? Want to add, remove, or adjust any?
|
|
72
|
+
|
|
73
|
+
Iterate with the developer until the breakdown is agreed.
|
|
74
|
+
|
|
75
|
+
### 5. Choose a grouping tag
|
|
76
|
+
|
|
77
|
+
Propose a tag that groups these decisions:
|
|
78
|
+
|
|
79
|
+
> I'll tag all of these with `payment-gateway` so they're grouped together. Sound good?
|
|
80
|
+
|
|
81
|
+
The tag should be descriptive, kebab-case, and specific to this feature.
|
|
82
|
+
|
|
83
|
+
### 6. Create decision records
|
|
84
|
+
|
|
85
|
+
For each decision in the breakdown, run the same commands used by `/dld-decide`:
|
|
86
|
+
|
|
87
|
+
First, get the next ID:
|
|
88
|
+
```bash
|
|
89
|
+
node "<skill-dir>/../dld-common/scripts/dld.mjs" next-id
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Then create the record, piping the body via `printf` with `\n` for newlines (do **not** use literal newlines in the body — use `\n` escape sequences):
|
|
93
|
+
```bash
|
|
94
|
+
printf "## Context\n\n...\n\n## Decision\n\n...\n\n## Rationale\n\n...\n\n## Consequences\n\n..." | node "<skill-dir>/../dld-common/scripts/dld.mjs" create-decision \
|
|
95
|
+
--id "DL-NNN" \
|
|
96
|
+
--title "Short descriptive title" \
|
|
97
|
+
--namespace "billing" \
|
|
98
|
+
--tags "payment-gateway" \
|
|
99
|
+
--supersedes "DL-003" \
|
|
100
|
+
--amends "DL-005" \
|
|
101
|
+
--body-stdin
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Repeat for each decision, incrementing the ID each time. Run `next-id` before each creation to ensure correct sequencing.
|
|
105
|
+
|
|
106
|
+
If any decision supersedes an existing one, also update the old decision's status:
|
|
107
|
+
```bash
|
|
108
|
+
node "<skill-dir>/../dld-common/scripts/dld.mjs" update-status DL-003 superseded
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Do not** update the status of amended decisions — they stay `accepted`.
|
|
112
|
+
|
|
113
|
+
For each decision, compose a focused body. Keep it concise — the full feature context is captured across the group. Each individual decision should capture its own specific rationale.
|
|
114
|
+
|
|
115
|
+
### 7. Regenerate INDEX.md
|
|
116
|
+
|
|
117
|
+
After all decisions are created:
|
|
118
|
+
```bash
|
|
119
|
+
node "<skill-dir>/../dld-common/scripts/dld.mjs" regenerate-index
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 8. Suggest next steps
|
|
123
|
+
|
|
124
|
+
> Created **N** decisions for feature `<tag>`:
|
|
125
|
+
>
|
|
126
|
+
> | ID | Title | Status |
|
|
127
|
+
> |----|-------|--------|
|
|
128
|
+
> | DL-010 | Choose payment gateway adapter pattern | proposed |
|
|
129
|
+
> | DL-011 | Define retry strategy for failed payments | proposed |
|
|
130
|
+
> | DL-012 | Idempotency key format | proposed |
|
|
131
|
+
>
|
|
132
|
+
> Next steps:
|
|
133
|
+
> - `/dld-adjust` — refine any decisions before implementing
|
|
134
|
+
> - `/dld-implement` — implement all proposed decisions (or `/dld-implement DL-NNN` for a specific one)
|
|
135
|
+
> - `/dld-lookup tag:<tag>` — review all decisions in this group
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dld-reindex
|
|
3
|
+
description: Resolve decision ID collisions between a local branch and the base branch (and open PRs) before rebasing. Renames colliding local decisions with git mv, rewrites cross-references and annotations, then squashes branch commits into a single rebase-clean reindex commit.
|
|
4
|
+
compatibility: Requires Node.js 20+ and git. Open-PR scanning additionally needs the `gh` CLI authenticated against a GitHub remote — the skill falls back gracefully when unavailable.
|
|
5
|
+
metadata:
|
|
6
|
+
dld-kit-version: "1.0.0-rc.1"
|
|
7
|
+
---
|
|
8
|
+
<!-- Generated by dld-kit from templates/skills/dld-reindex/SKILL.md. Do not edit: updating the skills overwrites this file. -->
|
|
9
|
+
|
|
10
|
+
# /dld-reindex — Resolve Decision ID Collisions
|
|
11
|
+
|
|
12
|
+
You are helping the developer untangle decision ID collisions before they rebase. Two or more developers can draft `DL-NNN` decisions in parallel; once one of them lands on the base branch (or appears in an open PR), the others must rename their local copies to the next free ID. This skill handles that mechanically and produces a branch state that rebases cleanly.
|
|
13
|
+
|
|
14
|
+
**This skill rewrites branch history.** That's not optional: if a colliding path (e.g. `decisions/records/DL-205.md`) was added by any commit on the branch, `git rebase` will hit an add/add conflict on that commit *before* it ever sees a later rename. The only fix is to ensure the colliding path never appears in the branch's history. The skill does this by squashing all branch commits since the merge-base into one reindex commit containing the renamed files.
|
|
15
|
+
|
|
16
|
+
If the branch has already been pushed, finishing the reindex will require a `--force-with-lease` push. The skill asks for explicit consent before rewriting history.
|
|
17
|
+
|
|
18
|
+
## Interaction style
|
|
19
|
+
|
|
20
|
+
Use the `AskUserQuestion` tool when prompting for consent and at the finish step. Everything else is deterministic.
|
|
21
|
+
|
|
22
|
+
**Do not redirect any command output to `/tmp` files.** The commands in this skill emit only what you need to act on; piping to `/tmp/*.txt`, `tee`-ing into scratch files, or stashing stderr separately is unnecessary and creates clutter outside the repo. If a command's output is too long to read in one go, narrow it (`| tail -N`, `| head -N`, or pass a more specific flag) rather than persisting it.
|
|
23
|
+
|
|
24
|
+
## Commands
|
|
25
|
+
|
|
26
|
+
The commands below run the `dld` CLI bundled with the dld-common skill, and need Node.js 20+. `<skill-dir>` stands for the absolute path of this skill's directory. If `<skill-dir>/../dld-common/scripts/dld.mjs` does not exist, stop and tell the user to install the dld-common skill: `npx skills add jimutt/dld-kit --skill dld-common`.
|
|
27
|
+
|
|
28
|
+
This skill uses: `resolve-base`, `plan-renames`, `rename-decision`, `find-stale-mentions`, `commit-reindex`, `regenerate-index`.
|
|
29
|
+
|
|
30
|
+
## Prerequisites
|
|
31
|
+
|
|
32
|
+
1. Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
|
|
33
|
+
2. Verify the working tree is clean (`git status --porcelain` empty). If not, ask the user to commit or stash first, then stop.
|
|
34
|
+
3. Fetch the latest base state:
|
|
35
|
+
```bash
|
|
36
|
+
git fetch origin
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Step 1: Resolve the base ref
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
BASE=$(node "<skill-dir>/../dld-common/scripts/dld.mjs" resolve-base)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`resolve-base` prefers the branch's upstream when it tracks a *different* branch (the typical "feature → main" setup). It falls back to `origin/main` if the upstream is unset OR if the upstream tracks the same branch name as the current branch (i.e. it's just the remote copy of this same branch, not a useful collision base).
|
|
46
|
+
|
|
47
|
+
The user may pass an explicit base when invoking the skill (e.g. `/dld-reindex origin/develop`) — honor it if present.
|
|
48
|
+
|
|
49
|
+
## Step 2: Plan the renames
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
PLAN=$(node "<skill-dir>/../dld-common/scripts/dld.mjs" plan-renames --base "$BASE")
|
|
53
|
+
echo "$PLAN"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Output is tab-separated, one rename per line:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
<relative-path>\t<DL-OLD>\t<DL-NEW>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If the output is empty, exit with:
|
|
63
|
+
|
|
64
|
+
> No ID collisions detected. Safe to rebase onto `$BASE`.
|
|
65
|
+
|
|
66
|
+
`plan-renames` may print a stderr note like `[dld-reindex] open PRs not scanned: gh CLI not installed`. **Always surface this to the user** so they know the renamed IDs were chosen against base-branch state only and may still collide with an open PR.
|
|
67
|
+
|
|
68
|
+
The underlying helpers (`find-collisions`, `list-taken-ids`) remain available for debugging, but the SKILL flow always goes through `plan-renames`.
|
|
69
|
+
|
|
70
|
+
## Step 3: Get explicit consent for the history rewrite
|
|
71
|
+
|
|
72
|
+
Show the user the rename plan and the implication. Use `AskUserQuestion`:
|
|
73
|
+
|
|
74
|
+
> Resolving these collisions requires rewriting branch history. I will squash the N commits since `<merge-base>` into a single reindex commit. The original commit subjects will be preserved in the new commit body. If the branch has already been pushed, finishing will require `git push --force-with-lease`. How should I proceed?
|
|
75
|
+
|
|
76
|
+
Options:
|
|
77
|
+
- **Rewrite and force-push** — agent applies renames, squashes, commits, and runs `git push --force-with-lease`.
|
|
78
|
+
- **Rewrite only** — agent applies renames, squashes, and commits. User pushes when ready.
|
|
79
|
+
- **Cancel** — abort with no changes.
|
|
80
|
+
|
|
81
|
+
If the user cancels, exit without touching anything.
|
|
82
|
+
|
|
83
|
+
## Step 4: Apply renames
|
|
84
|
+
|
|
85
|
+
For each line in the plan, call:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
node "<skill-dir>/../dld-common/scripts/dld.mjs" rename-decision --old DL-OLD --new DL-NEW --path <relative-path> --base "$BASE"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`rename-decision` does all of:
|
|
92
|
+
|
|
93
|
+
- `git mv` the file from `DL-OLD.md` to `DL-NEW.md`.
|
|
94
|
+
- Patches the `id:` frontmatter field in the renamed file.
|
|
95
|
+
- Rewrites `DL-OLD` mentions inside the renamed file's body.
|
|
96
|
+
- Rewrites `DL-OLD` mentions inside OTHER locally-added/modified decision files (frontmatter `supersedes` / `amends` / `references` and body). Scoped to the local change set vs the base ref.
|
|
97
|
+
- Rewrites `` `@decision` ``(DL-OLD) annotations to `` `@decision` ``(DL-NEW) in non-decision files that are part of the local change set.
|
|
98
|
+
|
|
99
|
+
The substitution is digit-aware: renaming `DL-100` will not accidentally rewrite `DL-1000`.
|
|
100
|
+
|
|
101
|
+
**Note on plain-text DL-NNN mentions in code:** In non-decision files (source code, READMEs, etc.) `rename-decision`'s rewrite is **scoped to `` `@decision` ``(DL-NNN) annotations only**. Bare `DL-NNN` references in comments, log strings, or test fixtures are left untouched here to avoid false-positive matches against unrelated identifiers. Step 5 handles them.
|
|
102
|
+
|
|
103
|
+
## Step 5: Review plain-text DL-OLD mentions
|
|
104
|
+
|
|
105
|
+
After all renames are applied (but before the squash), find any remaining bare `DL-OLD` references in non-decision changed files:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
echo "$PLAN" | node "<skill-dir>/../dld-common/scripts/dld.mjs" find-stale-mentions --base "$BASE"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Output is tab-separated, one match per line: `<path>\t<line>\t<DL-OLD>\t<DL-NEW>\t<line-content>`. Empty output means nothing to review.
|
|
112
|
+
|
|
113
|
+
For each match:
|
|
114
|
+
|
|
115
|
+
1. Read the surrounding context in the file.
|
|
116
|
+
2. Decide whether the reference makes sense as `DL-OLD` or should become `DL-NEW`. A code comment like `// Span-driven batching (DL-207) groups resolutions sharing the same turn context (DL-202)` after a `DL-207 → DL-213` rename almost certainly wants `DL-213` (it's prose alongside an annotation). A test fixture string that's checking historical data may need to stay as `DL-OLD`.
|
|
117
|
+
3. If the line should change, use the `Edit` tool to update that specific occurrence — don't do a blanket find-and-replace.
|
|
118
|
+
4. If the line should stay, leave it.
|
|
119
|
+
|
|
120
|
+
Surface the list of matches to the user with your verdicts before you finish, so they can sanity-check the judgment calls.
|
|
121
|
+
|
|
122
|
+
## Step 6: Squash and commit
|
|
123
|
+
|
|
124
|
+
Pipe the rename plan into `commit-reindex`:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
echo "$PLAN" | node "<skill-dir>/../dld-common/scripts/dld.mjs" commit-reindex --base "$BASE"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
This:
|
|
131
|
+
|
|
132
|
+
1. Computes the merge-base with `$BASE`.
|
|
133
|
+
2. Mixed-resets HEAD to the merge-base (working tree is preserved — it already holds the post-rename state from step 4).
|
|
134
|
+
3. Restores `INDEX.md` in the working tree to its merge-base state so the working tree is consistent with what we're about to commit. **INDEX.md is intentionally excluded from the reindex commit** — including it would cause a content conflict during rebase whenever the base branch also modified INDEX.md (git's 3-way merge fails to align both sides' top-of-file inserts even when row content overlaps). INDEX.md gets regenerated post-rebase instead.
|
|
135
|
+
4. Stages **only** an explicit path list derived from the original branch diff and the rename plan — the old paths (for deletions), the new paths (for additions), every other file the branch touched. Untracked unrelated paths (e.g. `.claude/worktrees`, scratch files, in-progress edits to unrelated files) are deliberately NOT swept in.
|
|
136
|
+
5. Commits with a templated message that lists the renames in the subject and preserves the original branch commits' subjects in the body.
|
|
137
|
+
|
|
138
|
+
**Do not use `git add -A` or `git commit -a` anywhere in this flow.** Use only `commit-reindex` to commit. Targeting paths explicitly is the whole point of this step.
|
|
139
|
+
|
|
140
|
+
## Step 7: Push (if the user chose force-push)
|
|
141
|
+
|
|
142
|
+
If step 3's answer was "Rewrite and force-push":
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
if git rev-parse --verify --quiet "@{upstream}" >/dev/null; then
|
|
146
|
+
git push --force-with-lease
|
|
147
|
+
else
|
|
148
|
+
git push -u origin HEAD
|
|
149
|
+
fi
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`--force-with-lease` is mandatory over `--force` here — it refuses to push if the remote moved since the last fetch, which protects against overwriting concurrent collaborator pushes.
|
|
153
|
+
|
|
154
|
+
## Step 8: Report
|
|
155
|
+
|
|
156
|
+
Print:
|
|
157
|
+
|
|
158
|
+
- The renames table.
|
|
159
|
+
- The stderr note from step 2 if `gh` was skipped.
|
|
160
|
+
- The number of commits squashed.
|
|
161
|
+
- The next steps:
|
|
162
|
+
|
|
163
|
+
> 1. `git rebase $BASE`
|
|
164
|
+
> 2. `node "<skill-dir>/../dld-common/scripts/dld.mjs" regenerate-index` (to repopulate INDEX.md with the renamed locals — the reindex commit intentionally leaves INDEX.md alone to keep the rebase conflict-free; INDEX.md is missing the renamed rows until you regenerate)
|
|
165
|
+
> 3. Commit the INDEX.md update
|
|
166
|
+
|
|
167
|
+
The skill never rebases or merges — that is always the user's call.
|
|
168
|
+
|
|
169
|
+
## Out of scope
|
|
170
|
+
|
|
171
|
+
- **Already-conflicted rebases.** If the user is mid-rebase with conflicts, tell them to `git rebase --abort` first and re-run this skill.
|
|
172
|
+
- **Preserving per-commit granularity.** The squash trades original commit boundaries for a deterministic rewrite. A future `--preserve-history` flag could perform a cherry-pick walk that rewrites each commit individually, but the edge cases (commits modifying an already-renamed file, merge commits, partial reruns) make it materially more complex than the squash.
|
|
173
|
+
- **Cross-namespace ID reconciliation** in namespaced projects. IDs are assumed globally unique across namespaces, matching `next-id`.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dld-retrofit
|
|
3
|
+
description: Bootstrap DLD decisions from an existing codebase. Analyzes code to infer rationale, generates decision records, and adds `@decision` annotations.
|
|
4
|
+
compatibility: Requires Node.js 20+ and git.
|
|
5
|
+
metadata:
|
|
6
|
+
dld-kit-version: "1.0.0-rc.1"
|
|
7
|
+
---
|
|
8
|
+
<!-- Generated by dld-kit from templates/skills/dld-retrofit/SKILL.md. Do not edit: updating the skills overwrites this file. -->
|
|
9
|
+
|
|
10
|
+
# /dld-retrofit — Retrofit Decisions onto Existing Code
|
|
11
|
+
|
|
12
|
+
You are helping the developer bootstrap DLD in an existing codebase by generating decision records from what the code already does. The goal is **not** 100% decision coverage — it's to create enough scaffolding that the DLD workflow feels natural for future development.
|
|
13
|
+
|
|
14
|
+
## Interaction style
|
|
15
|
+
|
|
16
|
+
Use the `AskUserQuestion` tool for all questions and prompts. This provides a structured input experience for the user rather than waiting for freeform replies.
|
|
17
|
+
|
|
18
|
+
## Commands
|
|
19
|
+
|
|
20
|
+
The commands below run the `dld` CLI bundled with the dld-common skill, and need Node.js 20+. `<skill-dir>` stands for the absolute path of this skill's directory. If `<skill-dir>/../dld-common/scripts/dld.mjs` does not exist, stop and tell the user to install the dld-common skill: `npx skills add jimutt/dld-kit --skill dld-common`.
|
|
21
|
+
|
|
22
|
+
This skill uses: `next-id`, `create-decision`, `update-status`, `regenerate-index`.
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
1. Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
|
|
27
|
+
2. There should be existing application code in the repository. If the repo is empty or only has boilerplate, suggest `/dld-decide` or `/dld-plan` instead.
|
|
28
|
+
|
|
29
|
+
## Read project context
|
|
30
|
+
|
|
31
|
+
1. Read `dld.config.yaml` for project structure (flat vs namespaced, decisions directory)
|
|
32
|
+
2. Read `decisions/PRACTICES.md` if it exists
|
|
33
|
+
3. Check for any existing decisions — retrofit can be run alongside existing decisions
|
|
34
|
+
|
|
35
|
+
## Step 1: Analyze the codebase
|
|
36
|
+
|
|
37
|
+
Perform a broad analysis of the codebase:
|
|
38
|
+
- Identify the main components, modules, and domain areas
|
|
39
|
+
- Note the tech stack, frameworks, and key dependencies
|
|
40
|
+
- Identify architectural patterns in use (layered architecture, domain-driven modules, etc.)
|
|
41
|
+
- Look for non-obvious implementation choices — these are the best candidates for decisions
|
|
42
|
+
|
|
43
|
+
Present a brief summary to the user:
|
|
44
|
+
|
|
45
|
+
> **Codebase analysis:**
|
|
46
|
+
> - [Tech stack summary]
|
|
47
|
+
> - [N] main components/modules identified: [list]
|
|
48
|
+
> - [Notable patterns or architectural choices observed]
|
|
49
|
+
|
|
50
|
+
## Step 2: Determine scope
|
|
51
|
+
|
|
52
|
+
Ask the user:
|
|
53
|
+
|
|
54
|
+
> Would you like to retrofit the **entire codebase**, or focus on a **specific area**?
|
|
55
|
+
|
|
56
|
+
If a specific area, ask them to identify it (a directory, module, or domain concept). Narrow the analysis scope accordingly.
|
|
57
|
+
|
|
58
|
+
## Step 3: Choose granularity
|
|
59
|
+
|
|
60
|
+
Explain the two modes and ask the user to choose:
|
|
61
|
+
|
|
62
|
+
> **Broad mode** — Creates high-level decisions covering major features and components. Produces file-level references only (e.g., `path: src/billing/service.ts`). Good for getting started quickly with a general decision scaffold.
|
|
63
|
+
>
|
|
64
|
+
> **Detailed mode** — Creates finer-grained decisions covering specific behaviors and design choices. Produces method-level references and annotations (e.g., `symbol: calculateVAT`). Takes longer but creates richer traceability from the start.
|
|
65
|
+
>
|
|
66
|
+
> Which mode would you like to use?
|
|
67
|
+
|
|
68
|
+
## Step 4: Identify decisions
|
|
69
|
+
|
|
70
|
+
### System-framing decisions (always include these first)
|
|
71
|
+
|
|
72
|
+
Before diving into implementation details, identify **foundational decisions that frame the system itself**. These establish the context that all other decisions hang on:
|
|
73
|
+
|
|
74
|
+
- **System purpose** — What is this service/application and why does it exist? What problem does it solve? (e.g., "Auth integration microservice bridging platform accounts to Firebase Auth")
|
|
75
|
+
- **Core domain model** — What are the key domain concepts and their relationships? (e.g., "Multi-provider account linking with one primary identity per provider")
|
|
76
|
+
- **Key integration boundaries** — What external systems does this interact with and how? (e.g., "Dual Firebase integration: Admin SDK for backend, REST API for OOB flows")
|
|
77
|
+
|
|
78
|
+
These framing decisions may not map to a single function — they often reference the application entry point, main service interface, or core domain model files. Without them, the projected OVERVIEW.md would read as a collection of implementation details with no narrative anchor.
|
|
79
|
+
|
|
80
|
+
Aim for 1-3 framing decisions depending on the system's complexity. Ask the user to help articulate these — they capture the kind of high-level context that's hardest to infer from code alone.
|
|
81
|
+
|
|
82
|
+
### Implementation-level decisions
|
|
83
|
+
|
|
84
|
+
Then identify decisions at the implementation level. Focus on:
|
|
85
|
+
|
|
86
|
+
- **Architectural choices** — why the code is structured this way (module boundaries, layer patterns, data flow)
|
|
87
|
+
- **Non-obvious implementation details** — retry logic, caching strategies, validation approaches, error handling patterns
|
|
88
|
+
- **Domain rules** — business logic that encodes specific rules or policies
|
|
89
|
+
- **Technology choices** — framework selection, library usage, storage approach
|
|
90
|
+
- **Trade-offs** — places where the code chose one approach over alternatives
|
|
91
|
+
|
|
92
|
+
**Broad mode:** Aim for 1-2 decisions per major component or feature area. Each decision should cover a significant chunk of functionality.
|
|
93
|
+
|
|
94
|
+
**Detailed mode:** Aim for decisions wherever there's a meaningful "why" behind the code. Still don't try to cover everything — focus on the decisions a future developer (or AI agent) would most benefit from knowing about.
|
|
95
|
+
|
|
96
|
+
**Ask when unsure:** If you encounter code that looks like a deliberate design choice but you can't confidently infer the rationale, ask the user. These are often the most valuable decisions to capture — the ones where the "why" isn't obvious from the code alone. For example:
|
|
97
|
+
|
|
98
|
+
> I see the order service retries with a 7-second delay and max 3 attempts. Is there a specific reason for these values, or is it a general resilience pattern?
|
|
99
|
+
|
|
100
|
+
Don't ask about everything — focus on cases where the implementation seems intentionally specific and the rationale would be lost without human input.
|
|
101
|
+
|
|
102
|
+
Present the proposed decisions as a numbered list, with framing decisions first:
|
|
103
|
+
|
|
104
|
+
> **Proposed decisions:**
|
|
105
|
+
>
|
|
106
|
+
> *System framing:*
|
|
107
|
+
> 1. **[System purpose/identity]** — [what this system is and why it exists]
|
|
108
|
+
> - Affects: `src/Application.ts` (or equivalent entry point)
|
|
109
|
+
> 2. **[Core domain model]** — [key concepts and relationships]
|
|
110
|
+
> - Affects: `src/models/Account.ts`, `src/models/Identity.ts`
|
|
111
|
+
>
|
|
112
|
+
> *Implementation decisions:*
|
|
113
|
+
> 3. **[Title]** — [one-line summary]
|
|
114
|
+
> - Affects: `src/path/to/code.ts`
|
|
115
|
+
> 4. **[Title]** — [one-line summary]
|
|
116
|
+
> - Affects: `src/path/to/other.ts`
|
|
117
|
+
> ...
|
|
118
|
+
>
|
|
119
|
+
> Want me to proceed with all of these, remove any, or adjust?
|
|
120
|
+
|
|
121
|
+
Let the user review and adjust the list before proceeding.
|
|
122
|
+
|
|
123
|
+
## Step 5: Generate decision records
|
|
124
|
+
|
|
125
|
+
For each approved decision:
|
|
126
|
+
|
|
127
|
+
1. Read the relevant code to understand what it does and infer the rationale
|
|
128
|
+
2. Write the decision record with Context, Decision, and Rationale sections. The **Context** should describe the problem the code solves. The **Decision** should describe what the code does. The **Rationale** should be your best inference of *why* — acknowledge when you're inferring rather than stating known facts (e.g., "likely chosen because..." or "this approach avoids...").
|
|
129
|
+
3. Include a Consequences section only when trade-offs are apparent from the code
|
|
130
|
+
4. Assign sequential IDs using `next-id`
|
|
131
|
+
5. Create each record using `create-decision`
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
ID=$(node "<skill-dir>/../dld-common/scripts/dld.mjs" next-id)
|
|
135
|
+
printf "## Context\n\n...\n\n## Decision\n\n...\n\n## Rationale\n\n..." | node "<skill-dir>/../dld-common/scripts/dld.mjs" create-decision \
|
|
136
|
+
--id "$ID" \
|
|
137
|
+
--title "Title" \
|
|
138
|
+
--tags "tag1, tag2" \
|
|
139
|
+
--body-stdin
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Step 6: Add annotations and references
|
|
143
|
+
|
|
144
|
+
For each decision, add `@decision(DL-NNN)` annotations to the relevant code:
|
|
145
|
+
|
|
146
|
+
- **Broad mode:** Annotate at the file/module level — typically at the top of the file or on the main export/class.
|
|
147
|
+
- **Detailed mode:** Annotate at the function/method/class level where the decision is embodied.
|
|
148
|
+
|
|
149
|
+
Then update each decision record's `references` field directly in the YAML frontmatter with the annotated code paths and symbols.
|
|
150
|
+
|
|
151
|
+
## Step 7: Mark as accepted
|
|
152
|
+
|
|
153
|
+
Since the code already exists, these decisions go directly to `accepted` status:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
node "<skill-dir>/../dld-common/scripts/dld.mjs" update-status DL-NNN accepted
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Do this for each generated decision.
|
|
160
|
+
|
|
161
|
+
## Step 8: Regenerate INDEX.md
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
node "<skill-dir>/../dld-common/scripts/dld.mjs" regenerate-index
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Step 9: Summary and next steps
|
|
168
|
+
|
|
169
|
+
> **Retrofit complete:**
|
|
170
|
+
> - Created **N** decisions (DL-XXX through DL-YYY)
|
|
171
|
+
> - Added **M** `@decision` annotations across the codebase
|
|
172
|
+
> - Mode: [broad/detailed]
|
|
173
|
+
> - Scope: [entire codebase / specific area]
|
|
174
|
+
>
|
|
175
|
+
> These decisions capture the current state of the codebase — not every design choice, but enough to establish a working decision scaffold.
|
|
176
|
+
>
|
|
177
|
+
> Next steps:
|
|
178
|
+
> - Review the generated decisions for accuracy — especially the inferred rationale
|
|
179
|
+
> - `/dld-snapshot` — generate SNAPSHOT.md and OVERVIEW.md from the new decisions
|
|
180
|
+
> - `/dld-decide` — record new decisions as you make changes going forward
|
|
181
|
+
> - `/dld-retrofit` — run again on other areas if you scoped to a specific component
|