@thedecipherist/mdd 1.5.4 → 1.5.6

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.
@@ -101,6 +101,40 @@ Manifest: .mdd/jobs/audit-<date>/MANIFEST.md
101
101
  - Clear context after every single file — no exceptions.
102
102
  - On every startup (including post-clear): follow STARTUP SEQUENCE below.
103
103
 
104
+ ## Standard Audit Criteria (apply to every file)
105
+
106
+ ### P1 Critical
107
+ - `eval()` used anywhere — only `vm.runInNewContext` is permitted
108
+ - Cloud metadata endpoints (169.254.169.254, 169.254.170.2, fd00:ec2::254, metadata.google.internal) reachable without block
109
+ - Secrets, API keys, or credentials hardcoded in source
110
+ - Security enforcement function exists in a dependency but is NOT called at this call site (check dependency docs for `integration_contracts`)
111
+ - "Immutable" rule arrays exported as plain mutable arrays — not `Object.freeze()` + `readonly`
112
+ - Untrusted MCP/API/CLI input used without validation or sanitization
113
+ - Data cached or stored without masking applied first
114
+ - `satisfies_contracts` entry is `status: pending` — contract was acknowledged but never wired
115
+
116
+ ### P2 High
117
+ - TypeScript `any` used — must use `unknown` with narrowing
118
+ - Missing `.js` extension on ESM imports in src/ files (NodeNext resolution)
119
+ - `console.log` in library code (should use logger)
120
+ - File exceeds 300 lines
121
+ - Function exceeds 50 lines
122
+ - Feature's `source_files` lists a file that does not exist on disk
123
+ - Transformation/substitution function handles some but not all AST/domain types (silent fallthrough for unhandled types)
124
+ - MCP-exposed function accepts untrusted params with no explicit validation
125
+
126
+ ### P3 Medium
127
+ - TypeScript strict mode not enabled in tsconfig
128
+ - Missing error handling at system/user-input boundaries
129
+ - Feature has `depends_on` entries with `integration_contracts` but `satisfies_contracts` is empty
130
+ - Security module's `integration_contracts` specifies a caller that has no `satisfies_contracts` entry
131
+ - Missing test cases for documented business rules
132
+
133
+ ### P4 Low
134
+ - Code style inconsistencies
135
+ - Dead code / unused imports
136
+ - Minor spec divergences
137
+
104
138
  ## Startup Sequence
105
139
  1. Read this config file
106
140
  2. Read shard-<N>.md to know your file list
