From de7814f071ed9645db859f046764cee56cd2e2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jimmy=20Utterstr=C3=B6m?= Date: Tue, 24 Mar 2026 21:48:06 +0100 Subject: [PATCH] Add /dld-adjust skill for updating existing decisions New skill that handles permission gating (proposed vs accepted+pushed) and prevents the common AI anti-pattern of adding negative statements when users ask to remove content from decisions. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/dld-adjust/SKILL.md | 141 +++++++++++++++++++++++++++++ .claude/skills/dld-decide/SKILL.md | 1 + .claude/skills/dld-plan/SKILL.md | 1 + README.md | 2 + rules/dld-workflow.md | 1 + skills/dld-adjust/SKILL.md | 141 +++++++++++++++++++++++++++++ skills/dld-decide/SKILL.md | 1 + skills/dld-plan/SKILL.md | 1 + tile.json | 3 + 9 files changed, 292 insertions(+) create mode 100644 .claude/skills/dld-adjust/SKILL.md create mode 100644 skills/dld-adjust/SKILL.md diff --git a/.claude/skills/dld-adjust/SKILL.md b/.claude/skills/dld-adjust/SKILL.md new file mode 100644 index 0000000..14ca12f --- /dev/null +++ b/.claude/skills/dld-adjust/SKILL.md @@ -0,0 +1,141 @@ +--- +name: dld-adjust +description: Adjust or update existing decision records. Handles permission gating for accepted decisions and correctly interprets adjustment requests. +user_invocable: true +--- + +# /dld-adjust — Adjust a Decision + +You are helping the developer adjust one or more existing decision records. Your job is to apply their requested changes accurately and minimally. + +## Interaction style + +Use the `AskUserQuestion` tool for all questions and prompts. This provides a structured input experience for the user. + +## Script Paths + +Shared scripts: +``` +.claude/skills/dld-common/scripts/update-status.sh +.claude/skills/dld-common/scripts/regenerate-index.sh +``` + +## Prerequisites + +Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop. + +## Read project context + +This skill is typically invoked mid-session after `/dld-plan`, `/dld-decide`, or during `/dld-implement`, so the project context and decision content are likely already in your conversation context. Only read these if you don't already have the information: + +1. `dld.config.yaml` — project structure (flat vs namespaced, decisions directory) +2. The target decision file(s) — decision records (`DL-*.md`) live in the `records/` subdirectory under the decisions directory + +## Step 1: Identify the decision(s) + +The user may specify decision IDs explicitly (e.g., `/dld-adjust DL-005`), but often they won't — this skill is typically used right after `/dld-plan`, `/dld-decide`, or during `/dld-implement`, so the decisions are already part of the current conversation context. + +- **Explicit IDs provided** — use those directly. +- **No IDs provided** — infer which decision(s) the user is referring to from the conversation context. If decisions were recently created or discussed in this session, assume those are the target. If it's still ambiguous, ask using `AskUserQuestion`. + +Find and read each decision file. If a decision ID is not found, report the error and continue with any remaining valid IDs. + +## Step 2: Determine if confirmation is needed + +For each decision, check whether editing requires user confirmation: + +### Proposed decisions (`status: proposed`) + +Edit freely. No confirmation needed — proposed decisions are mutable by convention. + +### Accepted decisions (`status: accepted`) + +Check if the decision file has been committed and pushed to the remote: + +```bash +# Get the last commit hash for the decision file +LAST_COMMIT=$(git log --format=%H -1 -- ) + +# Check if that commit exists on any remote branch +git branch -r --contains "$LAST_COMMIT" 2>/dev/null +``` + +- **Not yet pushed** (commit not on any remote branch, file is uncommitted, or file is untracked) — edit freely. It is still local work-in-progress. +- **Pushed to remote** — this decision has been published. Use `AskUserQuestion` to present options: + 1. **Edit anyway** — modify the accepted decision directly (breaks immutability convention) + 2. **Supersede instead** — record a new decision via `/dld-decide` that supersedes this one + 3. **Cancel** — do nothing + +If the user chooses to supersede, direct them to `/dld-decide` and stop. If they cancel, stop. Only proceed with editing if they explicitly choose to edit anyway. + +### Deprecated or superseded decisions + +These are historical records. Ask for confirmation before editing — modifying historical decisions is unusual. + +## Step 3: Collect the adjustment request + +If the user provided the adjustment alongside the skill invocation (e.g., `/dld-adjust DL-005 remove the mention of Java records`), use that directly. + +Otherwise, ask what changes they want to make. + +Read the current decision content so you understand the full context of what you are working with. + +## Step 4: Apply the changes + +### CRITICAL — How to interpret adjustment requests + +AI agents consistently misinterpret adjustment requests. Follow these rules exactly: + +**"Remove X" means DELETE the content about X.** +Do NOT replace it with "We decided not to use X" or "We chose against X" or any other negative phrasing. Simply remove the sentences, bullet points, or paragraphs that mention X. The goal is a clean decision record that reads as if X was never discussed. + +**"Change X to Y" means REPLACE the content.** +Find where X is described and replace it with Y. Do not add explanatory text about the change. + +**"Add X" means INSERT new content.** +Add the new content in the appropriate section. Do not add meta-commentary about it being an addition. + +**General principle:** The decision record should always read as a clean, coherent document. Never add editorial notes like "Updated on...", "Previously we...", "This was changed from...", or "We decided against...". The record captures the current state of the decision, not a changelog of edits. + +**Examples of WRONG vs RIGHT:** + +User says: *"Remove the mention of Java records from DL-005"* + +- WRONG: Replacing "We will use Java records for DTOs" with "We decided not to use Java records for DTOs" +- RIGHT: Deleting the sentence "We will use Java records for DTOs" entirely (and any related sentences about Java records) + +User says: *"Change the retry count from 3 to 5"* + +- WRONG: Adding "Originally 3 retries, changed to 5 retries because..." +- RIGHT: Replacing "3 retries" with "5 retries" wherever it appears in the decision + +User says: *"Remove the part about caching"* + +- WRONG: "We considered caching but decided it is not relevant to this decision" +- RIGHT: Delete all sentences and paragraphs about caching. Adjust surrounding text so the document flows naturally. + +### Applying edits + +1. Read the full decision file +2. Apply the requested changes to the markdown body (and frontmatter fields like title or tags if affected) +3. Write the updated file +4. Show the user a brief summary of what changed + +If multiple decisions are being adjusted, process them one at a time. + +## Step 5: Regenerate INDEX.md + +If any decision titles or metadata changed: + +```bash +bash .claude/skills/dld-common/scripts/regenerate-index.sh +``` + +## Step 6: Suggest next steps + +> Adjusted **DL-NNN**: [brief description of what changed] +> +> Next steps: +> - `/dld-lookup DL-NNN` — review the updated decision +> - `/dld-implement DL-NNN` — implement if the decision is proposed +> - `/dld-snapshot` — regenerate overview docs to reflect the update diff --git a/.claude/skills/dld-decide/SKILL.md b/.claude/skills/dld-decide/SKILL.md index 39aca94..4eecaea 100644 --- a/.claude/skills/dld-decide/SKILL.md +++ b/.claude/skills/dld-decide/SKILL.md @@ -119,5 +119,6 @@ bash .claude/skills/dld-common/scripts/regenerate-index.sh > Decision **DL-NNN** recorded as `proposed`. > > Next steps: +> - `/dld-adjust` — refine the decision before implementing > - `/dld-implement DL-NNN` — implement this decision > - `/dld-decide` — record another decision diff --git a/.claude/skills/dld-plan/SKILL.md b/.claude/skills/dld-plan/SKILL.md index 9b45a10..5e5dedf 100644 --- a/.claude/skills/dld-plan/SKILL.md +++ b/.claude/skills/dld-plan/SKILL.md @@ -135,5 +135,6 @@ bash .claude/skills/dld-common/scripts/regenerate-index.sh > | DL-012 | Idempotency key format | proposed | > > Next steps: +> - `/dld-adjust` — refine any decisions before implementing > - `/dld-implement` — implement all proposed decisions (or `/dld-implement DL-NNN` for a specific one) > - `/dld-lookup tag:` — review all decisions in this group diff --git a/README.md b/README.md index cf1ef9d..45acefb 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Use `/dld-plan` to break it down into decisions, then implement: ``` /dld-init # Bootstrap DLD in your repo (run once) /dld-plan # Break it down into decisions interactively +/dld-adjust DL-001 # Refine decisions if details change before implementing /dld-implement DL-001 # Implement each decision (or batch related ones) /dld-snapshot # Generate overview docs from the decision log ``` @@ -120,6 +121,7 @@ DLD is designed for long-lived codebases where decisions accumulate, original au | `/dld-decide` | Record a single decision interactively | | `/dld-plan` | Break down a feature into multiple grouped decisions | | `/dld-implement` | Implement proposed decisions — writes code, adds annotations, updates status | +| `/dld-adjust` | Adjust or update existing decisions — handles permission gating and correct intent interpretation | | `/dld-lookup` | Query decisions by ID, tag, code path, or keyword | | `/dld-status` | Overview of the decision log — counts, recent decisions, run tracking | | `/dld-audit` | Scan for drift between decisions and code | diff --git a/rules/dld-workflow.md b/rules/dld-workflow.md index e9e4674..a8c340a 100644 --- a/rules/dld-workflow.md +++ b/rules/dld-workflow.md @@ -14,4 +14,5 @@ This project uses Decision-Linked Development. Decision records (DL-*.md) live i - Use `/dld-audit` to scan for drift between decisions and code - Use `/dld-snapshot` to regenerate SNAPSHOT.md and OVERVIEW.md from the decision log - Use `/dld-status` for a quick overview of the decision log state +- Use `/dld-adjust` to adjust or update existing decisions - Use `/dld-retrofit` to generate decisions from an existing codebase diff --git a/skills/dld-adjust/SKILL.md b/skills/dld-adjust/SKILL.md new file mode 100644 index 0000000..16c3425 --- /dev/null +++ b/skills/dld-adjust/SKILL.md @@ -0,0 +1,141 @@ +--- +name: dld-adjust +description: Adjust or update existing decision records. Handles permission gating for accepted decisions and correctly interprets adjustment requests. +compatibility: Requires bash and git. Scripts use BASH_SOURCE for path resolution. +--- + +# /dld-adjust — Adjust a Decision + +You are helping the developer adjust one or more existing decision records. Your job is to apply their requested changes accurately and minimally. + +## Interaction style + +Use the `AskUserQuestion` tool for all questions and prompts. This provides a structured input experience for the user. + +## Script Paths + +Shared scripts: +``` +../dld-common/scripts/update-status.sh +../dld-common/scripts/regenerate-index.sh +``` + +## Prerequisites + +Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop. + +## Read project context + +This skill is typically invoked mid-session after `/dld-plan`, `/dld-decide`, or during `/dld-implement`, so the project context and decision content are likely already in your conversation context. Only read these if you don't already have the information: + +1. `dld.config.yaml` — project structure (flat vs namespaced, decisions directory) +2. The target decision file(s) — decision records (`DL-*.md`) live in the `records/` subdirectory under the decisions directory + +## Step 1: Identify the decision(s) + +The user may specify decision IDs explicitly (e.g., `/dld-adjust DL-005`), but often they won't — this skill is typically used right after `/dld-plan`, `/dld-decide`, or during `/dld-implement`, so the decisions are already part of the current conversation context. + +- **Explicit IDs provided** — use those directly. +- **No IDs provided** — infer which decision(s) the user is referring to from the conversation context. If decisions were recently created or discussed in this session, assume those are the target. If it's still ambiguous, ask using `AskUserQuestion`. + +Find and read each decision file. If a decision ID is not found, report the error and continue with any remaining valid IDs. + +## Step 2: Determine if confirmation is needed + +For each decision, check whether editing requires user confirmation: + +### Proposed decisions (`status: proposed`) + +Edit freely. No confirmation needed — proposed decisions are mutable by convention. + +### Accepted decisions (`status: accepted`) + +Check if the decision file has been committed and pushed to the remote: + +```bash +# Get the last commit hash for the decision file +LAST_COMMIT=$(git log --format=%H -1 -- ) + +# Check if that commit exists on any remote branch +git branch -r --contains "$LAST_COMMIT" 2>/dev/null +``` + +- **Not yet pushed** (commit not on any remote branch, file is uncommitted, or file is untracked) — edit freely. It is still local work-in-progress. +- **Pushed to remote** — this decision has been published. Use `AskUserQuestion` to present options: + 1. **Edit anyway** — modify the accepted decision directly (breaks immutability convention) + 2. **Supersede instead** — record a new decision via `/dld-decide` that supersedes this one + 3. **Cancel** — do nothing + +If the user chooses to supersede, direct them to `/dld-decide` and stop. If they cancel, stop. Only proceed with editing if they explicitly choose to edit anyway. + +### Deprecated or superseded decisions + +These are historical records. Ask for confirmation before editing — modifying historical decisions is unusual. + +## Step 3: Collect the adjustment request + +If the user provided the adjustment alongside the skill invocation (e.g., `/dld-adjust DL-005 remove the mention of Java records`), use that directly. + +Otherwise, ask what changes they want to make. + +Read the current decision content so you understand the full context of what you are working with. + +## Step 4: Apply the changes + +### CRITICAL — How to interpret adjustment requests + +AI agents consistently misinterpret adjustment requests. Follow these rules exactly: + +**"Remove X" means DELETE the content about X.** +Do NOT replace it with "We decided not to use X" or "We chose against X" or any other negative phrasing. Simply remove the sentences, bullet points, or paragraphs that mention X. The goal is a clean decision record that reads as if X was never discussed. + +**"Change X to Y" means REPLACE the content.** +Find where X is described and replace it with Y. Do not add explanatory text about the change. + +**"Add X" means INSERT new content.** +Add the new content in the appropriate section. Do not add meta-commentary about it being an addition. + +**General principle:** The decision record should always read as a clean, coherent document. Never add editorial notes like "Updated on...", "Previously we...", "This was changed from...", or "We decided against...". The record captures the current state of the decision, not a changelog of edits. + +**Examples of WRONG vs RIGHT:** + +User says: *"Remove the mention of Java records from DL-005"* + +- WRONG: Replacing "We will use Java records for DTOs" with "We decided not to use Java records for DTOs" +- RIGHT: Deleting the sentence "We will use Java records for DTOs" entirely (and any related sentences about Java records) + +User says: *"Change the retry count from 3 to 5"* + +- WRONG: Adding "Originally 3 retries, changed to 5 retries because..." +- RIGHT: Replacing "3 retries" with "5 retries" wherever it appears in the decision + +User says: *"Remove the part about caching"* + +- WRONG: "We considered caching but decided it is not relevant to this decision" +- RIGHT: Delete all sentences and paragraphs about caching. Adjust surrounding text so the document flows naturally. + +### Applying edits + +1. Read the full decision file +2. Apply the requested changes to the markdown body (and frontmatter fields like title or tags if affected) +3. Write the updated file +4. Show the user a brief summary of what changed + +If multiple decisions are being adjusted, process them one at a time. + +## Step 5: Regenerate INDEX.md + +If any decision titles or metadata changed: + +```bash +bash ../dld-common/scripts/regenerate-index.sh +``` + +## Step 6: Suggest next steps + +> Adjusted **DL-NNN**: [brief description of what changed] +> +> Next steps: +> - `/dld-lookup DL-NNN` — review the updated decision +> - `/dld-implement DL-NNN` — implement if the decision is proposed +> - `/dld-snapshot` — regenerate overview docs to reflect the update diff --git a/skills/dld-decide/SKILL.md b/skills/dld-decide/SKILL.md index b660f6d..63ad899 100644 --- a/skills/dld-decide/SKILL.md +++ b/skills/dld-decide/SKILL.md @@ -119,5 +119,6 @@ bash ../dld-common/scripts/regenerate-index.sh > Decision **DL-NNN** recorded as `proposed`. > > Next steps: +> - `/dld-adjust` — refine the decision before implementing > - `/dld-implement DL-NNN` — implement this decision > - `/dld-decide` — record another decision diff --git a/skills/dld-plan/SKILL.md b/skills/dld-plan/SKILL.md index 48f6ebb..6292717 100644 --- a/skills/dld-plan/SKILL.md +++ b/skills/dld-plan/SKILL.md @@ -135,5 +135,6 @@ bash ../dld-common/scripts/regenerate-index.sh > | DL-012 | Idempotency key format | proposed | > > Next steps: +> - `/dld-adjust` — refine any decisions before implementing > - `/dld-implement` — implement all proposed decisions (or `/dld-implement DL-NNN` for a specific one) > - `/dld-lookup tag:` — review all decisions in this group diff --git a/tile.json b/tile.json index 886718f..8bf8634 100644 --- a/tile.json +++ b/tile.json @@ -41,6 +41,9 @@ }, "dld-retrofit": { "path": "skills/dld-retrofit/SKILL.md" + }, + "dld-adjust": { + "path": "skills/dld-adjust/SKILL.md" } } }