---
name: dld-audit
description: Scan for drift between decisions and code. Finds orphaned annotations, stale references, and undocumented changes.
compatibility: Requires Node.js 22+ and git.
metadata:
  dld-kit-version: "1.0.0"
---
<!-- Generated by dld-kit from templates/skills/dld-audit/SKILL.md. Do not edit: updating the skills overwrites this file. -->

# /dld-audit — Audit Decision-Code Drift

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.

## Commands

The commands below run the `dld` CLI bundled with the dld-common skill, and need Node.js 22+. `<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`.

This skill uses: `find-annotations`, `related-decisions`, `find-missing-amends`, `update-status`, `regenerate-index`, `update-audit-state`.

## Prerequisites

Check that `dld.config.yaml` exists at the repo root. If not, tell the user to run `/dld-init` first and stop.

## Audit Steps

### 1. Collect all annotations in code

Run `find-annotations`:
```bash
node "<skill-dir>/../dld-common/scripts/dld.mjs" find-annotations
```

This outputs lines in the format `<file>:<line>:<DL-NNN>`, one per annotation occurrence. Annotations use the `annotation_prefix` from `dld.config.yaml` (`@decision` by default); the examples here show the default. On stderr it also prints `Warning: <file>:<line>: not an annotation: <text>` for text that looks like an annotation and names a decision but does not match the syntax, such as `` `@decision` ``( DL-002 ) with spaces, a lower-case `dl-003`, or two IDs in one pair of parentheses. Keep those lines for check (a2).

### 2. Collect all decision records

Read all `DL-*.md` files in the records subdirectory (`decisions/records/`). For each, note:
- The ID
- The status
- The code references listed in the frontmatter

### 3. Check for issues

Perform these drift checks:

#### a) Orphaned annotations

Annotations in code that reference non-existent decision IDs. These indicate decisions that were deleted or IDs that were mistyped.

#### a2) Malformed annotations

Every `not an annotation` warning from step 1. The code looks linked to a decision but is not, so `verify-annotations` and the other checks do not count it. Report each one with the fix: one ID per annotation, exactly `<prefix>(DL-NNN)`.

#### b) Annotations referencing non-accepted decisions

Annotations referencing decisions with status `deprecated` or `superseded`. Code is still tied to a decision that's no longer active.

#### b2) Annotations referencing amended decisions

Annotations referencing decisions that have been amended by a newer decision: `node "<skill-dir>/../dld-common/scripts/dld.mjs" related-decisions DL-NNN` prints an `amended-by` line for each. Report only amenders whose status is `accepted`; a `proposed` one is not in effect yet. 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.

#### c) Stale references in decisions

Decision records whose `references` list code paths that no longer exist in the repository. Use file existence checks.

#### d) Unreferenced code changes (if previous audit exists)

If `decisions/.dld-state.yaml` exists and has an `audit.commit_hash`, find files that:
1. Contain `@decision` annotations
2. Were modified since the last audit commit

First, verify the commit is reachable:
```bash
git cat-file -t <commit_hash> 2>/dev/null
```

If the commit is unreachable (e.g., after a rebase or shallow clone), skip this check and note it in the report:
> **Note:** Previous audit commit `<hash>` is not reachable in current history. Skipping changed-file detection. This can happen after a rebase or shallow clone.

If the commit is reachable:
```bash
git diff --name-only <commit_hash>..HEAD
```

Cross-reference this list with annotated files. Files that changed but whose associated decisions weren't updated may indicate undocumented drift.

#### e) Missing amendment relationships

Run `find-missing-amends` in every audit:

```bash
node "<skill-dir>/../dld-common/scripts/dld.mjs" find-missing-amends
```

Each line is `<source-id>:<referenced-id><TAB><tier>`: a decision whose body mentions another decision that its `supersedes` and `amends` fields don't list. By default the command only checks decisions changed since the last audit (recorded in `.dld-state.yaml`), and lists two tiers:

- `explicit`: a sentence of the source decision says it amends or supersedes the referenced one. The prose and the frontmatter disagree, so this is an issue. Read the sentence: if it is negated ("never supersedes") or is about another decision, it is not a missing relationship. Otherwise report it under **Missing Relationships** with the fix: add the ID to `amends` or `supersedes`, whichever the sentence says. The fix is applied after the report (step 5).
- `cue`: the Decision or Consequences section mentions the referenced decision in a sentence with a change word such as "replaces" or "no longer". This is advisory. List these under **Possible Missing Relationships**, with a short reading of each where it is obvious, and don't spend the audit evaluating every one in depth.

The checks are tuned for decision records written in English.

Plain mentions are not listed by default: most are citations. When the user asks for a deep audit of relationships, run `node "<skill-dir>/../dld-common/scripts/dld.mjs" find-missing-amends --all --mentions`, which checks every decision and adds a `mention` tier. `--all` alone checks every decision at the two default tiers, which suits a first audit of an existing log.

#### f) Decisions without annotations

`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.

### 4. Report findings

Present findings grouped by severity:

```
## Audit Report

### Issues Found

#### Orphaned Annotations
- `src/billing/vat.ts:42` references `DL-099` — decision does not exist

#### Malformed Annotations
- `src/billing/vat.ts:57` — two IDs in one annotation (`` `@decision` ``(DL-012, DL-015)) is not an annotation; write one annotation per ID

#### Stale References
- **DL-012** references `src/billing/old-vat.ts` — file does not exist

#### Deprecated/Superseded References
- `src/auth/login.ts:15` references `DL-003` (status: superseded by DL-012)

#### Missing Relationships
- **DL-014** says "Amends DL-009" but `amends` does not list DL-009 — add it

#### Possible Missing Relationships (advisory)
- **DL-021** → DL-015: "replaces the write path of DL-015" — may amend it

#### Amended Decisions (informational)
- `src/billing/vat.ts:42` references `DL-003` — amended by DL-012. Verify code aligns with the amendment.

#### Modified Annotated Files (since last audit)
- `src/billing/vat.ts` — modified, contains `@decision(DL-012)`. Review if decision needs updating.

### Summary
- **X** orphaned annotations
- **Y** stale references
- **W** missing relationships, **V** possible ones
- **Z** annotated files modified since last audit

### Suggested Remediation
- Fix orphaned annotation at `src/billing/vat.ts:42` — update to correct ID or remove
- Update DL-012 references — remove `src/billing/old-vat.ts`
- Review `src/billing/vat.ts` changes — consider `/dld-decide` if behavior changed
```

If no issues are found:
```
## Audit Report

No drift detected. All annotations reference valid, accepted decisions. All decision references point to existing code.
```

### 5. Apply relationship fixes

If the report lists **Missing Relationships**, ask the user with `AskUserQuestion` which fixes to apply. For each one they accept, add the ID to the source decision's `amends` or `supersedes` list in its frontmatter, which can always be changed, even on decisions already on the base branch. A new `supersedes` entry also marks the referenced decision superseded:

```bash
node "<skill-dir>/../dld-common/scripts/dld.mjs" update-status DL-NNN superseded
```

If any fix was applied, regenerate the index:

```bash
node "<skill-dir>/../dld-common/scripts/dld.mjs" regenerate-index
```

### 6. Update audit state

After the audit completes (regardless of findings):
```bash
node "<skill-dir>/../dld-common/scripts/dld.mjs" update-audit-state
```

### 7. Suggest next steps

> Audit complete. **N** issue(s) found.
>
> Next steps:
> - Fix any orphaned or stale references identified above
> - `/dld-decide` — record new decisions for undocumented changes
> - `/dld-snapshot` — regenerate the spec projection
> - `/dld-status` — view overall decision log state
