@ktpartners/dgs-platform 3.0.4 → 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 (115) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +8 -1
  3. package/agents/dgs-executor.md +124 -3
  4. package/agents/dgs-idea-researcher.md +447 -0
  5. package/agents/dgs-plan-checker.md +32 -0
  6. package/agents/dgs-planner.md +41 -8
  7. package/bin/install.js +44 -0
  8. package/commands/dgs/audit-milestone.md +2 -1
  9. package/commands/dgs/diff-report.md +124 -0
  10. package/commands/dgs/new-project.md +8 -21
  11. package/commands/dgs/package-scan.md +43 -0
  12. package/commands/dgs/research-idea.md +1 -0
  13. package/commands/dgs/switch-project.md +13 -0
  14. package/deliver-great-systems/bin/dgs-tools.cjs +120 -5
  15. package/deliver-great-systems/bin/lib/audit-tolerance.cjs +77 -0
  16. package/deliver-great-systems/bin/lib/audit-tolerance.test.cjs +101 -0
  17. package/deliver-great-systems/bin/lib/commands.cjs +311 -16
  18. package/deliver-great-systems/bin/lib/commands.test.cjs +115 -0
  19. package/deliver-great-systems/bin/lib/commit-verify.test.cjs +236 -0
  20. package/deliver-great-systems/bin/lib/config.cjs +41 -0
  21. package/deliver-great-systems/bin/lib/config.test.cjs +309 -0
  22. package/deliver-great-systems/bin/lib/core.cjs +7 -3
  23. package/deliver-great-systems/bin/lib/core.test.cjs +79 -1
  24. package/deliver-great-systems/bin/lib/fast-routing.cjs +199 -0
  25. package/deliver-great-systems/bin/lib/fast-routing.test.cjs +108 -0
  26. package/deliver-great-systems/bin/lib/final-commit-precondition.test.cjs +87 -0
  27. package/deliver-great-systems/bin/lib/fixtures/package-scan/bundler-audit-gemfile.json +21 -0
  28. package/deliver-great-systems/bin/lib/fixtures/package-scan/gate-parity-expected.md +186 -0
  29. package/deliver-great-systems/bin/lib/fixtures/package-scan/gate-parity-runresult.json +235 -0
  30. package/deliver-great-systems/bin/lib/fixtures/package-scan/govulncheck-import.json +3 -0
  31. package/deliver-great-systems/bin/lib/fixtures/package-scan/npm-audit-v10.json +37 -0
  32. package/deliver-great-systems/bin/lib/fixtures/package-scan/osv-clean.json +3 -0
  33. package/deliver-great-systems/bin/lib/fixtures/package-scan/osv-vulns.json +77 -0
  34. package/deliver-great-systems/bin/lib/fixtures/package-scan/pip-audit-requirements.json +28 -0
  35. package/deliver-great-systems/bin/lib/fixtures/package-scan/snyk-lodash.json +30 -0
  36. package/deliver-great-systems/bin/lib/fixtures/package-scan/snyk-workspaces.json +55 -0
  37. package/deliver-great-systems/bin/lib/frontmatter.cjs +1 -1
  38. package/deliver-great-systems/bin/lib/governance.cjs +211 -0
  39. package/deliver-great-systems/bin/lib/governance.test.cjs +339 -0
  40. package/deliver-great-systems/bin/lib/health-untracked-phase.test.cjs +269 -0
  41. package/deliver-great-systems/bin/lib/init.cjs +56 -27
  42. package/deliver-great-systems/bin/lib/init.test.cjs +212 -5
  43. package/deliver-great-systems/bin/lib/jobs.cjs +7 -4
  44. package/deliver-great-systems/bin/lib/milestone.cjs +101 -3
  45. package/deliver-great-systems/bin/lib/milestone.test.cjs +203 -0
  46. package/deliver-great-systems/bin/lib/package-adapters.cjs +530 -0
  47. package/deliver-great-systems/bin/lib/package-adapters.test.cjs +618 -0
  48. package/deliver-great-systems/bin/lib/package-ecosystems.cjs +350 -0
  49. package/deliver-great-systems/bin/lib/package-ecosystems.test.cjs +348 -0
  50. package/deliver-great-systems/bin/lib/package-runner.cjs +199 -0
  51. package/deliver-great-systems/bin/lib/package-runner.test.cjs +198 -0
  52. package/deliver-great-systems/bin/lib/package-scan-provenance.cjs +56 -0
  53. package/deliver-great-systems/bin/lib/package-scan-provenance.test.cjs +103 -0
  54. package/deliver-great-systems/bin/lib/package-scan-report.cjs +1140 -0
  55. package/deliver-great-systems/bin/lib/package-scan-report.test.cjs +1963 -0
  56. package/deliver-great-systems/bin/lib/package-scan-skill.cjs +96 -0
  57. package/deliver-great-systems/bin/lib/package-scan-skill.test.cjs +136 -0
  58. package/deliver-great-systems/bin/lib/package-scan.cjs +919 -0
  59. package/deliver-great-systems/bin/lib/package-scan.test.cjs +2147 -0
  60. package/deliver-great-systems/bin/lib/phase.cjs +18 -1
  61. package/deliver-great-systems/bin/lib/plan-number-validity.test.cjs +48 -0
  62. package/deliver-great-systems/bin/lib/projects.cjs +38 -3
  63. package/deliver-great-systems/bin/lib/projects.test.cjs +112 -2
  64. package/deliver-great-systems/bin/lib/quick.cjs +178 -23
  65. package/deliver-great-systems/bin/lib/quick.test.cjs +138 -4
  66. package/deliver-great-systems/bin/lib/repos.cjs +12 -12
  67. package/deliver-great-systems/bin/lib/review.cjs +1821 -0
  68. package/deliver-great-systems/bin/lib/state.cjs +7 -3
  69. package/deliver-great-systems/bin/lib/summary-frontmatter.cjs +54 -0
  70. package/deliver-great-systems/bin/lib/summary-frontmatter.test.cjs +78 -0
  71. package/deliver-great-systems/bin/lib/sweep-scope.test.cjs +263 -0
  72. package/deliver-great-systems/bin/lib/verify.cjs +118 -6
  73. package/deliver-great-systems/bin/lib/verify.test.cjs +82 -0
  74. package/deliver-great-systems/bin/lib/wave-0-template-rename.test.cjs +40 -0
  75. package/deliver-great-systems/bin/lib/worktrees.cjs +27 -1
  76. package/deliver-great-systems/bin/lib/worktrees.test.cjs +76 -0
  77. package/deliver-great-systems/references/agent-step-reliability.md +60 -0
  78. package/deliver-great-systems/references/conflict-resolution.md +4 -0
  79. package/deliver-great-systems/references/context-tiers.md +4 -0
  80. package/deliver-great-systems/references/package-scan-config.md +151 -0
  81. package/deliver-great-systems/references/questioning.md +0 -30
  82. package/deliver-great-systems/references/spec-review-loop.md +1 -2
  83. package/deliver-great-systems/references/workflow-conventions.md +29 -0
  84. package/deliver-great-systems/skills/dgs-tests/package-scan.md +44 -0
  85. package/deliver-great-systems/templates/REVIEW.md +35 -0
  86. package/deliver-great-systems/templates/VALIDATION.md +1 -1
  87. package/deliver-great-systems/templates/claude-md.md +11 -0
  88. package/deliver-great-systems/templates/package-scan-report.md +108 -0
  89. package/deliver-great-systems/templates/project.md +6 -170
  90. package/deliver-great-systems/templates/summary.md +3 -1
  91. package/deliver-great-systems/workflows/add-phase.md +5 -0
  92. package/deliver-great-systems/workflows/audit-milestone.md +66 -10
  93. package/deliver-great-systems/workflows/cancel-job.md +1 -1
  94. package/deliver-great-systems/workflows/codereview.md +103 -9
  95. package/deliver-great-systems/workflows/complete-milestone.md +26 -7
  96. package/deliver-great-systems/workflows/complete-quick.md +40 -2
  97. package/deliver-great-systems/workflows/discuss-phase.md +3 -2
  98. package/deliver-great-systems/workflows/execute-phase.md +89 -2
  99. package/deliver-great-systems/workflows/execute-plan.md +10 -1
  100. package/deliver-great-systems/workflows/help.md +51 -18
  101. package/deliver-great-systems/workflows/import-spec.md +65 -7
  102. package/deliver-great-systems/workflows/init-product.md +46 -152
  103. package/deliver-great-systems/workflows/new-milestone.md +115 -14
  104. package/deliver-great-systems/workflows/new-project.md +60 -331
  105. package/deliver-great-systems/workflows/package-scan.md +59 -0
  106. package/deliver-great-systems/workflows/plan-phase.md +79 -1
  107. package/deliver-great-systems/workflows/quick-complete.md +40 -2
  108. package/deliver-great-systems/workflows/quick.md +183 -10
  109. package/deliver-great-systems/workflows/research-idea.md +80 -142
  110. package/deliver-great-systems/workflows/run-job.md +21 -35
  111. package/deliver-great-systems/workflows/settings.md +13 -77
  112. package/deliver-great-systems/workflows/write-spec.md +9 -11
  113. package/hooks/dist/dgs-enforce-discipline.js +196 -0
  114. package/package.json +1 -1
  115. package/scripts/build-hooks.js +1 -0
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: dgs:diff-report
3
+ description: Generate a diff report (REVIEW.md) on demand for any milestone or quick task
4
+ argument-hint: "[version|--quick slug] [--detailed]"
5
+ allowed-tools:
6
+ - Read
7
+ - Bash
8
+ ---
9
+
10
+ # /dgs:diff-report -- On-Demand Diff Report
11
+
12
+ Generate a REVIEW.md on demand without requiring audit-milestone or complete-quick.
13
+
14
+ ## Usage
15
+
16
+ ```
17
+ /dgs:diff-report -- Auto-detect: active quick task or current milestone
18
+ /dgs:diff-report v21.0 -- Generate for a specific milestone version
19
+ /dgs:diff-report --quick slug -- Generate for a specific quick task
20
+ /dgs:diff-report --detailed -- Use LLM-powered detailed analysis mode
21
+ ```
22
+
23
+ ## Steps
24
+
25
+ <step name="parse_arguments">
26
+ Parse $ARGUMENTS for:
27
+ - A version string (e.g., `v21.0`, `v22.0`) — milestone target
28
+ - `--quick <slug>` — quick task target with explicit slug
29
+ - `--detailed` — pass through to underlying CLI command
30
+ - No arguments — auto-detect mode
31
+
32
+ Store as `TARGET_TYPE` (one of: `milestone`, `quick`, `auto`), `TARGET_VALUE` (version or slug, may be empty), and `DETAILED` (boolean).
33
+ </step>
34
+
35
+ <step name="detect_context">
36
+ **If TARGET_TYPE is `auto`** (no version or --quick specified):
37
+
38
+ Check for an active quick task first:
39
+ ```bash
40
+ ACTIVE_QUICK=$(node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" quick generate-review --raw 2>&1)
41
+ QUICK_EXIT=$?
42
+ ```
43
+
44
+ If `QUICK_EXIT` is 0 and the output contains `"generated": true` or `"fastForward": true`:
45
+ - Set `TARGET_TYPE = quick` (auto-detected)
46
+ - The command already ran and produced the review
47
+
48
+ If `QUICK_EXIT` is non-zero (no active quick task):
49
+ - Set `TARGET_TYPE = milestone` (fall back to current milestone)
50
+
51
+ **If TARGET_TYPE is `milestone`:**
52
+ Use the version argument if provided. Otherwise auto-detection happens inside the CLI command.
53
+
54
+ **If TARGET_TYPE is `quick`:**
55
+ Use the slug argument if provided. Otherwise auto-detection happens inside the CLI command.
56
+ </step>
57
+
58
+ <step name="show_context">
59
+ Display what will be generated before proceeding:
60
+
61
+ **If auto-detected quick task:**
62
+ ```
63
+ Generating review for quick task...
64
+ ```
65
+
66
+ **If milestone (with version):**
67
+ ```
68
+ Generating review for milestone {version}...
69
+ ```
70
+
71
+ **If milestone (auto-detect):**
72
+ ```
73
+ Generating review for current milestone...
74
+ ```
75
+
76
+ **If explicit quick task:**
77
+ ```
78
+ Generating review for quick task {slug}...
79
+ ```
80
+ </step>
81
+
82
+ <step name="generate">
83
+ Run the appropriate CLI command:
84
+
85
+ **For milestone reports:**
86
+ ```bash
87
+ RESULT=$(node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" jobs generate-review ${TARGET_VALUE} ${DETAILED_FLAG} 2>&1)
88
+ EXIT_CODE=$?
89
+ ```
90
+
91
+ Where `${TARGET_VALUE}` is the version (e.g., `v21.0`) or empty for auto-detect, and `${DETAILED_FLAG}` is `--detailed` if requested or empty.
92
+
93
+ **For quick task reports:**
94
+ ```bash
95
+ RESULT=$(node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" quick generate-review ${TARGET_VALUE} ${DETAILED_FLAG} 2>&1)
96
+ EXIT_CODE=$?
97
+ ```
98
+
99
+ Where `${TARGET_VALUE}` is the slug or empty for auto-detect.
100
+
101
+ Note: If auto-detect already ran the quick command in step 2 and succeeded, skip re-running — use the result from step 2.
102
+ </step>
103
+
104
+ <step name="report">
105
+ **If EXIT_CODE is 0:**
106
+
107
+ Display the result from the CLI command (it includes file path and stats).
108
+
109
+ **If EXIT_CODE is non-zero:**
110
+
111
+ Display the error from the CLI command. The underlying commands already produce actionable error messages:
112
+ - `No version specified and no active job found` — no milestone to generate for
113
+ - `No active quick task found` — no quick task to generate for
114
+ - `No job file found for [version]` — missing job file, need to run a milestone job first
115
+ - `No code changes detected` — fast-forwarded quick task (informational, not an error)
116
+ </step>
117
+
118
+ ## Success Criteria
119
+
120
+ - [ ] Auto-detects quick task vs milestone context
121
+ - [ ] Delegates to existing CLI commands (no code duplication)
122
+ - [ ] --detailed flag passed through to underlying command
123
+ - [ ] Shows context line before generating
124
+ - [ ] Error messages are actionable (from underlying CLI commands)
@@ -1,42 +1,29 @@
1
1
  ---