@@ -185,6 +219,17 @@ Read ONLY `audits/notes-<date>.md` (NOT source code again). Produce `audits/repo
185
219
  3. Findings by severity (P1 Critical / P2 High / P3 Medium / P4 Low)
186
220
  4. Test coverage summary
187
221
  5. Fix plan with effort estimates and affected files per finding
222
+ 6. Root Cause Analysis — for each cluster of findings, explain WHY the code writer made the mistake (not just what is wrong). Common root causes: "security module built in isolation without integration contracts," "immutability described in spec but not enforced at the code level," "MCP tool written without a threat model," "node type added after transformation function was written."
223
+ 7. Prevention Rules — derive concrete, actionable rules that would have prevented each finding cluster. Format: "When implementing X, always Y. Never Z. Reasoning: [which finding caused this]." These rules are proposed for addition to CLAUDE.md at the end of the audit.
224
+
225
+ **Integration contract cross-check (in addition to per-file analysis):**
226
+ After per-file analysis is complete, read all `.mdd/docs/*.md` and:
227
+ - For each feature with `integration_contracts` entries: verify that every listed `caller_feature` has a matching `satisfies_contracts` entry referencing back to this feature
228
+ - For each feature with `satisfies_contracts` entries still `status: pending`: flag as P1 — the wiring was documented but never implemented
229
+ - For each feature doc where `satisfies_contracts` is empty but `depends_on` includes a feature with `integration_contracts`: flag as P2 — missing acknowledgment of mandatory contracts
230
+ - For each source file flagged `[!]` where the finding is "security function not called at call site": cross-reference against `integration_contracts` of dependencies — these are contract violations, not just code quality issues
231
+
232
+ Report these as a separate "Contract Violations" section before the standard findings table.
188
233
 
189
234
  **Once `audits/report-<date>.md` is confirmed written and non-empty:**
190
235
  1. Copy `jobs/audit-<date>/MANIFEST.md` → `audits/MANIFEST-<date>.md`
@@ -193,6 +193,8 @@ phase: <last completed phase name, or "all" when fully built>
193
193
  mdd_version: <read from mdd.md frontmatter mdd_version field>
194
194
  tags: [<4-8 domain-concept keywords — systems touched, technology, feature names. NOT file paths>]
195
195
  path: <Area/Section>
196
+ integration_contracts: []
197
+ satisfies_contracts: []
196
198
  known_issues: []
197
199
  ---
198
200
 
@@ -226,6 +228,14 @@ known_issues: []
226
228
 
227
229
  <What this feature requires from other features. List by documentation ID.>
228
230
 
231
+ ## Security
232
+
233
+ <Only required when this feature: provides a security enforcement function, accepts external/user/MCP input, stores or caches data, spawns processes, or makes network calls. Leave empty otherwise.>
234
+
235
+ <For security enforcement features: list integration_contracts — which call sites must invoke which functions.>
236
+ <For input-accepting features: document trusted vs untrusted input boundary, sanitization requirements, and what a malicious caller could attempt.>
237
+ <For caching features: document what masking or sanitization runs before storage.>
238
+
229
239
  ## Known Issues
230
240
 
231
241
  <Empty for new features. Will be populated by future audits.>
@@ -235,6 +245,50 @@ known_issues: []
235
245
 
236
246
  **Always set `last_synced` to today's date** when writing or updating a feature doc. This is what SCAN MODE uses to detect drift. Set `status: draft` for new docs; update to `in_progress` when implementation begins, `complete` when Phase 7 is done.
237
247
 
248
+ #### Phase 3a — Integration Contract Resolution (mandatory when `depends_on` is non-empty)
249
+
250
+ After writing the feature doc, resolve integration obligations from dependencies:
251
+
252
+ 1. For each feature ID in `depends_on`, read its `.mdd/docs/*.md` file
253
+ 2. Check whether it has `integration_contracts` entries
254
+ 3. For each contract that applies to the current feature, add it to `satisfies_contracts` as a **placeholder** showing what must be wired:
255
+
256
+ ```yaml
257
+ satisfies_contracts:
258
+ - from: <dependency-feature-id>
259
+ function: <function-name>(<args>)
260
+ when: <condition — e.g. "before any file read in executeInclude">
261
+ status: pending ← change to "verified: <file>:<line>" during Phase 6
262
+ ```
263
+
264
+ **Leaving `satisfies_contracts` empty when a dependency has mandatory `integration_contracts` is a build error.** Do not proceed past Phase 3a until all applicable contracts are acknowledged.
265
+
266
+ **Cross-cutting concerns that always require contract resolution:**
267
+ - Any dependency tagged with `security`, `auth`, `masking`, `filesystem`, `audit`, `immutable` — its contracts are always mandatory
268
+ - Any dependency that provides a "check before X" or "enforce Y" function — that function must be in your `satisfies_contracts`
269
+
270
+ During Phase 6 implementation, update each `satisfies_contracts` entry from `status: pending` to `verified: <file>:<line>` as each call site is wired. Phase 7c will verify all entries are `verified` before marking the feature complete.
271
+
272
+ #### Phase 3b — Special Case Rules
273
+
274
+ These rules apply regardless of what the feature doc says. They are not optional.
275
+
276
+ **Immutability rule:** Any spec language describing values as "immutable," "cannot be overridden," "always enforced," or "built-in" requires both:
277
+ - `readonly string[]` (or `as const`) TypeScript typing
278
+ - `Object.freeze()` applied at definition
279
+
280
+ Using a plain `const` array is not sufficient and will fail audit.
281
+
282
+ **MCP and external-caller threat model:** Any feature that exposes functions to MCP clients, CLI users, API callers, or any untrusted external party must include a Security section in its doc that explicitly:
283
+ - Lists which inputs are untrusted
284
+ - States what a malicious caller could send
285
+ - Specifies validation/sanitization required before use
286
+ - States what the function is NOT permitted to expose (e.g., full `process.env`, raw credentials, unrestricted filesystem paths)
287
+
288
+ **Node substitution completeness rule:** Any function that transforms, substitutes, or dispatches across AST node types must handle ALL node types defined in `types.ts` — either explicitly or with a documented explicit-skip decision. An unhandled node type that silently falls through is a bug, not a design choice.
289
+
290
+ **Existence gate for source_files:** When marking `status: complete`, all files listed in `source_files` must exist on disk. Missing files block completion. Add missing files to `known_issues` with a TODO, or implement them before closing the feature.
291
+
238
292
  **Determine the `path` field** before writing the doc. Read the `path` values of all existing docs in `.mdd/docs/` to understand established product vocabulary and category names. Then ask: "What would a user navigate to in order to reach this feature?" — answer in their mental model of the product, not the code structure. Use 1–3 segments, Title Case, product vocabulary (e.g. `Auth/Login`, `E-commerce/Cart`, `Dashboard/Analytics`). Siblings must use identical parent spelling — if `Auth/Login` exists, use `Auth` not `Authentication`. If you can infer the path from context with confidence, set it and show the user. If genuinely ambiguous (feature could belong in 2+ places), ask: "Where does this feature live in the product? (e.g. `Auth/Login` or `Dashboard/Reports`)"
239
293
 
240
294
  **After writing the feature doc**, trigger the `.mdd/.startup.md` rebuild (same logic as in Status Mode — rebuild auto-generated zone, preserve Notes zone) so the Features list stays current.
@@ -604,7 +658,15 @@ where the agent patches the wrong thing because it accepted an external excuse t
604
658
 
605
659
  **If integration verified:**
606
660
 
607
- 1. **Update the feature doc frontmatter** — write these fields now, before displaying the signal:
661
+ 1. **Contract verification gate** — before marking complete, check the feature doc's `satisfies_contracts`:
662
+ - Any entry still `status: pending` means the integration was never wired
663
+ - For each pending entry: locate the call site in the implementation, verify it exists, update to `verified: <file>:<line>`
664
+ - If the call site is missing: implement it now (do not mark complete without it)
665
+ - **A feature with any `pending` contract cannot be marked `status: complete`**
666
+
667
+ Also check that all files in `source_files` exist on disk. Any missing file must be implemented or moved to `known_issues` with explicit documentation of why it was deferred.
668
+
669
+ 2. **Update the feature doc frontmatter** — write these fields now, before displaying the signal:
608
670
  - `status: complete`
609
671
  - `phase: all`
610
672
  - `last_synced: <today>`
@@ -8,6 +8,21 @@ Reads one or more large spec or prompt documents — the kind produced by extend
8
8
 
9
9
  ### Phase IS1 — Read Spec Files
10
10
 
11
+ **Stale job detection (runs first):** Check `.mdd/jobs/` for any existing `import-*/` folder.
12
+ - If found: read its `MANIFEST.md` and count written vs total files. Present to user:
13
+ ```
14
+ Found interrupted import job from <date>.
15
+ MANIFEST shows <done>/<total> files written.
16
+ Written: <list of [x] paths>
17
+ Remaining: <list of [ ] paths>
18
+
19
+ [R] Resume — skip already-written files, continue from where it left off
20
+ [D] Discard — delete job, start the full import from scratch
21
+ ```
22
+ - **Resume:** skip IS1–IS3, go directly to IS4 writing only the `[ ]` entries. IS5 runs normally after.
23
+ - **Discard:** delete the `import-<date>/` folder, proceed normally.
24
+ - If no stale job: proceed normally.
25
+
11
26
  Parse file path(s) from the arguments following `import-spec`. Multiple files may be space-separated or specified as a glob.
12
27
 
13
28
  For each file path:
@@ -316,6 +331,31 @@ Is the build order correct? Does each wave's demo-state make sense?
316
331
 
317
332
  **Do not proceed to IS4 until the user explicitly approves.**
318
333
 
334
+ **After approval — create the job folder and MANIFEST before writing any file:**
335
+
336
+ Create `.mdd/jobs/import-<YYYY-MM-DD>/MANIFEST.md`:
337
+
338
+ ```markdown
339
+ # Import Spec Job Manifest
340
+ # Job: import-<YYYY-MM-DD>
341
+ # Source: <filename(s)>
342
+ # Started: <ISO timestamp>
343
+ # Files: <N total>
344
+ # Status: IN PROGRESS
345
+ #
346
+ # States: [ ] pending [~] writing [x] written [!] error
347
+
348
+ ## Files to create
349
+ [ ] .mdd/initiatives/<slug>.md
350
+ [ ] .mdd/waves/<slug>-wave-1.md
351
+ [ ] .mdd/waves/<slug>-wave-2.md
352
+ [ ] .mdd/docs/01-<slug>.md
353
+ [ ] .mdd/docs/02-<slug>.md
354
+ ...
355
+ ```
356
+
357
+ List every file that will be written in the order it will be written. Nothing proceeds until this file exists on disk.
358
+
319
359
  ---
320
360
 
321
361
  ### Phase IS4 — Write Files
@@ -518,6 +558,8 @@ known_issues: []
518
558
  3. Tags: 4–8 domain-concept keywords. NOT file paths or spec section names.
519
559
  4. `depends_on`: populate from the build order analysis. COMPONENT docs list the SPEC docs they implement. SPEC docs list other SPECs they depend on (e.g. the expression system spec is depended on by the filter spec).
520
560
 
561
+ **For every file written:** mark it `[~]` in MANIFEST before writing, then `[x]` immediately after. If writing fails, mark `[!]` with a one-line error note. This ensures the MANIFEST is always an accurate snapshot of what exists on disk — a resume after interruption will never re-write a file that was already successfully written.
562
+
521
563
  **Progress report as you write:**
522
564
  ```
