@ktpartners/dgs-platform 2.9.0 → 3.3.0

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.
Files changed (166) hide show
  1. package/CHANGELOG.md +197 -0
  2. package/README.md +34 -2
  3. package/agents/dgs-executor.md +124 -3
  4. package/agents/dgs-idea-researcher.md +447 -0
  5. package/agents/dgs-plan-checker.md +61 -3
  6. package/agents/dgs-planner.md +51 -8
  7. package/bin/install.js +44 -0
  8. package/commands/dgs/abandon-quick.md +28 -0
  9. package/commands/dgs/add-tests.md +2 -2
  10. package/commands/dgs/audit-milestone.md +4 -3
  11. package/commands/dgs/capture-principle.md +11 -11
  12. package/commands/dgs/cleanup.md +2 -2
  13. package/commands/dgs/complete-milestone.md +11 -11
  14. package/commands/dgs/complete-quick.md +28 -0
  15. package/commands/dgs/create-milestone-job.md +2 -2
  16. package/commands/dgs/debug.md +3 -3
  17. package/commands/dgs/develop-idea.md +1 -1
  18. package/commands/dgs/diff-report.md +124 -0
  19. package/commands/dgs/fast.md +3 -1
  20. package/commands/dgs/health.md +1 -1
  21. package/commands/dgs/map-codebase.md +6 -6
  22. package/commands/dgs/new-milestone.md +5 -5
  23. package/commands/dgs/new-project.md +8 -21
  24. package/commands/dgs/package-scan.md +43 -0
  25. package/commands/dgs/plan-milestone-gaps.md +1 -1
  26. package/commands/dgs/progress.md +3 -3
  27. package/commands/dgs/quick-abandon.md +8 -0
  28. package/commands/dgs/quick-complete.md +8 -0
  29. package/commands/dgs/quick.md +10 -3
  30. package/commands/dgs/research-idea.md +3 -2
  31. package/commands/dgs/research-phase.md +3 -3
  32. package/commands/dgs/switch-project.md +14 -1
  33. package/commands/dgs/write-spec.md +3 -3
  34. package/deliver-great-systems/bin/dgs-tools.cjs +401 -32
  35. package/deliver-great-systems/bin/lib/audit-tolerance.cjs +77 -0
  36. package/deliver-great-systems/bin/lib/audit-tolerance.test.cjs +101 -0
  37. package/deliver-great-systems/bin/lib/commands.cjs +626 -46
  38. package/deliver-great-systems/bin/lib/commands.test.cjs +451 -0
  39. package/deliver-great-systems/bin/lib/commit-verify.test.cjs +236 -0
  40. package/deliver-great-systems/bin/lib/config.cjs +80 -6
  41. package/deliver-great-systems/bin/lib/config.test.cjs +309 -0
  42. package/deliver-great-systems/bin/lib/context.cjs +120 -0
  43. package/deliver-great-systems/bin/lib/core.cjs +35 -14
  44. package/deliver-great-systems/bin/lib/core.test.cjs +79 -1
  45. package/deliver-great-systems/bin/lib/execution.cjs +49 -17
  46. package/deliver-great-systems/bin/lib/fast-routing.cjs +199 -0
  47. package/deliver-great-systems/bin/lib/fast-routing.test.cjs +108 -0
  48. package/deliver-great-systems/bin/lib/final-commit-precondition.test.cjs +87 -0
  49. package/deliver-great-systems/bin/lib/fixtures/package-scan/bundler-audit-gemfile.json +21 -0
  50. package/deliver-great-systems/bin/lib/fixtures/package-scan/gate-parity-expected.md +186 -0
  51. package/deliver-great-systems/bin/lib/fixtures/package-scan/gate-parity-runresult.json +235 -0
  52. package/deliver-great-systems/bin/lib/fixtures/package-scan/govulncheck-import.json +3 -0
  53. package/deliver-great-systems/bin/lib/fixtures/package-scan/npm-audit-v10.json +37 -0
  54. package/deliver-great-systems/bin/lib/fixtures/package-scan/osv-clean.json +3 -0
  55. package/deliver-great-systems/bin/lib/fixtures/package-scan/osv-vulns.json +77 -0
  56. package/deliver-great-systems/bin/lib/fixtures/package-scan/pip-audit-requirements.json +28 -0
  57. package/deliver-great-systems/bin/lib/fixtures/package-scan/snyk-lodash.json +30 -0
  58. package/deliver-great-systems/bin/lib/fixtures/package-scan/snyk-workspaces.json +55 -0
  59. package/deliver-great-systems/bin/lib/flat-migration.test.cjs +396 -0
  60. package/deliver-great-systems/bin/lib/frontmatter.cjs +1 -1
  61. package/deliver-great-systems/bin/lib/governance.cjs +211 -0
  62. package/deliver-great-systems/bin/lib/governance.test.cjs +339 -0
  63. package/deliver-great-systems/bin/lib/health-untracked-phase.test.cjs +269 -0
  64. package/deliver-great-systems/bin/lib/ideas.cjs +206 -91
  65. package/deliver-great-systems/bin/lib/ideas.test.cjs +244 -1
  66. package/deliver-great-systems/bin/lib/init.cjs +357 -61
  67. package/deliver-great-systems/bin/lib/init.test.cjs +625 -8
  68. package/deliver-great-systems/bin/lib/jobs.cjs +131 -25
  69. package/deliver-great-systems/bin/lib/jobs.test.cjs +193 -74
  70. package/deliver-great-systems/bin/lib/migration.cjs +409 -1
  71. package/deliver-great-systems/bin/lib/migration.test.cjs +158 -1
  72. package/deliver-great-systems/bin/lib/milestone.cjs +154 -31
  73. package/deliver-great-systems/bin/lib/milestone.test.cjs +203 -0
  74. package/deliver-great-systems/bin/lib/package-adapters.cjs +530 -0
  75. package/deliver-great-systems/bin/lib/package-adapters.test.cjs +618 -0
  76. package/deliver-great-systems/bin/lib/package-ecosystems.cjs +350 -0
  77. package/deliver-great-systems/bin/lib/package-ecosystems.test.cjs +348 -0
  78. package/deliver-great-systems/bin/lib/package-runner.cjs +199 -0
  79. package/deliver-great-systems/bin/lib/package-runner.test.cjs +198 -0
  80. package/deliver-great-systems/bin/lib/package-scan-provenance.cjs +56 -0
  81. package/deliver-great-systems/bin/lib/package-scan-provenance.test.cjs +103 -0
  82. package/deliver-great-systems/bin/lib/package-scan-report.cjs +1140 -0
  83. package/deliver-great-systems/bin/lib/package-scan-report.test.cjs +1963 -0
  84. package/deliver-great-systems/bin/lib/package-scan-skill.cjs +96 -0
  85. package/deliver-great-systems/bin/lib/package-scan-skill.test.cjs +136 -0
  86. package/deliver-great-systems/bin/lib/package-scan.cjs +919 -0
  87. package/deliver-great-systems/bin/lib/package-scan.test.cjs +2147 -0
  88. package/deliver-great-systems/bin/lib/phase.cjs +146 -3
  89. package/deliver-great-systems/bin/lib/phase.test.cjs +420 -0
  90. package/deliver-great-systems/bin/lib/plan-number-validity.test.cjs +48 -0
  91. package/deliver-great-systems/bin/lib/projects.cjs +65 -10
  92. package/deliver-great-systems/bin/lib/projects.test.cjs +198 -2
  93. package/deliver-great-systems/bin/lib/quick.cjs +739 -0
  94. package/deliver-great-systems/bin/lib/quick.test.cjs +730 -0
  95. package/deliver-great-systems/bin/lib/repos.cjs +37 -13
  96. package/deliver-great-systems/bin/lib/review.cjs +1821 -0
  97. package/deliver-great-systems/bin/lib/roadmap.cjs +34 -13
  98. package/deliver-great-systems/bin/lib/specs.cjs +3 -81
  99. package/deliver-great-systems/bin/lib/state-transition-gate.test.cjs +160 -0
  100. package/deliver-great-systems/bin/lib/state.cjs +147 -55
  101. package/deliver-great-systems/bin/lib/summary-frontmatter.cjs +54 -0
  102. package/deliver-great-systems/bin/lib/summary-frontmatter.test.cjs +78 -0
  103. package/deliver-great-systems/bin/lib/sweep-scope.test.cjs +263 -0
  104. package/deliver-great-systems/bin/lib/sync.cjs +75 -0
  105. package/deliver-great-systems/bin/lib/verify.cjs +198 -7
  106. package/deliver-great-systems/bin/lib/verify.test.cjs +82 -0
  107. package/deliver-great-systems/bin/lib/wave-0-template-rename.test.cjs +40 -0
  108. package/deliver-great-systems/bin/lib/worktrees.cjs +790 -0
  109. package/deliver-great-systems/bin/lib/worktrees.test.cjs +963 -0
  110. package/deliver-great-systems/references/agent-step-reliability.md +60 -0
  111. package/deliver-great-systems/references/conflict-resolution.md +4 -0
  112. package/deliver-great-systems/references/context-tiers.md +4 -0
  113. package/deliver-great-systems/references/package-scan-config.md +151 -0
  114. package/deliver-great-systems/references/questioning.md +0 -30
  115. package/deliver-great-systems/references/spec-review-loop.md +1 -2
  116. package/deliver-great-systems/references/workflow-conventions.md +29 -0
  117. package/deliver-great-systems/skills/dgs-tests/package-scan.md +44 -0
  118. package/deliver-great-systems/templates/REVIEW.md +35 -0
  119. package/deliver-great-systems/templates/VALIDATION.md +1 -1
  120. package/deliver-great-systems/templates/claude-md.md +27 -0
  121. package/deliver-great-systems/templates/package-scan-report.md +108 -0
  122. package/deliver-great-systems/templates/project.md +6 -170
  123. package/deliver-great-systems/templates/summary.md +3 -1
  124. package/deliver-great-systems/workflows/abandon-quick.md +89 -0
  125. package/deliver-great-systems/workflows/add-idea.md +3 -3
  126. package/deliver-great-systems/workflows/add-phase.md +5 -0
  127. package/deliver-great-systems/workflows/add-tests.md +14 -0
  128. package/deliver-great-systems/workflows/add-todo.md +1 -0
  129. package/deliver-great-systems/workflows/approve-spec.md +25 -4
  130. package/deliver-great-systems/workflows/audit-milestone.md +66 -10
  131. package/deliver-great-systems/workflows/audit-phase.md +15 -5
  132. package/deliver-great-systems/workflows/cancel-job.md +2 -2
  133. package/deliver-great-systems/workflows/check-todos.md +2 -3
  134. package/deliver-great-systems/workflows/codereview.md +103 -9
  135. package/deliver-great-systems/workflows/complete-milestone.md +218 -24
  136. package/deliver-great-systems/workflows/complete-quick.md +106 -0
  137. package/deliver-great-systems/workflows/consolidate-ideas.md +1 -1
  138. package/deliver-great-systems/workflows/create-milestone-job.md +4 -4
  139. package/deliver-great-systems/workflows/develop-idea.md +11 -11
  140. package/deliver-great-systems/workflows/diagnose-issues.md +14 -0
  141. package/deliver-great-systems/workflows/discuss-idea.md +1 -1
  142. package/deliver-great-systems/workflows/discuss-phase.md +3 -2
  143. package/deliver-great-systems/workflows/execute-phase.md +209 -33
  144. package/deliver-great-systems/workflows/execute-plan.md +22 -22
  145. package/deliver-great-systems/workflows/help.md +53 -20
  146. package/deliver-great-systems/workflows/import-spec.md +65 -7
  147. package/deliver-great-systems/workflows/init-product.md +45 -167
  148. package/deliver-great-systems/workflows/new-milestone.md +140 -33
  149. package/deliver-great-systems/workflows/new-project.md +60 -331
  150. package/deliver-great-systems/workflows/package-scan.md +59 -0
  151. package/deliver-great-systems/workflows/plan-phase.md +79 -1
  152. package/deliver-great-systems/workflows/progress-all.md +133 -0
  153. package/deliver-great-systems/workflows/quick-abandon.md +89 -0
  154. package/deliver-great-systems/workflows/quick-complete.md +106 -0
  155. package/deliver-great-systems/workflows/quick.md +328 -26
  156. package/deliver-great-systems/workflows/refine-spec.md +1 -1
  157. package/deliver-great-systems/workflows/research-idea.md +77 -139
  158. package/deliver-great-systems/workflows/resume-project.md +2 -2
  159. package/deliver-great-systems/workflows/run-job.md +29 -43
  160. package/deliver-great-systems/workflows/settings.md +13 -77
  161. package/deliver-great-systems/workflows/validate-phase.md +39 -1
  162. package/deliver-great-systems/workflows/verify-work.md +14 -0
  163. package/deliver-great-systems/workflows/write-spec.md +11 -13
  164. package/hooks/dist/dgs-enforce-discipline.js +196 -0
  165. package/package.json +1 -1
  166. package/scripts/build-hooks.js +1 -0