2
2
  name: dgs:new-project
3
- description: Initialize a new project with deep context gathering and PROJECT.md
4
- argument-hint: "[--auto]"
3
+ description: Initialize a new project as a thin skeleton (name + one-liner).
4
+ argument-hint: "[<name>]"
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Bash
8
8
  - Write
9
- - Task
10
- - AskUserQuestion
11
9
  ---
12
- <context>
13
- **Flags:**
14
- - `--auto` — Automatic mode. After config questions, runs research → requirements → roadmap without further interaction. Expects idea document via @ reference.
15
- </context>
16
-
17
10
  <objective>
18
- Initialize a new project through unified flow: questioning research (optional) requirements → roadmap.
11
+ Initialize a new project as a thin skeleton. Projects are holders specs and
12
+ milestones carry the real work.
19
13
 
20
14
  **Creates:**
21
- - `${project_path}` — project context
22
- - `config.json` — workflow preferences
23
- - `${project_root}/research/` — domain research (optional)
24
- - `${project_root}/REQUIREMENTS.md` — scoped requirements
25
- - `${roadmap_path}` — phase structure
26
- - `${state_path}` — project memory
15
+ - `${project_path}` — thin PROJECT.md (title + one-line placeholder)
27
16
 
28
- **After this command:** Run `/dgs:plan-phase 1` to start execution.
17
+ **After this command:** Run `/dgs:write-spec` to capture what you're building,
18
+ then `/dgs:new-milestone --auto <spec-id>` to start the first milestone.
29
19
  </objective>
