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,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dld-init
|
|
3
|
+
description: Bootstrap DLD (Decision-Linked Development) in a repository. Creates dld.config.yaml, the decisions/ directory, and INDEX.md. Run once per project.
|
|
4
|
+
compatibility: Requires Node.js 20+ and git.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /dld-init — Bootstrap DLD
|
|
8
|
+
|
|
9
|
+
You are initializing Decision-Linked Development (DLD) in this repository. This is an interactive setup process that runs once per project.
|
|
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: `create-config`, `create-directories`, `create-empty-index`, `install-rule`.
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
- This must be a git repository
|
|
24
|
+
- `dld.config.yaml` must NOT already exist at the repo root (if it does, tell the user DLD is already initialized and suggest the dld-status skill instead)
|
|
25
|
+
|
|
26
|
+
Users who install dld-kit from npm can run `npx dld-kit init` in a terminal instead: it does steps 2–4 and 6 non-interactively and also installs the skills. This skill covers projects whose skills were installed another way.
|
|
27
|
+
|
|
28
|
+
## Steps
|
|
29
|
+
|
|
30
|
+
### 1. Ask about project structure
|
|
31
|
+
|
|
32
|
+
Ask the user:
|
|
33
|
+
|
|
34
|
+
> Is this a **flat** project (all decisions in one directory) or a **namespaced** project (decisions organized by component/domain, e.g., for a monorepo)?
|
|
35
|
+
|
|
36
|
+
- **Flat** is the default and right for most projects
|
|
37
|
+
- **Namespaced** is for monorepos or projects with distinct domains (billing, auth, etc.)
|
|
38
|
+
|
|
39
|
+
If namespaced, ask for the initial namespace list. Suggest they can add more later.
|
|
40
|
+
|
|
41
|
+
### 2. Create `dld.config.yaml`
|
|
42
|
+
|
|
43
|
+
Run `create-config`:
|
|
44
|
+
```bash
|
|
45
|
+
{{dld}} create-config <mode> [namespace1 namespace2 ...]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Example flat:
|
|
49
|
+
```bash
|
|
50
|
+
{{dld}} create-config flat
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Example namespaced:
|
|
54
|
+
```bash
|
|
55
|
+
{{dld}} create-config namespaced billing auth shared
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. Create directory structure
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
{{dld}} create-directories
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This reads mode and namespaces from `dld.config.yaml` (created in step 2).
|
|
65
|
+
|
|
66
|
+
### 4. Create initial INDEX.md
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
{{dld}} create-empty-index
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This reads mode from `dld.config.yaml`.
|
|
73
|
+
|
|
74
|
+
### 5. Offer to create a practices manifest
|
|
75
|
+
|
|
76
|
+
Ask the user:
|
|
77
|
+
|
|
78
|
+
> Would you like to create a **development practices manifest**? This is an optional document (`decisions/PRACTICES.md`) that captures your project's development conventions (testing approach, code style, error handling patterns, etc.). The AI agent reads this when making and implementing decisions.
|
|
79
|
+
>
|
|
80
|
+
> You can skip this now and add it later at any time.
|
|
81
|
+
|
|
82
|
+
If they accept, help them fill it out by asking about:
|
|
83
|
+
- Testing practices (TDD? coverage targets? integration test requirements?)
|
|
84
|
+
- Code style preferences (error handling patterns, validation approach)
|
|
85
|
+
- Architecture conventions (dependency injection, repository pattern, etc.)
|
|
86
|
+
|
|
87
|
+
If the repository already has application code, scan it first and suggest conventions you observe (e.g., "I see you're using Result types for error handling and Zod for validation — should I include those?"). This saves the user from having to recall everything from scratch.
|
|
88
|
+
|
|
89
|
+
Write `decisions/PRACTICES.md` with their answers in simple markdown format:
|
|
90
|
+
```markdown
|
|
91
|
+
# Development Practices
|
|
92
|
+
|
|
93
|
+
## Testing
|
|
94
|
+
- ...
|
|
95
|
+
|
|
96
|
+
## Code Style
|
|
97
|
+
- ...
|
|
98
|
+
|
|
99
|
+
## Architecture
|
|
100
|
+
- ...
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
For namespaced projects, this is the root-level shared practices. Mention they can create namespace-specific practices later at `decisions/records/<namespace>/PRACTICES.md`.
|
|
104
|
+
|
|
105
|
+
### 6. Install the always-on rule
|
|
106
|
+
|
|
107
|
+
The rule tells the agent to look up `@decision` annotations before changing annotated code, in every session. Install it for the harness you are running in:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
{{dld}} install-rule --agent <harness>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`<harness>` is one of `claude` (Claude Code), `antigravity`, `codex`, `cursor`, `opencode` or `pi`; for another harness that reads `AGENTS.md`, such as Copilot CLI, use `codex`. If you are unsure which one you are, or the user says the team uses several agents, ask the user and pass them all, comma-separated (e.g. `--agent claude,codex`). The command decides where the rule goes (a rule file the harness loads, or a marked block in `AGENTS.md` or `CLAUDE.md`) and prints what it wrote; relay that to the user, including any warning.
|
|
114
|
+
|
|
115
|
+
Do not write the rule into `CLAUDE.md` or `AGENTS.md` yourself.
|
|
116
|
+
|
|
117
|
+
### 7. Suggest next steps
|
|
118
|
+
|
|
119
|
+
Tell the user:
|
|
120
|
+
|
|
121
|
+
> DLD is initialized. Here's what you can do next:
|
|
122
|
+
|
|
123
|
+
If the repository already has application code:
|
|
124
|
+
> - the dld-retrofit skill — generate initial decisions from your existing codebase
|
|
125
|
+
> - Edit `decisions/PRACTICES.md` to refine your development practices (if created)
|
|
126
|
+
|
|
127
|
+
If this is a new/empty project:
|
|
128
|
+
> - the dld-decide skill — record your first decision
|
|
129
|
+
> - the dld-plan skill — break down a feature into multiple decisions
|
|
130
|
+
> - Edit `decisions/PRACTICES.md` to refine your development practices (if created)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dld-lookup
|
|
3
|
+
description: Look up decisions by ID, tag, code path, or keyword. IMPORTANT — use this proactively whenever you encounter `@decision` annotations in code you are about to read or modify.
|
|
4
|
+
compatibility: No external dependencies.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /dld-lookup — Look Up Decisions
|
|
8
|
+
|
|
9
|
+
You are looking up decision records. This skill is used in two ways:
|
|
10
|
+
1. **Proactively by you (the AI agent)** — whenever you encounter `@decision(DL-XXX)` annotations in code you're reading or about to modify, look up the decision to understand the rationale before proceeding. This is not optional.
|
|
11
|
+
2. **On request by the developer** — to query decisions by ID, tag, code path, or keyword.
|
|
12
|
+
|
|
13
|
+
## Prerequisites
|
|
14
|
+
|
|
15
|
+
Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
|
|
16
|
+
|
|
17
|
+
Read `dld.config.yaml` to understand the project structure (flat vs namespaced, decisions directory). The decisions directory path can be resolved by reading the `decisions_dir` field from `dld.config.yaml`. Decision records (DL-*.md) live in the `records/` subdirectory under the decisions directory.
|
|
18
|
+
|
|
19
|
+
## Query modes
|
|
20
|
+
|
|
21
|
+
Parse the user's input to determine the query type:
|
|
22
|
+
|
|
23
|
+
### By ID: `/dld-lookup DL-047`
|
|
24
|
+
|
|
25
|
+
Find and read the decision file `DL-047.md`. Search the records subdirectory (`decisions/records/`, including namespace subdirectories) for the file.
|
|
26
|
+
|
|
27
|
+
Display the full decision record.
|
|
28
|
+
|
|
29
|
+
### By tag: `/dld-lookup tag:payment-gateway`
|
|
30
|
+
|
|
31
|
+
Scan all decision files and find those with the matching tag in their YAML frontmatter `tags` field.
|
|
32
|
+
|
|
33
|
+
Display a summary table, then offer to show full details for any specific decision:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Found 3 decisions tagged `payment-gateway`:
|
|
37
|
+
|
|
38
|
+
| ID | Title | Status |
|
|
39
|
+
|----|-------|--------|
|
|
40
|
+
| DL-045 | Payment gateway retry strategy | accepted |
|
|
41
|
+
| DL-046 | Idempotency key format | proposed |
|
|
42
|
+
| DL-047 | Gateway timeout handling | proposed |
|
|
43
|
+
|
|
44
|
+
Would you like to see the full details for any of these?
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### By code path: `/dld-lookup path:src/billing/vat.ts`
|
|
48
|
+
|
|
49
|
+
Scan all decision files and find those with a matching `path` in their `references` field. Match both exact paths and partial paths (e.g., `vat.ts` should match `src/billing/vat.ts`).
|
|
50
|
+
|
|
51
|
+
Display results the same way as tag lookup.
|
|
52
|
+
|
|
53
|
+
### By keyword: `/dld-lookup <search terms>`
|
|
54
|
+
|
|
55
|
+
If the input doesn't match the `DL-NNN`, `tag:`, or `path:` patterns, treat it as a keyword search. Search across:
|
|
56
|
+
- Decision titles
|
|
57
|
+
- Decision body content (Context, Decision, Rationale, Consequences sections)
|
|
58
|
+
- Tags
|
|
59
|
+
|
|
60
|
+
Display results the same way as tag lookup.
|
|
61
|
+
|
|
62
|
+
## Proactive usage (encountering `@decision` annotations)
|
|
63
|
+
|
|
64
|
+
When you encounter `@decision(DL-XXX)` in code — whether you are reading, modifying, or reviewing it — you MUST look up the referenced decision before proceeding. This applies to all interactions with annotated code, not just when explicitly asked.
|
|
65
|
+
|
|
66
|
+
After reading the decision:
|
|
67
|
+
|
|
68
|
+
1. **Understand** the rationale behind the annotated code
|
|
69
|
+
2. **Assess** whether your planned changes are compatible with the decision
|
|
70
|
+
3. **If they conflict** — stop and inform the user. Explain the conflict and suggest recording a new decision via `/dld-decide` that supersedes the existing one. Do not silently modify code in a way that contradicts an active decision.
|
|
71
|
+
4. **If they're compatible** — proceed with the modification
|
|
72
|
+
|
|
73
|
+
This is the core DLD feedback loop — `@decision` annotations are mechanical triggers that ensure design rationale is consulted before code is changed.
|
|
@@ -0,0 +1,132 @@
|
|
|
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
|
+
---
|
|
6
|
+
|
|
7
|
+
# /dld-plan — Plan a Feature as Multiple Decisions
|
|
8
|
+
|
|
9
|
+
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.
|
|
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
|
|
28
|
+
2. Read `decisions/PRACTICES.md` if it exists — consider project conventions when breaking down the feature
|
|
29
|
+
|
|
30
|
+
## Conversation flow
|
|
31
|
+
|
|
32
|
+
### 1. Collect the feature description
|
|
33
|
+
|
|
34
|
+
If the user provided context with the skill invocation, use it. Otherwise ask:
|
|
35
|
+
|
|
36
|
+
> What feature are you planning? Describe what you want to build and why.
|
|
37
|
+
|
|
38
|
+
### 2. Determine namespace (namespaced projects only)
|
|
39
|
+
|
|
40
|
+
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.
|
|
41
|
+
|
|
42
|
+
Once determined, also read `decisions/records/<namespace>/PRACTICES.md` if it exists for namespace-specific conventions.
|
|
43
|
+
|
|
44
|
+
### 3. Check for related existing decisions
|
|
45
|
+
|
|
46
|
+
Before proposing the breakdown, scan existing decision files for:
|
|
47
|
+
- Decisions that reference the same code areas
|
|
48
|
+
- Decisions with overlapping tags or topics
|
|
49
|
+
- Decisions that the new feature might supersede or amend
|
|
50
|
+
|
|
51
|
+
Mention any related decisions to the developer so the breakdown accounts for them.
|
|
52
|
+
|
|
53
|
+
### 4. Break it down
|
|
54
|
+
|
|
55
|
+
Analyze the feature and propose a breakdown into discrete decisions. Each decision should be:
|
|
56
|
+
- **Independent enough** to stand on its own as a rationale record
|
|
57
|
+
- **Concrete enough** that it captures a specific choice, not just "build X"
|
|
58
|
+
- **Ordered** by dependency where relevant (which decisions depend on others)
|
|
59
|
+
|
|
60
|
+
Present the proposed breakdown:
|
|
61
|
+
|
|
62
|
+
> I'd suggest breaking this into the following decisions:
|
|
63
|
+
>
|
|
64
|
+
> 1. **Choose payment gateway adapter pattern** — How to abstract the gateway interface
|
|
65
|
+
> 2. **Define retry strategy for failed payments** — Backoff logic and max attempts
|
|
66
|
+
> 3. **Idempotency key format** — How to prevent duplicate charges
|
|
67
|
+
>
|
|
68
|
+
> Does this look right? Want to add, remove, or adjust any?
|
|
69
|
+
|
|
70
|
+
Iterate with the developer until the breakdown is agreed.
|
|
71
|
+
|
|
72
|
+
### 5. Choose a grouping tag
|
|
73
|
+
|
|
74
|
+
Propose a tag that groups these decisions:
|
|
75
|
+
|
|
76
|
+
> I'll tag all of these with `payment-gateway` so they're grouped together. Sound good?
|
|
77
|
+
|
|
78
|
+
The tag should be descriptive, kebab-case, and specific to this feature.
|
|
79
|
+
|
|
80
|
+
### 6. Create decision records
|
|
81
|
+
|
|
82
|
+
For each decision in the breakdown, run the same commands used by `/dld-decide`:
|
|
83
|
+
|
|
84
|
+
First, get the next ID:
|
|
85
|
+
```bash
|
|
86
|
+
{{dld}} next-id
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
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):
|
|
90
|
+
```bash
|
|
91
|
+
printf "## Context\n\n...\n\n## Decision\n\n...\n\n## Rationale\n\n...\n\n## Consequences\n\n..." | {{dld}} create-decision \
|
|
92
|
+
--id "DL-NNN" \
|
|
93
|
+
--title "Short descriptive title" \
|
|
94
|
+
--namespace "billing" \
|
|
95
|
+
--tags "payment-gateway" \
|
|
96
|
+
--supersedes "DL-003" \
|
|
97
|
+
--amends "DL-005" \
|
|
98
|
+
--body-stdin
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Repeat for each decision, incrementing the ID each time. Run `next-id` before each creation to ensure correct sequencing.
|
|
102
|
+
|
|
103
|
+
If any decision supersedes an existing one, also update the old decision's status:
|
|
104
|
+
```bash
|
|
105
|
+
{{dld}} update-status DL-003 superseded
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Do not** update the status of amended decisions — they stay `accepted`.
|
|
109
|
+
|
|
110
|
+
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.
|
|
111
|
+
|
|
112
|
+
### 7. Regenerate INDEX.md
|
|
113
|
+
|
|
114
|
+
After all decisions are created:
|
|
115
|
+
```bash
|
|
116
|
+
{{dld}} regenerate-index
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 8. Suggest next steps
|
|
120
|
+
|
|
121
|
+
> Created **N** decisions for feature `<tag>`:
|
|
122
|
+
>
|
|
123
|
+
> | ID | Title | Status |
|
|
124
|
+
> |----|-------|--------|
|
|
125
|
+
> | DL-010 | Choose payment gateway adapter pattern | proposed |
|
|
126
|
+
> | DL-011 | Define retry strategy for failed payments | proposed |
|
|
127
|
+
> | DL-012 | Idempotency key format | proposed |
|
|
128
|
+
>
|
|
129
|
+
> Next steps:
|
|
130
|
+
> - `/dld-adjust` — refine any decisions before implementing
|
|
131
|
+
> - `/dld-implement` — implement all proposed decisions (or `/dld-implement DL-NNN` for a specific one)
|
|
132
|
+
> - `/dld-lookup tag:<tag>` — review all decisions in this group
|
|
@@ -0,0 +1,170 @@
|
|
|
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
|
+
---
|
|
6
|
+
|
|
7
|
+
# /dld-reindex — Resolve Decision ID Collisions
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
**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.
|
|
12
|
+
|
|
13
|
+
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.
|
|
14
|
+
|
|
15
|
+
## Interaction style
|
|
16
|
+
|
|
17
|
+
Use the `AskUserQuestion` tool when prompting for consent and at the finish step. Everything else is deterministic.
|
|
18
|
+
|
|
19
|
+
**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.
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
{{dld-setup}}
|
|
24
|
+
|
|
25
|
+
This skill uses: `resolve-base`, `plan-renames`, `rename-decision`, `find-stale-mentions`, `commit-reindex`, `regenerate-index`.
|
|
26
|
+
|
|
27
|
+
## Prerequisites
|
|
28
|
+
|
|
29
|
+
1. Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.
|
|
30
|
+
2. Verify the working tree is clean (`git status --porcelain` empty). If not, ask the user to commit or stash first, then stop.
|
|
31
|
+
3. Fetch the latest base state:
|
|
32
|
+
```bash
|
|
33
|
+
git fetch origin
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Step 1: Resolve the base ref
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
BASE=$({{dld}} resolve-base)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`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).
|
|
43
|
+
|
|
44
|
+
The user may pass an explicit base when invoking the skill (e.g. `/dld-reindex origin/develop`) — honor it if present.
|
|
45
|
+
|
|
46
|
+
## Step 2: Plan the renames
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
PLAN=$({{dld}} plan-renames --base "$BASE")
|
|
50
|
+
echo "$PLAN"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Output is tab-separated, one rename per line:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
<relative-path>\t<DL-OLD>\t<DL-NEW>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If the output is empty, exit with:
|
|
60
|
+
|
|
61
|
+
> No ID collisions detected. Safe to rebase onto `$BASE`.
|
|
62
|
+
|
|
63
|
+
`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.
|
|
64
|
+
|
|
65
|
+
The underlying helpers (`find-collisions`, `list-taken-ids`) remain available for debugging, but the SKILL flow always goes through `plan-renames`.
|
|
66
|
+
|
|
67
|
+
## Step 3: Get explicit consent for the history rewrite
|
|
68
|
+
|
|
69
|
+
Show the user the rename plan and the implication. Use `AskUserQuestion`:
|
|
70
|
+
|
|
71
|
+
> 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?
|
|
72
|
+
|
|
73
|
+
Options:
|
|
74
|
+
- **Rewrite and force-push** — agent applies renames, squashes, commits, and runs `git push --force-with-lease`.
|
|
75
|
+
- **Rewrite only** — agent applies renames, squashes, and commits. User pushes when ready.
|
|
76
|
+
- **Cancel** — abort with no changes.
|
|
77
|
+
|
|
78
|
+
If the user cancels, exit without touching anything.
|
|
79
|
+
|
|
80
|
+
## Step 4: Apply renames
|
|
81
|
+
|
|
82
|
+
For each line in the plan, call:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
{{dld}} rename-decision --old DL-OLD --new DL-NEW --path <relative-path> --base "$BASE"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`rename-decision` does all of:
|
|
89
|
+
|
|
90
|
+
- `git mv` the file from `DL-OLD.md` to `DL-NEW.md`.
|
|
91
|
+
- Patches the `id:` frontmatter field in the renamed file.
|
|
92
|
+
- Rewrites `DL-OLD` mentions inside the renamed file's body.
|
|
93
|
+
- 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.
|
|
94
|
+
- Rewrites `` `@decision` ``(DL-OLD) annotations to `` `@decision` ``(DL-NEW) in non-decision files that are part of the local change set.
|
|
95
|
+
|
|
96
|
+
The substitution is digit-aware: renaming `DL-100` will not accidentally rewrite `DL-1000`.
|
|
97
|
+
|
|
98
|
+
**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.
|
|
99
|
+
|
|
100
|
+
## Step 5: Review plain-text DL-OLD mentions
|
|
101
|
+
|
|
102
|
+
After all renames are applied (but before the squash), find any remaining bare `DL-OLD` references in non-decision changed files:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
echo "$PLAN" | {{dld}} find-stale-mentions --base "$BASE"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
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.
|
|
109
|
+
|
|
110
|
+
For each match:
|
|
111
|
+
|
|
112
|
+
1. Read the surrounding context in the file.
|
|
113
|
+
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`.
|
|
114
|
+
3. If the line should change, use the `Edit` tool to update that specific occurrence — don't do a blanket find-and-replace.
|
|
115
|
+
4. If the line should stay, leave it.
|
|
116
|
+
|
|
117
|
+
Surface the list of matches to the user with your verdicts before you finish, so they can sanity-check the judgment calls.
|
|
118
|
+
|
|
119
|
+
## Step 6: Squash and commit
|
|
120
|
+
|
|
121
|
+
Pipe the rename plan into `commit-reindex`:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
echo "$PLAN" | {{dld}} commit-reindex --base "$BASE"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This:
|
|
128
|
+
|
|
129
|
+
1. Computes the merge-base with `$BASE`.
|
|
130
|
+
2. Mixed-resets HEAD to the merge-base (working tree is preserved — it already holds the post-rename state from step 4).
|
|
131
|
+
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.
|
|
132
|
+
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.
|
|
133
|
+
5. Commits with a templated message that lists the renames in the subject and preserves the original branch commits' subjects in the body.
|
|
134
|
+
|
|
135
|
+
**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.
|
|
136
|
+
|
|
137
|
+
## Step 7: Push (if the user chose force-push)
|
|
138
|
+
|
|
139
|
+
If step 3's answer was "Rewrite and force-push":
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
if git rev-parse --verify --quiet "@{upstream}" >/dev/null; then
|
|
143
|
+
git push --force-with-lease
|
|
144
|
+
else
|
|
145
|
+
git push -u origin HEAD
|
|
146
|
+
fi
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`--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.
|
|
150
|
+
|
|
151
|
+
## Step 8: Report
|
|
152
|
+
|
|
153
|
+
Print:
|
|
154
|
+
|
|
155
|
+
- The renames table.
|
|
156
|
+
- The stderr note from step 2 if `gh` was skipped.
|
|
157
|
+
- The number of commits squashed.
|
|
158
|
+
- The next steps:
|
|
159
|
+
|
|
160
|
+
> 1. `git rebase $BASE`
|
|
161
|
+
> 2. `{{dld}} 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)
|
|
162
|
+
> 3. Commit the INDEX.md update
|
|
163
|
+
|
|
164
|
+
The skill never rebases or merges — that is always the user's call.
|
|
165
|
+
|
|
166
|
+
## Out of scope
|
|
167
|
+
|
|
168
|
+
- **Already-conflicted rebases.** If the user is mid-rebase with conflicts, tell them to `git rebase --abort` first and re-run this skill.
|
|
169
|
+
- **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.
|
|
170
|
+
- **Cross-namespace ID reconciliation** in namespaced projects. IDs are assumed globally unique across namespaces, matching `next-id`.
|