@@ -12,6 +12,14 @@ Audit Nyquist validation gaps for a completed phase. Generate missing tests. Upd
12
12
 
13
13
  ## 0. Initialize
14
14
 
15
+ **Parse `--scaffold` flag:**
16
+
17
+ ```
18
+ Parse `--scaffold` flag from PHASE_ARG (e.g., `/dgs:validate-phase 16 --scaffold`).
19
+ Set `SCAFFOLD_MODE = true` if `--scaffold` is present, `false` otherwise.
20
+ Strip `--scaffold` from PHASE_ARG before passing to `init phase-op`.
21
+ ```
22
+
15
23
  ```bash
16
24
  INIT=$(node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" init phase-op "${PHASE_ARG}")
17
25
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
@@ -83,10 +91,14 @@ Classify each requirement:
83
91
 
84
92
  Build: `{ task_id, requirement, gap_type, suggested_test_path, suggested_command }`
85
93
 
86
- No gaps skip to Step 6, set `nyquist_compliant: true`.
94
+ **Scaffold mode:** If `SCAFFOLD_MODE` is true, override all gap statuses to `PENDING_REVIEW` (not MISSING, not manual-only -- a distinct scaffold status meaning "gap identified but not yet triaged").
95
+
96
+ No gaps → skip to Step 6, set `nyquist_compliant: true`. In scaffold mode, this still produces a VALIDATION.md (with all requirements COVERED or PENDING_REVIEW).
87
97
 
88
98
  ## 4. Present Gap Plan
89
99
 
100
+ **Scaffold mode:** If `SCAFFOLD_MODE` is true, skip this step entirely (do not call AskUserQuestion). Proceed directly to Step 6.
101
+
90
102
  Call AskUserQuestion with gap table and options:
91
103
  1. "Fix all gaps" → Step 5
92
104
  2. "Skip — mark manual-only" → add to Manual-Only, Step 6
@@ -94,6 +106,8 @@ Call AskUserQuestion with gap table and options:
94
106
 
95
107
  ## 5. Spawn dgs-nyquist-auditor
96
108
 
109
+ **Scaffold mode:** If `SCAFFOLD_MODE` is true, skip this step entirely (do not spawn auditor). Proceed directly to Step 6.
110
+
97
111
  ```
98
112
  Task(
99
113
  prompt="Read ~/.claude/agents/dgs-nyquist-auditor.md for instructions.\n\n" +
@@ -114,6 +128,8 @@ Handle return:
114
128
 
115
129
  ## 6. Generate/Update VALIDATION.md
116
130
 
131
+ **Scaffold mode:** If `SCAFFOLD_MODE` is true, always use the State B (create) flow regardless of existing VALIDATION.md state. Gaps are marked as `PENDING_REVIEW` in the Per-Task Map.
132
+
117
133
  **State B (create):**
118
134
  1. Read template from `~/.claude/deliver-great-systems/templates/VALIDATION.md`
119
135
  2. Fill: frontmatter, Test Infrastructure, Per-Task Map, Manual-Only, Sign-Off
@@ -134,6 +150,15 @@ Handle return:
134
150
 
135
151
  ## 7. Commit
136
152
 
153
+ **Scaffold mode:** If `SCAFFOLD_MODE` is true:
154
+ - Only commit VALIDATION.md (no test files -- none were generated)
155
+ - Commit message: `docs(phase-${PHASE}): scaffold Nyquist validation`
156
+ - Use: `node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" commit-docs "docs(phase-${PHASE}): scaffold Nyquist validation"`
157
+ - Do NOT run the `git add {test_files}` / `git commit -m "test(..."` block
158
+ - Skip to Step 8
159
+
160
+ **Non-scaffold mode:**
161
+
137
162
  ```bash
138
163
  git add {test_files}
139
164
  git commit -m "test(phase-${PHASE}): add Nyquist validation tests"
@@ -143,6 +168,14 @@ node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" commit-docs "docs(p
143
168
 
144
169
  ## 8. Results + Routing
145
170
 
171
+ **Scaffold mode:** If `SCAFFOLD_MODE` is true, display scaffold-specific output and exit:
172
+ ```
173
+ DGS > PHASE {N} VALIDATION SCAFFOLDED
174
+ {M} requirements mapped, {K} gaps pending review.
175
+ > Fill gaps: /dgs:validate-phase {N}
176
+ ```
177
+ Display `/clear` reminder. Skip the Compliant/Partial output below.
178
+
146
179
  **Compliant:**
147
180
  ```
148
181
  DGS > PHASE {N} IS NYQUIST-COMPLIANT
@@ -174,4 +207,9 @@ Display `/clear` reminder.
174
207
  - [ ] VALIDATION.md created or updated
175
208
  - [ ] Test files committed separately
176
209
  - [ ] Results with routing presented
210
+ - [ ] --scaffold flag parsed and controls Steps 4-8
211
+ - [ ] Scaffold mode skips interactive gap plan (Step 4) and auditor (Step 5)
212
+ - [ ] Scaffold mode marks gaps as PENDING_REVIEW
213
+ - [ ] Scaffold mode commits docs-only with scaffold commit message
214
+ - [ ] Scaffold mode displays scaffold-specific results banner
177
215
  </success_criteria>
@@ -63,6 +63,20 @@ REPOS_MD=$(node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" repos li
63
63
  ```
64
64
 
65
65
  Parse JSON for the list of registered repos with paths.
66
+
67
+ **Worktree-aware code directory resolution (resolveCodeContext):**
68
+
69
+ For each registered code repo, resolve the correct working directory. When a milestone or quick worktree is active, code operations must target the worktree directory, not the main checkout.
70
+
71
+ ```javascript
72
+ // In the agent's execution context, use resolveCodeContext to determine the code directory:
73
+ const { resolveCodeContext } = require('./bin/lib/context.cjs');
74
+ const ctx = resolveCodeContext(planningRoot, repoName);
75
+ // ctx.type: 'main' | 'milestone' | 'quick'
76
+ // ctx.directory: absolute path to the correct working directory
77
+ ```
78
+
79
+ Use `ctx.directory` (or the repo's main checkout path when no worktree is active) for all file reading, test execution, and code verification operations. Do NOT hardcode repo paths from REPOS.md when a worktree may be active.
66
80
  </step>
67
81
 
68
82
  <step name="check_active_session">
@@ -103,8 +103,8 @@ Then proceed normally. Only show this tip when ALL selected ideas lack enrichmen
103
103
  **Load supporting documents** from each selected idea's `docs/` directory:
104
104
 
105
105
  For each selected idea:
106
- a. Derive the idea's docs path: `${project_root}/ideas/pending/{idea_slug}/docs/` where `idea_slug` is derived from the idea filename (strip numeric prefix and .md suffix, e.g., `005-retry-logic.md` -> `retry-logic`).
107
- Alternative path: check if ideas use a flat structure where docs are at `${project_root}/docs/ideas/pending/{slug}-*.md`.
106
+ a. Derive the idea's docs path: `${project_root}/docs/ideas/{idea_slug}/` where `idea_slug` is derived from the idea filename (strip numeric prefix and .md suffix, e.g., `005-retry-logic.md` -> `retry-logic`).
107
+ Alternative path: check for research docs at `${project_root}/docs/ideas/{slug}-*.md`.
108
108
  b. If the docs/ directory exists, list all files in it:
109
109
  ```bash
110
110
  ls "${IDEA_DOCS_DIR}/" 2>/dev/null
@@ -222,7 +222,7 @@ node ~/.claude/deliver-great-systems/bin/dgs-tools.cjs specs add-log-entry --id
222
222
 
223
223
  Commit the draft:
224
224
  ```bash
225
- node ~/.claude/deliver-great-systems/bin/dgs-tools.cjs commit "specs: draft $id from ideas $idea_ids" --push --files ${project_root}/specs/$filename
225
+ node ~/.claude/deliver-great-systems/bin/dgs-tools.cjs commit "specs: draft $id from ideas $idea_ids" --push --files specs/$filename
226
226
  ```
227
227
 
228
228
  Store `SPEC_ID` and `FILENAME` for subsequent steps.
@@ -289,7 +289,7 @@ Use AskUserQuestion: "Review the draft spec above. Type **approve** to send to r
289
289
 
290
290
  After approval, commit any changes:
291
291
  ```bash
292
- node ~/.claude/deliver-great-systems/bin/dgs-tools.cjs commit "specs: revise draft $SPEC_ID" --push --files ${project_root}/specs/$FILENAME
292
+ node ~/.claude/deliver-great-systems/bin/dgs-tools.cjs commit "specs: revise draft $SPEC_ID" --push --files specs/$FILENAME
293
293
  ```
294
294
  </step>
295
295
 
@@ -350,7 +350,7 @@ Estimated cost: ~$X.XX
350
350
  **6. Commit updated spec:**
351
351
 
352
352
  ```bash
353
- node ~/.claude/deliver-great-systems/bin/dgs-tools.cjs commit "specs: review $SPEC_ID (N rounds)" --push --files ${project_root}/specs/$FILENAME
353
+ node ~/.claude/deliver-great-systems/bin/dgs-tools.cjs commit "specs: review $SPEC_ID (N rounds)" --push --files specs/$FILENAME
354
354
  ```
355
355
  </step>
356
356
 
@@ -394,18 +394,16 @@ Source ideas moved to done: $IDEAS_MOVED
394
394
  Research documents moved to done: $RESEARCH_DOCS_MOVED (if any)
395
395
 
396
396
  What would you like to do next?
397
- 1. Create a new project from this spec -> /dgs:new-project
398
- 2. Add a milestone to an existing project -> /dgs:new-milestone
399
- 3. Nothing for now -- the spec is saved and ready when you are
397
+ 1. Start a milestone from this spec -> /dgs:new-milestone --auto $SPEC_ID
398
+ 2. Nothing for now -- the spec is saved and ready when you are
400
399
  ```
401
400
 
402
- In interactive mode, use AskUserQuestion: "Choose 1, 2, or 3 (or just press enter to defer):"
401
+ In interactive mode, use AskUserQuestion: "Choose 1 or 2 (or just press enter to defer):"
403
402
 
404
- - If **1**: Tell user "Run `/dgs:new-project` and reference spec `$FILENAME` during project creation."
405
- - If **2**: Tell user "Run `/dgs:new-milestone` and reference spec `$FILENAME` during milestone creation."
406
- - If **3** or empty/enter: Output "Spec saved. You can find it at `${project_root}/specs/$FILENAME`."
403
+ - If **1**: Tell user "Run `/dgs:new-milestone --auto $SPEC_ID` to start a milestone from this spec. If no project exists yet, run `/dgs:new-project` first to create the project holder, then `/dgs:new-milestone --auto $SPEC_ID`."
404
+ - If **2** or empty/enter: Output "Spec saved. You can find it at `specs/$FILENAME` (planning root)."
407
405
 
408
- In `--auto` mode: skip the routing question, just output the summary with the three options listed for reference.
406
+ In `--auto` mode: skip the routing question, just output the summary with the two options listed for reference.
409
407
  </step>
410
408
 
411
409
  </process>
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env node
2
+ // DGS Workflow Discipline Enforcement - PreToolUse + PostToolUse hook
3
+ //
4
+ // Ensures Edit/Write tool calls only happen inside /dgs:* commands.
5
+ // Works via a marker file that tracks active DGS command state:
6
+ //
7
+ // 1. When tool_name is "Skill" and the skill name starts with "dgs:":
8
+ // - PreToolUse: Write a marker file to /tmp/dgs-active-{session_id}.json
9
+ // - PostToolUse: Delete the marker, then check for uncommitted DGS files
10
+ //
11
+ // 2. When tool_name is "Edit" or "Write":
12
+ // - Check for marker file — if present, allow
13
+ // - Check if target path is in the allowlist — if so, allow
14
+ // - Check if cwd is a DGS planning folder — if not, allow (non-DGS project)
15
+ // - Otherwise, deny with explanation
16
+ //
17
+ // Safety net: After every /dgs:* command completes, checks for uncommitted
18
+ // DGS-managed files and auto-commits them. Logs a warning so the upstream
19
+ // workflow bug can be identified and fixed.
20
+
21
+ const fs = require('fs');
22
+ const os = require('os');
23
+ const path = require('path');
24
+ const { execSync } = require('child_process');
25
+
26
+ // Paths where Edit/Write is allowed without a DGS command
27
+ const ALLOWED_PATH_PATTERNS = [
28
+ /\.claude\/projects\/.*\/memory\//, // Auto-memory system
29
+ /\.claude\/.*\/memory\//, // Memory in any .claude subfolder
30
+ /\/tmp\//, // Temp files
31
+ ];
32
+
33
+ // DGS-managed paths that should be committed (relative to planning root)
34
+ // Used by the safety net to detect orphaned writes after a command completes
35
+ const DGS_MANAGED_PATTERNS = [
36
+ /^STATE\.md$/,
37
+ /^PROJECTS\.md$/,
38
+ /^MILESTONES\.md$/,
39
+ /^RETROSPECTIVE\.md$/,
40
+ /^CLAUDE\.md$/,
41
+ /^config\.json$/,
42
+ /^projects\/[^/]+\/STATE\.md$/,
43
+ /^projects\/[^/]+\/ROADMAP\.md$/,
44
+ /^projects\/[^/]+\/REQUIREMENTS\.md$/,
45
+ /^projects\/[^/]+\/PROJECT\.md$/,
46
+ /^projects\/[^/]+\/phases\//,
47
+ /^projects\/[^/]+\/milestones\//,
48
+ /^specs\//,
49
+ /^ideas\//,
50
+ /^todos\//,
51
+ /^jobs\//,
52
+ /^quick\//,
53
+ /^milestones\//,
54
+ /^codebase\//,
55
+ ];
56
+
57
+ function getMarkerPath(sessionId) {
58
+ return path.join(os.tmpdir(), `dgs-active-${sessionId}.json`);
59
+ }
60
+
61
+ function isDgsProject(cwd) {
62
+ try {
63
+ const configPath = path.join(cwd, 'config.json');
64
+ if (!fs.existsSync(configPath)) return false;
65
+ const content = fs.readFileSync(configPath, 'utf-8');
66
+ return content.includes('"product_name"');
67
+ } catch {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ function isAllowedPath(filePath) {
73
+ if (!filePath) return false;
74
+ return ALLOWED_PATH_PATTERNS.some(pattern => pattern.test(filePath));
75
+ }
76
+
77
+ function getTargetPath(toolName, toolInput) {
78
+ if (!toolInput) return null;
79
+ // Edit and Write both use file_path
80
+ return toolInput.file_path || null;
81
+ }
82
+
83
+ let input = '';
84
+ const stdinTimeout = setTimeout(() => process.exit(0), 3000);
85
+ process.stdin.setEncoding('utf8');
86
+ process.stdin.on('data', chunk => input += chunk);
87
+ process.stdin.on('end', () => {
88
+ clearTimeout(stdinTimeout);
89
+ try {
90
+ const data = JSON.parse(input);
91
+ const sessionId = data.session_id;
92
+ const hookEvent = data.hook_event_name;
93
+ const toolName = data.tool_name;
94
+ const toolInput = data.tool_input || {};
95
+ const cwd = data.cwd || process.cwd();
96
+
97
+ // ── PostToolUse: Clean up marker + safety net when Skill completes ──
98
+ if (hookEvent === 'PostToolUse') {
99
+ if (toolName === 'Skill') {
100
+ const skillName = toolInput.skill || toolInput.name || '';
101
+ if (skillName.startsWith('dgs:')) {
102
+ // Delete the active marker
103
+ const markerPath = getMarkerPath(sessionId);
104
+ try { fs.unlinkSync(markerPath); } catch { /* already gone */ }
105
+
106
+ // Safety net: check for uncommitted DGS-managed files
107
+ if (isDgsProject(cwd)) {
108
+ try {
109
+ const status = execSync('git status --porcelain', { cwd, encoding: 'utf-8', timeout: 5000 });
110
+ if (status.trim()) {
111
+ const lines = status.trim().split('\n');
112
+ const dirty = lines
113
+ .map(l => l.slice(3).trim()) // strip status prefix (e.g., " M ", "?? ")
114
+ .filter(f => DGS_MANAGED_PATTERNS.some(p => p.test(f)));
115
+
116
+ if (dirty.length > 0) {
117
+ // Stage and commit orphaned DGS files
118
+ for (const f of dirty) {
119
+ execSync(`git add "${f}"`, { cwd, stdio: 'pipe', timeout: 5000 });
120
+ }
121
+ const msg = `chore: auto-commit ${dirty.length} uncommitted DGS file(s) after ${skillName}`;
122
+ execSync(`git commit -m "${msg}"`, { cwd, stdio: 'pipe', timeout: 10000 });
123
+
124
+ // Warn via additionalContext so Claude sees it
125
+ const result = {
126
+ continue: true,
127
+ suppressOutput: false,
128
+ hookSpecificOutput: {
129
+ hookEventName: 'PostToolUse',
130
+ additionalContext: `[DGS safety net] Auto-committed ${dirty.length} orphaned file(s) after ${skillName}: ${dirty.join(', ')}. This indicates a missing commit in the ${skillName} workflow — consider fixing upstream.`,
131
+ },
132
+ };
133
+ process.stdout.write(JSON.stringify(result));
134
+ process.exit(0);
135
+ }
136
+ }
137
+ } catch { /* git not available or commit failed — don't block */ }
138
+ }
139
+ }
140
+ }
141
+ process.exit(0);
142
+ }
143
+
144
+ // ── PreToolUse: Skill → write marker ──
145
+ if (hookEvent === 'PreToolUse' && toolName === 'Skill') {
146
+ const skillName = toolInput.skill || toolInput.name || '';
147
+ if (skillName.startsWith('dgs:')) {
148
+ const markerPath = getMarkerPath(sessionId);
149
+ const marker = {
150
+ command: skillName,
151
+ started: new Date().toISOString(),
152
+ session_id: sessionId,
153
+ };
154
+ fs.writeFileSync(markerPath, JSON.stringify(marker));
155
+ }
156
+ process.exit(0);
157
+ }
158
+
159
+ // ── PreToolUse: Edit/Write → check marker ──
160
+ if (hookEvent === 'PreToolUse' && (toolName === 'Edit' || toolName === 'Write')) {
161
+ // Not a DGS project? Allow everything.
162
+ if (!isDgsProject(cwd)) {
163
+ process.exit(0);
164
+ }
165
+
166
+ // Target path in allowlist? Allow.
167
+ const targetPath = getTargetPath(toolName, toolInput);
168
+ if (isAllowedPath(targetPath)) {
169
+ process.exit(0);
170
+ }
171
+
172
+ // DGS command active? Allow.
173
+ const markerPath = getMarkerPath(sessionId);
174
+ if (fs.existsSync(markerPath)) {
175
+ process.exit(0);
176
+ }
177
+
178
+ // No DGS command active in a DGS project — deny.
179
+ const result = {
180
+ hookSpecificOutput: {
181
+ hookEventName: 'PreToolUse',
182
+ permissionDecision: 'deny',
183
+ permissionDecisionReason: 'DGS workflow discipline: Edit/Write requires an active /dgs:* command. Use /dgs:fast (trivial), /dgs:quick (small), or /dgs:execute-phase (feature). Say "skip DGS" to bypass.',
184
+ },
185
+ };
186
+ process.stdout.write(JSON.stringify(result));
187
+ process.exit(0);
188
+ }
189
+
190
+ // Any other tool/event — allow
191
+ process.exit(0);
192
+ } catch {
193
+ // Parse error or unexpected input — don't block
194
+ process.exit(0);
195
+ }
196
+ });
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "bugs": {
9
9
  "url": "https://github.com/KT-Partners-Ltd/dgs-platform-docs/issues"
10
10
  },
11
- "version": "2.9.0",
11
+ "version": "3.3.0",
12
12
  "description": "Deliver Great Systems Platform — A meta-prompting, context engineering and spec-driven development system for Claude Code and Gemini by KT Partners.",
13
13
  "bin": {
14
14
  "dgs": "bin/install.js"
@@ -13,6 +13,7 @@ const DIST_DIR = path.join(HOOKS_DIR, 'dist');
13
13
  const HOOKS_TO_COPY = [
14
14
  'dgs-check-update.js',
15
15
  'dgs-context-monitor.js',
16
+ 'dgs-enforce-discipline.js',
16
17
  'dgs-statusline.js'
17
18
  ];
18
19