30
20
 
31
21
  <execution_context>
32
22
  @~/.claude/deliver-great-systems/workflows/new-project.md
33
- @~/.claude/deliver-great-systems/references/questioning.md
34
23
  @~/.claude/deliver-great-systems/references/ui-brand.md
35
24
  @~/.claude/deliver-great-systems/templates/project.md
36
- @~/.claude/deliver-great-systems/templates/requirements.md
37
25
  </execution_context>
38
26
 
39
27
  <process>
40
- Execute the new-project workflow from @~/.claude/deliver-great-systems/workflows/new-project.md end-to-end.
41
- Preserve all workflow gates (validation, approvals, commits, routing).
28
+ Execute the new-project workflow end-to-end. Preserve gates (--auto error, commit).
42
29
  </process>
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: dgs:package-scan
3
+ description: Scan all repos for dependency vulnerabilities and licence compliance
4
+ argument-hint: "[--threshold <sev>] [--repo <name>]"
5
+ allowed-tools:
6
+ - Read
7
+ - Bash
8
+ - Edit
9
+ - Write
10
+ - Glob
11
+ - Grep
12
+ ---
13
+ <objective>
14
+ Scan all registered repos and the product root for dependency vulnerabilities via a tool cascade (Snyk → OSV-Scanner → ecosystem-native). Produces a markdown report with YAML frontmatter (programmatic consumption) and a human-readable body, committed atomically to the active phase directory / active milestone / project root depending on lifecycle context.
15
+
16
+ Purpose: Surface known CVEs and licence compliance issues across every language ecosystem in the project within seconds, with no configuration beyond REPOS.md.
17
+
18
+ Output: `{phase-dir}/{phase}-PACKAGE-SCAN.md` (when run during a phase), or `milestones/v{X}.{Y}-PACKAGE-SCAN.md` (during a milestone), or `PACKAGE-SCAN-{YYYY-MM-DD-HHmm}.md` at project root (standalone). The report is atomically committed via `dgs-tools commit --files`.
19
+ </objective>
20
+
21
+ <execution_context>
22
+ @~/.claude/deliver-great-systems/workflows/package-scan.md
23
+ </execution_context>
24
+
25
+ <context>
26
+ Arguments: $ARGUMENTS
27
+
28
+ **Flags** (Phase 153 will wire these; the command accepts them silently now):
29
+ - `--threshold <sev>` — filter to findings at `<sev>` severity or higher (critical/high/medium/low)
30
+ - `--repo <name>` — scan a single repo by name (must match REPOS.md entry)
31
+
32
+ **Config keys** (see `deliver-great-systems/references/package-scan-config.md`):
33
+ - `testing.packages.tool` — `auto` (default), `snyk`, `osv`, or `native`
34
+ - `testing.packages.severity_threshold` — minimum severity to include
35
+ - `testing.packages.include_dev_dependencies` — boolean, default `true`
36
+ - `testing.packages.timeout_seconds` — integer, default 300
37
+ - `testing.packages.snyk_token` — local-only (use `dgs-tools config-local-set`)
38
+ </context>
39
+
40
+ <process>
41
+ Execute the package-scan workflow from @~/.claude/deliver-great-systems/workflows/package-scan.md end-to-end.
42
+ Preserve all workflow gates (init, scan invocation, report-write-and-commit composition).
43
+ </process>
@@ -10,6 +10,7 @@ allowed-tools:
10
10
  - Grep
11
11
  - WebSearch
12
12
  - WebFetch
13
+ - Task
13
14
  ---
14
15
 
15
16
  <objective>
@@ -55,4 +55,17 @@ Progress: {status.progress}%
55
55
  **If error:**
56
56
  Display the error message from the response. Suggest `/dgs:list-projects` to see available projects.
57
57
 
58
+ ## 4. Commit PROJECTS.md if modified
59
+
60
+ The `projects list` call in step 2 regenerates PROJECTS.md. Commit it if changed:
61
+
62
+ ```bash
63
+ git -C "$(node -e "const{getPlanningRoot}=require('$HOME/.claude/deliver-great-systems/bin/lib/core.cjs');process.stdout.write(getPlanningRoot(process.cwd()))")" diff --quiet PROJECTS.md 2>/dev/null
64
+ ```
65
+
66
+ If the above exits non-zero (file has changes):
67
+ ```bash
68
+ node "$HOME/.claude/deliver-great-systems/bin/dgs-tools.cjs" commit "chore(project): regenerate PROJECTS.md on switch" --push
69
+ ```
70
+
58
71
  </process>
@@ -30,6 +30,7 @@
30
30
  * summary-extract <path> [--fields] Extract structured data from SUMMARY.md
31
31
  * state-snapshot Structured parse of STATE.md
32
32
  * phase-plan-index <phase> Index plans with waves and status
33
+ * package-scan [--raw] Scan all repos for dependency vulnerabilities; writes committed report
33
34
  * websearch <query> Search web via Brave API (if configured)
34
35
  * [--limit N] [--freshness day|week|month]
35
36
  *
@@ -790,6 +791,88 @@ async function main() {
790
791
  break;
791
792
  }
792
793
 
794
+ case 'final-commit-precondition': {
795
+ // REL-08 (Phase 157): pre-commit precondition gate. Aborts with
796
+ // `summary-frontmatter-mismatch` label when PLAN.md `requirements:` is
797
+ // non-empty AND SUMMARY.md `requirements_completed:` is empty. Read-only —
798
+ // never writes to the working tree.
799
+ const planIdx = args.indexOf('--plan');
800
+ const summaryIdx = args.indexOf('--summary');
801
+ const opts = {
802
+ plan: planIdx !== -1 ? args[planIdx + 1] : undefined,
803
+ summary: summaryIdx !== -1 ? args[summaryIdx + 1] : undefined,
804
+ };
805
+ return commands.cmdFinalCommitPrecondition(cwd, opts);
806
+ }
807
+
808
+ case 'commit-verify-plan': {
809
+ // REL-01 (Phase 156): orchestrator-side commit + verification helper
810
+ // for /dgs:plan-phase. Commits a planner-emitted createdFiles list and
811
+ // verifies every reported path appears in HEAD; on mismatch, returns
812
+ // plan-commit-incomplete with working tree unchanged.
813
+ gateIdentity();
814
+ const message = args[1];
815
+ // --files <paths...> (collect args after --files until next --flag)
816
+ const filesIndex = args.indexOf('--files');
817
+ const createdFiles = filesIndex !== -1
818
+ ? args.slice(filesIndex + 1).filter(a => !a.startsWith('--'))
819
+ : [];
820
+ // --extra-files <paths...> (e.g. ROADMAP.md)
821
+ const extraIdx = args.indexOf('--extra-files');
822
+ const extraFiles = extraIdx !== -1
823
+ ? args.slice(extraIdx + 1).filter(a => !a.startsWith('--'))
824
+ : [];
825
+ // --repo-cwd <path>
826
+ const repoCwdIdxV = args.indexOf('--repo-cwd');
827
+ const repoCwdV = repoCwdIdxV !== -1 ? args[repoCwdIdxV + 1] : undefined;
828
+ const pushV = args.includes('--push');
829
+ const result = commands.verifyPlanCommit(cwd, {
830
+ message,
831
+ createdFiles,
832
+ extraFiles,
833
+ repoCwd: repoCwdV,
834
+ push: pushV,
835
+ }, raw);
836
+ // verifyPlanCommit is a pure helper — emit output and exit non-zero
837
+ // on plan-commit-incomplete so the calling workflow can detect failure.
838
+ if (raw) {
839
+ process.stdout.write(JSON.stringify(result));
840
+ } else {
841
+ if (result.ok) {
842
+ process.stdout.write(result.hash || result.reason || 'ok');
843
+ } else {
844
+ process.stdout.write(`[${result.exitLabel}] ${result.reason}`);
845
+ }
846
+ }
847
+ process.exit(result.ok ? 0 : 1);
848
+ }
849
+
850
+ case 'compute-phase-sweep': {
851
+ // REL-02 (Phase 156): scope-bounded executor sweep helper.
852
+ // Returns the UNION of git-discovered phase-dir paths and the
853
+ // executor-reported modified_files list, scope-filtered to
854
+ // ${phasesDir}/${phaseDir}/ only.
855
+ const phasesDirIdx = args.indexOf('--phases-dir');
856
+ const phaseDirIdx = args.indexOf('--phase-dir');
857
+ const modifiedIdx = args.indexOf('--modified-files');
858
+ const phasesDirV = phasesDirIdx !== -1 ? args[phasesDirIdx + 1] : undefined;
859
+ const phaseDirV = phaseDirIdx !== -1 ? args[phaseDirIdx + 1] : undefined;
860
+ const modifiedFiles = modifiedIdx !== -1
861
+ ? args.slice(modifiedIdx + 1).filter(a => !a.startsWith('--'))
862
+ : [];
863
+ const result = commands.computePhaseSweep(cwd, {
864
+ phasesDir: phasesDirV,
865
+ phaseDir: phaseDirV,
866
+ modifiedFiles,
867
+ }, raw);
868
+ if (raw) {
869
+ process.stdout.write(JSON.stringify(result));
870
+ } else {
871
+ process.stdout.write(`Swept: ${result.swept.length} | Dropped: ${result.dropped.length}`);
872
+ }
873
+ process.exit(result.error ? 1 : 0);
874
+ }
875
+
793
876
  case 'verify-summary': {
794
877
  const summaryPath = args[1];
795
878
  const countIndex = args.indexOf('--check-count');
@@ -1123,6 +1206,7 @@ async function main() {
1123
1206
  if (subcommand === 'complete') {
1124
1207
  const nameIndex = args.indexOf('--name');
1125
1208
  const archivePhases = args.includes('--archive-phases');
1209
+ const force = args.includes('--force');
1126
1210
  // Collect --name value (everything after --name until next flag or end)
1127
1211
  let milestoneName = null;
1128
1212
  if (nameIndex !== -1) {
@@ -1133,7 +1217,7 @@ async function main() {
1133
1217
  }
1134
1218
  milestoneName = nameArgs.join(' ') || null;
1135
1219
  }
1136
- milestone.cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases }, raw);
1220
+ milestone.cmdMilestoneComplete(cwd, args[2], { name: milestoneName, archivePhases, force }, raw);
1137
1221
  } else {
1138
1222
  error('Unknown milestone subcommand. Available: complete');
1139
1223
  }
@@ -1211,7 +1295,7 @@ async function main() {
1211
1295
  init.cmdInitPlanPhase(cwd, args[2], raw);
1212
1296
  break;
1213
1297
  case 'new-project':
1214
- init.cmdInitNewProject(cwd, raw);
1298
+ init.cmdInitNewProject(cwd, args[2], raw);
1215
1299
  break;
1216
1300
  case 'new-milestone':
1217
1301
  init.cmdInitNewMilestone(cwd, raw);
@@ -1697,6 +1781,7 @@ async function main() {
1697
1781
  jobs.cmdJobsUpdateStep(cwd, args[2], args[3], args[4], { timestamp: timestampVal, error: errorVal }, raw);
1698
1782
  } else if (subcommand === 'move') {
1699
1783
  if (!args[2] || !args[3]) error('Usage: jobs move <file> <target-dir>');
1784
+ process.stderr.write('[DGS] Deprecation: "jobs move" is deprecated. Use "jobs set-status <version> --status <status>" for state transitions.\n');
1700
1785
  jobs.cmdJobsMove(cwd, args[2], args[3], raw);
1701
1786
  } else if (subcommand === 'create-milestone') {
1702
1787
  const noCheckIdx = args.indexOf('--no-check');
@@ -1769,6 +1854,11 @@ async function main() {
1769
1854
  } else if (subcommand === 'rollback') {
1770
1855
  if (!args[2]) error('Usage: jobs rollback <version>');
1771
1856
  jobs.cmdJobsRollback(cwd, args[2], raw);
1857
+ } else if (subcommand === 'generate-review') {
1858
+ const review = require('./lib/review.cjs');
1859
+ const detailed = args.includes('--detailed');
1860
+ const versionArg = args.slice(2).filter(a => a !== '--detailed' && a !== '--raw')[0];
1861
+ review.cmdJobsGenerateReview(cwd, versionArg, raw, detailed);
1772
1862
  } else if (subcommand === 'set-status') {
1773
1863
  const version = args[2];
1774
1864
  const statusIdx = args.indexOf('--status');
@@ -1785,7 +1875,7 @@ async function main() {
1785
1875
  error(err.message);
1786
1876
  }
1787
1877
  } else {
1788
- error('Unknown jobs subcommand: ' + (subcommand || '(none)') + '. Available: parse, update-step, move, find-job, update-header, insert-steps, insert-gap-fix-section, insert-phase-gap-fix, create-milestone, milestone-preview, list-jobs, cancel-job, health, dry-run, generate-summary, record-start-shas, rollback, set-status');
1878
+ error('Unknown jobs subcommand: ' + (subcommand || '(none)') + '. Available: parse, update-step, move, find-job, update-header, insert-steps, insert-gap-fix-section, insert-phase-gap-fix, create-milestone, milestone-preview, list-jobs, cancel-job, health, dry-run, generate-summary, generate-review, record-start-shas, rollback, set-status');
1789
1879
  }
1790
1880
  break;
1791
1881
  }
@@ -1823,6 +1913,12 @@ async function main() {
1823
1913
  break;
1824
1914
  }
1825
1915
 
1916
+ case 'package-scan': {
1917
+ const packageScan = require('./lib/package-scan.cjs');
1918
+ packageScan.cmdPackageScan(cwd, args, raw);
1919
+ break;
1920
+ }
1921
+
1826
1922
  case 'phase-uat-status': {
1827
1923
  const autoTest = require('./lib/auto-test.cjs');
1828
1924
  autoTest.cmdPhaseUatStatus(cwd, args[1], raw);
@@ -1971,7 +2067,7 @@ async function main() {
1971
2067
  case 'complete-quick':
1972
2068
  case 'quick-complete': {
1973
2069
  const { cmdQuickComplete } = require('./lib/quick.cjs');
1974
- cmdQuickComplete(cwd);
2070
+ cmdQuickComplete(cwd, args);
1975
2071
  break;
1976
2072
  }
1977
2073
 
@@ -1984,8 +2080,15 @@ async function main() {
1984
2080
 
1985
2081
  case 'quick': {
1986
2082
  const subcommand = args[1];
2083
+ if (subcommand === 'generate-review') {
2084
+ const review = require('./lib/review.cjs');
2085
+ const detailed = args.includes('--detailed');
2086
+ const slugArg = args.slice(2).filter(a => a !== '--detailed' && a !== '--raw')[0];
2087
+ review.cmdQuickGenerateReview(cwd, slugArg, raw, detailed);
2088
+ break;
2089
+ }
1987
2090
  if (subcommand !== 'finalize') {
1988
- error('Usage: dgs-tools quick finalize <quick_id> [--description <desc>] --quick-dir <dir> [--state-path <path>] [--push] [--repo-cwd <path>] [--fast]');
2091
+ error('Usage: dgs-tools quick <generate-review [slug]|finalize <quick_id> [options]>');
1989
2092
  return;
1990
2093
  }
1991
2094
  gateIdentity();
@@ -2033,6 +2136,18 @@ async function main() {
2033
2136
  break;
2034
2137
  }
2035
2138
 
2139
+ case 'fast-route': {
2140
+ // REL-05/06: fast-mode commit routing helper. Surveys planning root +
2141
+ // registered sub-repos for dirty state, then computes a routing decision.
2142
+ // Used by /dgs:fast workflow F0.5 (pre-edit dirt check, REL-06) and F4/F5
2143
+ // (post-edit routing, REL-05). Exits 1 if action == 'fail'.
2144
+ const { surveyDirty, decideRouting } = require('./lib/fast-routing.cjs');
2145
+ const survey = surveyDirty(cwd);
2146
+ const decision = decideRouting(survey);
2147
+ process.stdout.write(JSON.stringify({ survey, decision }, null, 2));
2148
+ process.exit(decision.action === 'fail' ? 1 : 0);
2149
+ }
2150
+
2036
2151
  default:
2037
2152
  error(`Unknown command: ${command}`);
2038
2153
  }
@@ -0,0 +1,77 @@
1
+ // deliver-great-systems/bin/lib/audit-tolerance.cjs
2
+ // REL-10: cross-reference matrix for /dgs:audit-milestone status determination.
3
+ // Extends the existing 5d matrix with soft-tolerance for empty requirements_completed
4
+ // when VERIFICATION explicitly lists the ID and status: passed.
5
+ //
6
+ // Soft-warning channel: 'summary-frontmatter-empty-but-verified' — distinct from
7
+ // real partials. Surfaces under audit JSON `soft_warnings.summary_frontmatter_empty_but_verified`,
8
+ // NOT under `gaps.requirements`. Removal trigger: 3 consecutive milestones ship
9
+ // with zero soft-warnings → drop the tolerance row, restore strict default.
10
+
11
+ const SOFT_WARNING_EMPTY_BUT_VERIFIED = 'summary-frontmatter-empty-but-verified';
12
+
13
+ function applyMatrix(input) {
14
+ const {
15
+ verificationStatus,
16
+ requirementsClaimed = [],
17
+ summaryRequirementsCompleted = [],
18
+ reqId,
19
+ strictAudit = false,
20
+ } = input;
21
+
22
+ if (!reqId) {
23
+ return { status: 'unsatisfied', softWarning: null };
24
+ }
25
+
26
+ // gaps_found short-circuits everything — VERIFICATION explicitly failed.
27
+ if (verificationStatus === 'gaps_found') {
28
+ return { status: 'unsatisfied', softWarning: null };
29
+ }
30
+
31
+ const summaryListsId = summaryRequirementsCompleted.includes(reqId);
32
+ const verificationListsId = requirementsClaimed.includes(reqId);
33
+
34
+ // Happy path: VERIFICATION passed AND SUMMARY explicitly populated.
35
+ if (verificationStatus === 'passed' && summaryListsId) {
36
+ return { status: 'satisfied', softWarning: null };
37
+ }
38
+
39
+ // Tolerance path: VERIFICATION passed AND lists ID, SUMMARY empty/missing, NOT strict.
40
+ if (
41
+ verificationStatus === 'passed' &&
42
+ !summaryListsId &&
43
+ verificationListsId &&
44
+ !strictAudit
45
+ ) {
46
+ return { status: 'satisfied', softWarning: SOFT_WARNING_EMPTY_BUT_VERIFIED };
47
+ }
48
+
49
+ // Strict path: same input as tolerance path but --strict-audit forces partial.
50
+ if (
51
+ verificationStatus === 'passed' &&
52
+ !summaryListsId &&
53
+ verificationListsId &&
54
+ strictAudit
55
+ ) {
56
+ return { status: 'partial', softWarning: null };
57
+ }
58
+
59
+ // VERIFICATION passed but does NOT list the ID, SUMMARY empty → real partial.
60
+ // (Tolerance must NOT mask this — the safety net per spec.)
61
+ if (verificationStatus === 'passed' && !summaryListsId && !verificationListsId) {
62
+ return { status: 'partial', softWarning: null };
63
+ }
64
+
65
+ // VERIFICATION missing → unsatisfied (orphan-style).
66
+ if (verificationStatus === 'missing') {
67
+ if (summaryListsId) {
68
+ return { status: 'partial', softWarning: null };
69
+ }
70
+ return { status: 'unsatisfied', softWarning: null };
71
+ }
72
+
73
+ // Default fallthrough.
74
+ return { status: 'unsatisfied', softWarning: null };
75
+ }
76
+
77
+ module.exports = { applyMatrix, SOFT_WARNING_EMPTY_BUT_VERIFIED };
@@ -0,0 +1,101 @@
1
+ // deliver-great-systems/bin/lib/audit-tolerance.test.cjs
2
+ // REL-10 regression test scaffold — initially RED. Turns GREEN after plan 03
3
+ // extends the audit cross-reference matrix with soft-tolerance + adds
4
+ // --strict-audit flag handling.
5
+
6
+ const test = require('node:test');
7
+ const assert = require('node:assert');
8
+
9
+ // REL-10 surfaces a function applyMatrix(input) -> { status, softWarning? }
10
+ // in a new module bin/lib/audit-tolerance.cjs. Plan 03 implements it.
11
+ // applyMatrix input shape:
12
+ // { verificationStatus: 'passed'|'gaps_found'|'missing',
13
+ // requirementsClaimed: string[], // from VERIFICATION.md frontmatter
14
+ // summaryRequirementsCompleted: string[], // from SUMMARY.md frontmatter (canonical key)
15
+ // reqId: string, // requirement ID under evaluation
16
+ // strictAudit: boolean // --strict-audit flag
17
+ // }
18
+ // applyMatrix output:
19
+ // { status: 'satisfied'|'partial'|'unsatisfied',
20
+ // softWarning: 'summary-frontmatter-empty-but-verified' | null
21
+ // }
22
+
23
+ function getApplyMatrix() {
24
+ try {
25
+ return require('./audit-tolerance.cjs').applyMatrix;
26
+ } catch (err) {
27
+ assert.fail('REL-10 audit-tolerance module not yet implemented: bin/lib/audit-tolerance.cjs (plan 03 task)');
28
+ }
29
+ }
30
+
31
+ test('REL-10: empty SUMMARY + VERIFICATION lists ID + status passed → satisfied + soft-warning', () => {
32
+ const applyMatrix = getApplyMatrix();
33
+ const result = applyMatrix({
34
+ verificationStatus: 'passed',
35
+ requirementsClaimed: ['TEST-01'],
36
+ summaryRequirementsCompleted: [],
37
+ reqId: 'TEST-01',
38
+ strictAudit: false,
39
+ });
40
+
41
+ assert.strictEqual(result.status, 'satisfied');
42
+ assert.strictEqual(result.softWarning, 'summary-frontmatter-empty-but-verified');
43
+ });
44
+
45
+ test('REL-10: --strict-audit preserves old strict behaviour (empty SUMMARY → partial)', () => {
46
+ const applyMatrix = getApplyMatrix();
47
+ const result = applyMatrix({
48
+ verificationStatus: 'passed',
49
+ requirementsClaimed: ['TEST-01'],
50
+ summaryRequirementsCompleted: [],
51
+ reqId: 'TEST-01',
52
+ strictAudit: true,
53
+ });
54
+
55
+ assert.strictEqual(result.status, 'partial');
56
+ // soft-warning may be null OR may still flag; spec is silent; canonical: null under strict
57
+ assert.strictEqual(result.softWarning || null, null);
58
+ });
59
+
60
+ test('REL-10: tolerance does NOT mask real partials (VERIFICATION not listing ID still partial)', () => {
61
+ const applyMatrix = getApplyMatrix();
62
+ const result = applyMatrix({
63
+ verificationStatus: 'passed',
64
+ requirementsClaimed: ['OTHER-01'], // does NOT list TEST-01
65
+ summaryRequirementsCompleted: [],
66
+ reqId: 'TEST-01',
67
+ strictAudit: false,
68
+ });
69
+
70
+ assert.strictEqual(result.status, 'partial');
71
+ assert.strictEqual(result.softWarning || null, null);
72
+ });
73
+
74
+ test('REL-10: gaps_found VERIFICATION → unsatisfied regardless of SUMMARY shape', () => {
75
+ const applyMatrix = getApplyMatrix();
76
+ const result = applyMatrix({
77
+ verificationStatus: 'gaps_found',
78
+ requirementsClaimed: ['TEST-01'],
79
+ summaryRequirementsCompleted: ['TEST-01'],
80
+ reqId: 'TEST-01',
81
+ strictAudit: false,
82
+ });
83
+
84
+ assert.strictEqual(result.status, 'unsatisfied');
85
+ });
86
+
87
+ test('REL-10: SUMMARY explicitly populated + VERIFICATION passed → satisfied (no soft-warning)', () => {
88
+ const applyMatrix = getApplyMatrix();
89
+ const result = applyMatrix({
90
+ verificationStatus: 'passed',
91
+ requirementsClaimed: ['TEST-01'],
92
+ summaryRequirementsCompleted: ['TEST-01'],
93
+ reqId: 'TEST-01',
94
+ strictAudit: false,
95
+ });
96
+
97
+ assert.strictEqual(result.status, 'satisfied');
98
+ assert.strictEqual(result.softWarning || null, null);
99
+ });
100
+
101
+ // REL-10 sentinel — flag this file as a Wave-0 RED scaffold for plan 03.