523
565
  Writing files...
@@ -550,6 +592,8 @@ Read all `.mdd/docs/*.md` (excluding `archive/`) — frontmatter only (id, title
550
592
  - **Warnings:** broken `depends_on` refs (target doesn't exist), circular dependencies, docs missing `path`.
551
593
  - **Write** `.mdd/connections.md` with YAML frontmatter (`generated: <today>`, `doc_count: <N>`, `connection_count: <N>`, `overlap_count: <N>`) and four sections: Path Tree, Dependency Graph (Mermaid), Source File Overlap, Warnings.
552
594
 
595
+ **Clean up job folder:** Delete `.mdd/jobs/import-<date>/` entirely — the written files are the authoritative record.
596
+
553
597
  Then report:
554
598
 
555
599
  ```
@@ -569,6 +613,7 @@ Structure:
569
613
 
570
614
  Startup: .mdd/.startup.md rebuilt
571
615
  Connections: .mdd/connections.md updated
616
+ Job: .mdd/jobs/import-<date>/ deleted
572
617
 
573
618
  Next steps:
574
619
  /mdd plan-execute <slug>-wave-1 — start building Wave 1
@@ -210,14 +210,28 @@ DIRTY=$(git status --porcelain)
210
210
  Follow the same (a)/(b)/(c) logic as mdd-build.md Phase 0.
211
211
  - **Never proceed on main.** This is a hard block regardless of clean/dirty state.
212
212
 
213
- 1. Parse `<wave-slug>` — hard stop *"Wave does not exist"* if `waves/<wave-slug>.md` not found.
213
+ 1. Parse `<wave-slug>` — hard stop *"Wave does not exist"* if `.mdd/waves/<wave-slug>.md` not found.
214
214
  2. Read the wave doc.
215
215
  3. Derive and read the parent initiative — hard stop if not found.
216
216
  4. **Hash check:** verify both initiative and wave file hashes. Hard stop on any mismatch: *"File has been manually edited since last sync. Run `/mdd plan-sync` first."*
217
217
  5. **Depends-on gate:** if wave's `depends_on` is not `none`, verify that wave is `complete`. Hard stop if not.
218
- 6. **Feature ordering check (Gap 4):** build dependency graph of features within the wave. If any ordering violation found → hard stop, explain exact conflict, offer auto-reorder.
219
-
220
- ### Phase PE2 Interaction mode
218
+ 6. **Feature ordering check:** build dependency graph of features within the wave. If any ordering violation found → hard stop, explain exact conflict, offer auto-reorder.
219
+ 7. **Stale job detection:** Check `.mdd/jobs/` for any existing `wave-<wave-slug>/` folder.
220
+ - If found: read its `MANIFEST.md` and count entries by state (`[ ]`, `[~]`, `[x]`, `[!]`). Present to user:
221
+ ```
222
+ Found interrupted wave job from <date>.
223
+ MANIFEST shows <done>/<total> features complete.
224
+ Features done: <list of [x] slugs>
225
+ Remaining: <list of [ ] and [~] slugs>
226
+
227
+ [R] Resume — continue from where it left off
228
+ [D] Discard — delete job and start wave from scratch
229
+ ```
230
+ - **Resume:** skip PE2, skip to PE3 starting from the first `[ ]` or `[~]` entry. Features marked `[x]` are already complete — do not re-run them.
231
+ - **Discard:** delete the `wave-<wave-slug>/` folder, proceed to PE2 normally.
232
+ - If no stale job exists: proceed to PE2 normally.
233
+
234
+ ### Phase PE2 — Interaction mode + Job Setup
221
235
 
222
236
  Ask:
223
237
  ```
@@ -230,24 +244,51 @@ How do you want to run this wave?
230
244
 
231
245
  **Interactive:** full Phase 2 gate, Phase 5 plan confirmation, green gate iteration prompts on every feature.
232
246
 
247
+ **After the interaction mode is chosen — create the job folder and MANIFEST (nothing proceeds until this exists on disk):**
248
+
249
+ Create `.mdd/jobs/wave-<wave-slug>/MANIFEST.md`:
250
+
251
+ ```markdown
252
+ # Wave Job Manifest
253
+ # Job: wave-<wave-slug>
254
+ # Wave: .mdd/waves/<wave-slug>.md
255
+ # Initiative: <initiative-slug>
256
+ # Started: <ISO timestamp>
257
+ # Mode: <automated | interactive>
258
+ # Features: <N>
259
+ # Status: IN PROGRESS
260
+ #
261
+ # States: [ ] planned [~] in_progress [x] complete [!] error
262
+
263
+ ## Features (in build order)
264
+ [ ] <feature-slug-1> .mdd/docs/<NN>-<slug>.md
265
+ [ ] <feature-slug-2> .mdd/docs/<NN>-<slug>.md
266
+ [ ] <feature-slug-3> .mdd/docs/<NN>-<slug>.md
267
+ ```
268
+
269
+ List every feature from the wave's Features table in order. Features already marked `complete` in the wave doc get `[x]` from the start.
270
+
233
271
  ### Phase PE3 — Execute features
234
272
 
235
273
  For each feature in the wave's feature table, in dependency order, skipping `complete` features:
236
274
 
237
275
  1. Tell user: *"Starting Feature N: <feature-slug>"*
238
- 2. Flip `wave_status: active` for this feature in the wave doc immediately.
239
- 3. Update the wave doc's `Doc` column with the feature doc path (once created in MDD Phase 3).
240
- 4. Run full MDD Build Mode (Phases 1–7) for the feature, at the chosen interaction level.
276
+ 2. Mark the feature `[~]` in `MANIFEST.md` immediately (before any other work).
277
+ 3. Flip `wave_status: active` for this feature in the wave doc immediately.
278
+ 4. Update the wave doc's `Doc` column with the feature doc path (once created in MDD Phase 3).
279
+ 5. Run full MDD Build Mode (Phases 1–7) for the feature, at the chosen interaction level.
241
280
  - Feature doc is auto-numbered from `.mdd/docs/` and gets `initiative`, `wave`, `wave_status` fields added.
242
- 5. After Phase 7 verify: flip `wave_status: complete` in wave doc AND confirm `status: complete` is written to the feature doc frontmatter (Phase 7c should have done this — verify it, write it if missing).
243
- 6. Ask: *"Feature N done ✓. Start Feature N+1? (yes / pause here)"*
281
+ 6. After Phase 7 verify: flip `wave_status: complete` in wave doc AND confirm `status: complete` is written to the feature doc frontmatter (Phase 7c should have done this — verify it, write it if missing).
282
+ 7. Mark the feature `[x]` in `MANIFEST.md`. If an error occurred that prevented completion, mark `[!]` with a one-line note.
283
+ 8. Ask: *"Feature N done ✓. Start Feature N+1? (yes / pause here)"*
244
284
 
245
- **Resume behaviour (Gap 2):** if re-run on a partially complete wave, read each feature's `wave_status`. Skip `complete`. Resume at first `active` or `planned`. If `active` but no doc exists restart from Phase 1.
285
+ **Resume behaviour:** if re-run on a partially complete wave, stale job detection in PE1 handles resume. MANIFEST is the authoritative progress record it is always written before and after each feature so an interrupted session can pick up at the exact right point.
246
286
 
247
287
  ### Phase PE4 — Wave completion
248
288
 
249
289
  When all features are `complete`:
250
- 1. Show the demo-state: *"Wave complete. Demo-state: '<demo-state>'. Have you verified this?"*
290
+ 1. Update `MANIFEST.md` set `# Status: COMPLETE` in the header.
291
+ 2. Show the demo-state: *"Wave complete. Demo-state: '<demo-state>'. Have you verified this?"*
251
292
  2. User confirms → flip wave `status: complete` in both `waves/<slug>.md` AND the waves table in `initiatives/<slug>.md`.
252
293
  3. **Cascade status to feature docs** — for every feature listed in this wave, read its `.mdd/docs/<NN>-<slug>.md` and check `status:`. For any doc that is NOT already `complete` or `deprecated`, write:
253
294
  - `status: complete`
@@ -272,6 +313,8 @@ Read all `.mdd/docs/*.md` (excluding `archive/`) — frontmatter only (id, title
272
313
  - **Warnings:** broken `depends_on` refs (target doesn't exist), circular dependencies, docs missing `path`.
273
314
  - **Write** `.mdd/connections.md` with YAML frontmatter (`generated: <today>`, `doc_count: <N>`, `connection_count: <N>`, `overlap_count: <N>`) and four sections: Path Tree, Dependency Graph (Mermaid), Source File Overlap, Warnings.
274
315
 
316
+ **Clean up job folder:** Delete `.mdd/jobs/wave-<wave-slug>/` entirely. The wave doc and feature docs are the authoritative completion record — the job folder is ephemeral tracking only.
317
+
275
318
  ---
276
319
 
277
320
  ## PLAN-SYNC MODE — `/mdd plan-sync`
package/commands/mdd.md CHANGED
@@ -3,7 +3,7 @@ description: "MDD workflow — Document → Audit → Fix → Verify. Build feat
3
3
  scope: project
4
4
  argument-hint: "<feature-description> or audit [section]"
5
5
  allowed-tools: Read, Write, Edit, Grep, Glob, Bash, AskUserQuestion, Agent
6
- mdd_version: 9
6
+ mdd_version: 10
7
7
  ---
8
8
 
9
9
  # MDD — Manual-Driven Development Workflow
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thedecipherist/mdd",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "MDD — Manual-Driven Development workflow for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {