create-quiver 0.6.0 → 0.8.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 (120) hide show
  1. package/.claude/settings.local.json +45 -0
  2. package/.github/workflows/ci.yml +9 -32
  3. package/AGENTS.md.template +41 -0
  4. package/BACKLOG.md +139 -0
  5. package/CHANGELOG.md +17 -0
  6. package/README.md +68 -14
  7. package/README_FOR_AI.md +48 -16
  8. package/ROADMAP.md +100 -0
  9. package/docs/AI_CONTEXT.md.template +19 -26
  10. package/docs/AI_ONBOARDING_PROMPT.md.template +16 -0
  11. package/docs/COMMANDS.md.template +25 -0
  12. package/docs/CONTEXTO.md.template +4 -17
  13. package/docs/DECISIONS.md.template +18 -0
  14. package/docs/DEEP.md.template +34 -0
  15. package/docs/DOCUMENTATION_GUIDE.md.template +9 -7
  16. package/docs/GITFLOW_PR_GUIDE.md.template +7 -0
  17. package/docs/INDEX.md.template +11 -0
  18. package/docs/QUICK.md.template +27 -0
  19. package/docs/STANDARD.md.template +49 -0
  20. package/docs/STATUS.md.template +2 -2
  21. package/docs/SUPPORT_MATRIX.md.template +16 -4
  22. package/docs/TESTING_GUIDE_FOR_AI.md.template +4 -3
  23. package/docs/TROUBLESHOOTING.md.template +14 -0
  24. package/docs/WORKFLOW.md.template +21 -4
  25. package/docs/examples/graph.md.template +62 -0
  26. package/docs/examples/next.md.template +27 -0
  27. package/docs/examples/plan.md.template +28 -0
  28. package/package.json +6 -2
  29. package/package.template.json +16 -0
  30. package/scripts/check-slice-readiness.sh +6 -4
  31. package/scripts/cleanup-slice.sh +2 -172
  32. package/scripts/init-docs.sh +147 -26
  33. package/scripts/package-quiver.sh +5 -0
  34. package/scripts/start-slice.sh +3 -425
  35. package/specs/[project-name]/EVIDENCE_REPORT.md.template +3 -1
  36. package/specs/[project-name]/HANDOFF.md.template +37 -0
  37. package/specs/[project-name]/slices/slice-template/slice.json +7 -2
  38. package/specs/quiver-v08-agent-onboarding-analysis/slices/slice-01-project-scan-command/slice.json +1 -1
  39. package/specs/quiver-v08-agent-onboarding-analysis/slices/slice-02-ai-onboarding-prompt/slice.json +1 -1
  40. package/specs/quiver-v08-agent-onboarding-analysis/slices/slice-03-doctor-readme-adoption-flow/slice.json +1 -1
  41. package/specs/quiver-v12-cross-platform-native-runtime/EVIDENCE_REPORT.md +30 -0
  42. package/specs/quiver-v12-cross-platform-native-runtime/SPEC.md +86 -0
  43. package/specs/quiver-v12-cross-platform-native-runtime/STATUS.md +29 -0
  44. package/specs/quiver-v12-cross-platform-native-runtime/slices/slice-01-cross-platform-support-contract/slice.json +69 -0
  45. package/specs/quiver-v12-cross-platform-native-runtime/slices/slice-02-node-init-docs-runtime/slice.json +76 -0
  46. package/specs/quiver-v12-cross-platform-native-runtime/slices/slice-03-node-migrate-analyze-doctor-flow/slice.json +74 -0
  47. package/specs/quiver-v12-cross-platform-native-runtime/slices/slice-04-node-slice-lifecycle-commands/slice.json +81 -0
  48. package/specs/quiver-v12-cross-platform-native-runtime/slices/slice-05-generated-project-scripts-and-migration/slice.json +78 -0
  49. package/specs/quiver-v12-cross-platform-native-runtime/slices/slice-06-cross-platform-ci-release-readiness/slice.json +74 -0
  50. package/specs/quiver-v13-token-efficient-ai-context/EVIDENCE_REPORT.md +28 -0
  51. package/specs/quiver-v13-token-efficient-ai-context/SPEC.md +68 -0
  52. package/specs/quiver-v13-token-efficient-ai-context/STATUS.md +26 -0
  53. package/specs/quiver-v13-token-efficient-ai-context/slices/slice-01-token-efficient-ai-modes-guidance/slice.json +65 -0
  54. package/specs/quiver-v13-token-efficient-ai-context/slices/slice-02-decision-log-context-checkpoint/slice.json +64 -0
  55. package/specs/quiver-v13-token-efficient-ai-context/slices/slice-03-project-map-reading-order/slice.json +66 -0
  56. package/specs/quiver-v14-tiered-context-pack/EVIDENCE_REPORT.md +42 -0
  57. package/specs/quiver-v14-tiered-context-pack/SPEC.md +116 -0
  58. package/specs/quiver-v14-tiered-context-pack/STATUS.md +35 -0
  59. package/specs/quiver-v14-tiered-context-pack/slices/slice-01-tiered-context-pack/slice.json +77 -0
  60. package/specs/quiver-v14-tiered-context-pack/slices/slice-02-agents-md-router/slice.json +74 -0
  61. package/specs/quiver-v14-tiered-context-pack/slices/slice-03-active-slice-lifecycle/slice.json +74 -0
  62. package/specs/quiver-v14-tiered-context-pack/slices/slice-04-dedup-frontmatter/slice.json +83 -0
  63. package/specs/quiver-v14-tiered-context-pack/slices/slice-05-doctor-smokes-tiered-pack/slice.json +84 -0
  64. package/specs/quiver-v15-init-required-before-migrate/EVIDENCE_REPORT.md +26 -0
  65. package/specs/quiver-v15-init-required-before-migrate/SPEC.md +66 -0
  66. package/specs/quiver-v15-init-required-before-migrate/STATUS.md +26 -0
  67. package/specs/quiver-v15-init-required-before-migrate/slices/slice-01-migrate-initialization-precondition/slice.json +65 -0
  68. package/specs/quiver-v15-init-required-before-migrate/slices/slice-02-doctor-not-initialized-guidance/slice.json +61 -0
  69. package/specs/quiver-v15-init-required-before-migrate/slices/slice-03-docs-smokes-init-before-migrate/slice.json +64 -0
  70. package/specs/quiver-v16-handoff-contract/EVIDENCE_REPORT.md +26 -0
  71. package/specs/quiver-v16-handoff-contract/SPEC.md +68 -0
  72. package/specs/quiver-v16-handoff-contract/STATUS.md +26 -0
  73. package/specs/quiver-v16-handoff-contract/slices/slice-01-handoff-template-and-contract/slice.json +66 -0
  74. package/specs/quiver-v16-handoff-contract/slices/slice-02-check-handoff-command/slice.json +70 -0
  75. package/specs/quiver-v16-handoff-contract/slices/slice-03-handoff-scaffold-optional/slice.json +67 -0
  76. package/specs/quiver-v17-orchestration-foundation/EVIDENCE_REPORT.md +32 -0
  77. package/specs/quiver-v17-orchestration-foundation/SPEC.md +79 -0
  78. package/specs/quiver-v17-orchestration-foundation/STATUS.md +31 -0
  79. package/specs/quiver-v17-orchestration-foundation/slices/slice-01-ci-matrix-verified/slice.json +68 -0
  80. package/specs/quiver-v17-orchestration-foundation/slices/slice-02-slice-graph-library/slice.json +65 -0
  81. package/specs/quiver-v17-orchestration-foundation/slices/slice-03-depends-on-validation/slice.json +72 -0
  82. package/specs/quiver-v18-slice-orchestration/EVIDENCE_REPORT.md +38 -0
  83. package/specs/quiver-v18-slice-orchestration/SPEC.md +91 -0
  84. package/specs/quiver-v18-slice-orchestration/STATUS.md +33 -0
  85. package/specs/quiver-v18-slice-orchestration/slices/slice-01-plan-command/slice.json +79 -0
  86. package/specs/quiver-v18-slice-orchestration/slices/slice-02-graph-mvp-tree/slice.json +75 -0
  87. package/specs/quiver-v18-slice-orchestration/slices/slice-03-graph-extended-formats/slice.json +70 -0
  88. package/specs/quiver-v18-slice-orchestration/slices/slice-04-next-command/slice.json +73 -0
  89. package/specs/quiver-v18-stabilization/EVIDENCE_REPORT.md +26 -0
  90. package/specs/quiver-v18-stabilization/SPEC.md +62 -0
  91. package/specs/quiver-v18-stabilization/STATUS.md +30 -0
  92. package/specs/quiver-v18-stabilization/slices/slice-01-fix-legacy-dependency-resolution/CLOSURE_BRIEF.md +29 -0
  93. package/specs/quiver-v18-stabilization/slices/slice-01-fix-legacy-dependency-resolution/EXECUTION_BRIEF.md +134 -0
  94. package/specs/quiver-v18-stabilization/slices/slice-01-fix-legacy-dependency-resolution/slice.json +56 -0
  95. package/specs/quiver-v18-stabilization/slices/slice-02-roadmap-and-branch-cleanup/CLOSURE_BRIEF.md +29 -0
  96. package/specs/quiver-v18-stabilization/slices/slice-02-roadmap-and-branch-cleanup/EXECUTION_BRIEF.md +118 -0
  97. package/specs/quiver-v18-stabilization/slices/slice-02-roadmap-and-branch-cleanup/slice.json +57 -0
  98. package/specs/quiver-v18-stabilization/slices/slice-03-publish-drafts-branch/CLOSURE_BRIEF.md +23 -0
  99. package/specs/quiver-v18-stabilization/slices/slice-03-publish-drafts-branch/EXECUTION_BRIEF.md +73 -0
  100. package/specs/quiver-v18-stabilization/slices/slice-03-publish-drafts-branch/slice.json +49 -0
  101. package/src/create-quiver/commands/graph.js +97 -0
  102. package/src/create-quiver/commands/next.js +134 -0
  103. package/src/create-quiver/commands/plan.js +205 -0
  104. package/src/create-quiver/index.js +476 -123
  105. package/src/create-quiver/lib/analyze.js +9 -0
  106. package/src/create-quiver/lib/doctor.js +212 -0
  107. package/src/create-quiver/lib/git.js +154 -0
  108. package/src/create-quiver/lib/handoff.js +104 -0
  109. package/src/create-quiver/lib/init-docs.js +674 -0
  110. package/src/create-quiver/lib/json.js +14 -0
  111. package/src/create-quiver/lib/lifecycle.js +479 -0
  112. package/src/create-quiver/lib/paths.js +19 -0
  113. package/src/create-quiver/lib/readiness.js +354 -0
  114. package/src/create-quiver/lib/renderers/dot.js +129 -0
  115. package/src/create-quiver/lib/renderers/mermaid.js +119 -0
  116. package/src/create-quiver/lib/renderers/tree.js +116 -0
  117. package/src/create-quiver/lib/scope.js +5 -0
  118. package/src/create-quiver/lib/slice-graph.js +453 -0
  119. package/src/create-quiver/lib/slice.js +195 -0
  120. package/src/create-quiver/lib/state.js +139 -0
@@ -2,6 +2,21 @@ const fs = require('fs');
2
2
  const os = require('os');
3
3
  const path = require('path');
4
4
  const { execFileSync } = require('child_process');
5
+ const { checkHandoff, scaffoldHandoff } = require('./lib/handoff');
6
+ const { collectDoctorWarnings } = require('./lib/doctor');
7
+ const { runGraph } = require('./commands/graph');
8
+ const { runNext } = require('./commands/next');
9
+ const { runPlan } = require('./commands/plan');
10
+ const { initializeProjectDocs } = require('./lib/init-docs');
11
+ const { checkPrReadiness, checkScope, checkSliceReadiness } = require('./lib/readiness');
12
+ const { cleanupSlice, refreshActiveSlicesBoard, startSlice } = require('./lib/lifecycle');
13
+ const { relativePosixPath, resolveTargetRoot } = require('./lib/paths');
14
+ const {
15
+ hasQuiverInitializationEvidence,
16
+ readState,
17
+ updateStateForAnalyze,
18
+ updateStateForMigrate,
19
+ } = require('./lib/state');
5
20
  const cliPackageJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../..', 'package.json'), 'utf8'));
6
21
  const CLI_VERSION = cliPackageJson.version || '0.0.0';
7
22
 
@@ -13,21 +28,56 @@ function printUsage() {
13
28
  console.log(`Usage:
14
29
  npx create-quiver [options]
15
30
  npx create-quiver analyze [options]
31
+ npx create-quiver plan [options]
32
+ npx create-quiver graph [options]
33
+ npx create-quiver next [options]
16
34
  npx create-quiver migrate [options]
17
35
  npx create-quiver doctor [options]
36
+ npx create-quiver start-slice [options] <slice.json>
37
+ npx create-quiver check-slice [options] <slice.json>
38
+ npx create-quiver check-pr <slice.json>
39
+ npx create-quiver check-handoff <handoff.md>
40
+ npx create-quiver new-handoff <spec-slug>
41
+ npx create-quiver cleanup-slice [options] <slice.json>
42
+ npx create-quiver check-scope [options] <slice.json>
43
+ npx create-quiver refresh-active-slices
18
44
 
19
45
  Options:
20
46
  -n, --name <project-name> Project name to generate
21
47
  -d, --dir <target-dir> Target directory to scaffold into or inspect
48
+ --spec <slug> Restrict plan output to one spec
49
+ --format <name> Graph output format (tree, mermaid, dot)
50
+ --show-conflicts Show shared file paths in graph output
51
+ --level <n> Restrict graph output to one level
52
+ --json Emit machine-readable JSON
53
+ --only-ready Show only slices with no pending dependencies
54
+ --all-ready List every ready slice returned by next
55
+ --auto-start Prompt for confirmation and run start-slice on next
56
+ --unicode Prefer Unicode output when supported
22
57
  -y, --yes Skip prompts and use the provided inputs
23
58
  -h, --help Show this help message
24
59
 
25
60
  Examples:
26
61
  npx create-quiver --name "My Project"
27
62
  npx create-quiver --name "My Project" --dir ./my-project
28
- npx create-quiver analyze --dir ./my-project
29
- npx create-quiver migrate --dir ./my-project
30
- npx create-quiver doctor --dir ./my-project
63
+ cd ./my-project && npx create-quiver analyze
64
+ cd ./my-project && npx create-quiver plan --json
65
+ cd ./my-project && npx create-quiver graph --show-conflicts
66
+ cd ./my-project && npx create-quiver graph --format mermaid
67
+ cd ./my-project && npx create-quiver graph --format dot
68
+ cd ./my-project && npx create-quiver next
69
+ cd ./my-project && npx create-quiver next --all-ready
70
+ cd ./my-project && npx create-quiver next --auto-start
71
+ cd ./my-project && npx create-quiver migrate
72
+ cd ./my-project && npx create-quiver doctor
73
+ cd ./my-project && npx create-quiver start-slice specs/my-project/slices/slice-01/slice.json
74
+ cd ./my-project && npx create-quiver check-slice specs/my-project/slices/slice-01/slice.json
75
+ cd ./my-project && npx create-quiver check-pr specs/my-project/slices/slice-01/slice.json
76
+ cd ./my-project && npx create-quiver check-handoff specs/my-project/HANDOFF.md
77
+ cd ./my-project && npx create-quiver new-handoff my-spec
78
+ cd ./my-project && npx create-quiver cleanup-slice specs/my-project/slices/slice-01/slice.json
79
+ cd ./my-project && npx create-quiver check-scope specs/my-project/slices/slice-01/slice.json
80
+ cd ./my-project && npx create-quiver refresh-active-slices
31
81
  node bin/create-quiver.js doctor --dir ./my-project
32
82
  `);
33
83
  }
@@ -37,12 +87,29 @@ function parseArgs(argv) {
37
87
  help: false,
38
88
  force: false,
39
89
  mode: 'init',
90
+ allowDraft: false,
91
+ closeBaseline: false,
92
+ discard: false,
93
+ dryRun: false,
94
+ gate: 'execution',
40
95
  projectName: '',
41
96
  targetDir: '.',
97
+ strict: false,
98
+ strictOverlap: false,
99
+ json: false,
100
+ onlyReady: false,
101
+ allReady: false,
102
+ autoStart: false,
103
+ specSlug: '',
104
+ format: 'tree',
105
+ showConflicts: false,
106
+ level: null,
107
+ unicode: false,
42
108
  };
43
109
 
44
110
  const args = [...argv];
45
- if (args[0] === 'doctor' || args[0] === 'analyze' || args[0] === 'migrate') {
111
+ const commandModes = new Set(['plan', 'graph', 'next', 'doctor', 'analyze', 'migrate', 'start-slice', 'check-slice', 'check-pr', 'check-handoff', 'new-handoff', 'cleanup-slice', 'check-scope', 'refresh-active-slices']);
112
+ if (commandModes.has(args[0])) {
46
113
  result.mode = args[0];
47
114
  args.shift();
48
115
  } else if (args[0] === '--analyze') {
@@ -54,6 +121,12 @@ function parseArgs(argv) {
54
121
  } else if (args[0] === '--doctor') {
55
122
  result.mode = 'doctor';
56
123
  args.shift();
124
+ } else if (args[0] === '--check-handoff') {
125
+ result.mode = 'check-handoff';
126
+ args.shift();
127
+ } else if (args[0] === '--new-handoff') {
128
+ result.mode = 'new-handoff';
129
+ args.shift();
57
130
  }
58
131
 
59
132
  const positional = [];
@@ -81,6 +154,116 @@ function parseArgs(argv) {
81
154
  continue;
82
155
  }
83
156
 
157
+ if (arg === '--check-handoff') {
158
+ result.mode = 'check-handoff';
159
+ continue;
160
+ }
161
+
162
+ if (arg === '--new-handoff') {
163
+ result.mode = 'new-handoff';
164
+ continue;
165
+ }
166
+
167
+ if (arg === '--allow-draft') {
168
+ result.allowDraft = true;
169
+ continue;
170
+ }
171
+
172
+ if (arg === '--close-baseline') {
173
+ result.closeBaseline = true;
174
+ continue;
175
+ }
176
+
177
+ if (arg === '--discard') {
178
+ result.discard = true;
179
+ continue;
180
+ }
181
+
182
+ if (arg === '--dry-run') {
183
+ result.dryRun = true;
184
+ continue;
185
+ }
186
+
187
+ if (arg === '--strict') {
188
+ result.strict = true;
189
+ continue;
190
+ }
191
+
192
+ if (arg === '--strict-overlap') {
193
+ result.strictOverlap = true;
194
+ continue;
195
+ }
196
+
197
+ if (arg === '--json') {
198
+ result.json = true;
199
+ continue;
200
+ }
201
+
202
+ if (arg === '--show-conflicts') {
203
+ result.showConflicts = true;
204
+ continue;
205
+ }
206
+
207
+ if (arg === '--format') {
208
+ const value = args[++index];
209
+ if (!value) {
210
+ throw new Error(formatError('missing value for --format'));
211
+ }
212
+ result.format = value;
213
+ continue;
214
+ }
215
+
216
+ if (arg === '--level') {
217
+ const value = args[++index];
218
+ if (typeof value === 'undefined') {
219
+ throw new Error(formatError('missing value for --level'));
220
+ }
221
+ const parsed = Number.parseInt(value, 10);
222
+ if (!Number.isInteger(parsed) || parsed < 0) {
223
+ throw new Error(formatError('invalid value for --level'));
224
+ }
225
+ result.level = parsed;
226
+ continue;
227
+ }
228
+
229
+ if (arg === '--only-ready') {
230
+ result.onlyReady = true;
231
+ continue;
232
+ }
233
+
234
+ if (arg === '--all-ready') {
235
+ result.allReady = true;
236
+ continue;
237
+ }
238
+
239
+ if (arg === '--auto-start') {
240
+ result.autoStart = true;
241
+ continue;
242
+ }
243
+
244
+ if (arg === '--unicode') {
245
+ result.unicode = true;
246
+ continue;
247
+ }
248
+
249
+ if (arg === '--spec') {
250
+ const value = args[++index];
251
+ if (!value) {
252
+ throw new Error(formatError('missing value for --spec'));
253
+ }
254
+ result.specSlug = value;
255
+ continue;
256
+ }
257
+
258
+ if (arg === '--gate') {
259
+ const value = args[++index];
260
+ if (!value) {
261
+ throw new Error(formatError('missing value for --gate'));
262
+ }
263
+ result.gate = value;
264
+ continue;
265
+ }
266
+
84
267
  if (arg === '-n' || arg === '--name' || arg === '--project-name') {
85
268
  const value = args[++index];
86
269
  if (!value) {
@@ -114,6 +297,14 @@ function parseArgs(argv) {
114
297
  if (positional.length > 0) {
115
298
  result.targetDir = positional.shift();
116
299
  }
300
+ } else if (result.mode === 'plan') {
301
+ if (positional.length > 0) {
302
+ throw new Error(formatError('plan does not accept positional arguments; use --spec <slug>'));
303
+ }
304
+ } else if (result.mode === 'refresh-active-slices') {
305
+ if (positional.length > 0) {
306
+ throw new Error(formatError('refresh-active-slices does not accept positional arguments'));
307
+ }
117
308
  } else {
118
309
  if (positional.length > 0) {
119
310
  result.targetDir = positional.shift();
@@ -204,84 +395,14 @@ function mergeDirectoryTree(sourceDir, targetDir) {
204
395
  }
205
396
 
206
397
  function runInitDocs(repoRoot, projectName) {
207
- runCommand('bash', ['docs-template/scripts/init-docs.sh', projectName], {
208
- cwd: repoRoot,
398
+ initializeProjectDocs({
399
+ projectRoot: repoRoot,
400
+ projectName,
401
+ cliVersion: CLI_VERSION,
402
+ migrateMode: false,
209
403
  });
210
404
  }
211
405
 
212
- function runInitDocsWithMode(repoRoot, projectName, mode) {
213
- return runCommand('bash', ['docs-template/scripts/init-docs.sh', projectName], {
214
- cwd: repoRoot,
215
- env: {
216
- ...process.env,
217
- QUIVER_PROJECT_NAME: projectName,
218
- QUIVER_MIGRATE: mode === 'migrate' ? '1' : '0',
219
- QUIVER_VERSION: CLI_VERSION,
220
- },
221
- });
222
- }
223
-
224
- function writeQuiverState(projectRoot, nextState) {
225
- const stateDir = path.join(projectRoot, '.quiver');
226
- const statePath = path.join(stateDir, 'state.json');
227
- fs.mkdirSync(stateDir, { recursive: true });
228
- fs.writeFileSync(statePath, `${JSON.stringify(nextState, null, 2)}\n`);
229
- return statePath;
230
- }
231
-
232
- function readQuiverState(projectRoot) {
233
- return readJsonIfExists(path.join(projectRoot, '.quiver', 'state.json'));
234
- }
235
-
236
- function createInitialQuiverState(projectName) {
237
- const now = new Date().toISOString();
238
-
239
- return {
240
- project_name: projectName,
241
- quiver_version: CLI_VERSION,
242
- initialized_version: CLI_VERSION,
243
- migrated_version: null,
244
- last_initialized_at: now,
245
- last_migration_at: null,
246
- last_analysis_at: null,
247
- };
248
- }
249
-
250
- function updateQuiverStateForAnalyze(projectRoot) {
251
- const currentState = readQuiverState(projectRoot);
252
-
253
- if (!currentState) {
254
- return null;
255
- }
256
-
257
- const nextState = {
258
- ...currentState,
259
- quiver_version: CLI_VERSION,
260
- last_analysis_at: new Date().toISOString(),
261
- };
262
-
263
- writeQuiverState(projectRoot, nextState);
264
- return nextState;
265
- }
266
-
267
- function updateQuiverStateForMigrate(projectRoot, projectName) {
268
- const currentState = readQuiverState(projectRoot);
269
- const now = new Date().toISOString();
270
- const nextState = {
271
- ...(currentState || {}),
272
- project_name: projectName,
273
- quiver_version: CLI_VERSION,
274
- initialized_version: currentState?.initialized_version ?? null,
275
- migrated_version: CLI_VERSION,
276
- last_initialized_at: currentState?.last_initialized_at ?? null,
277
- last_migration_at: now,
278
- last_analysis_at: currentState?.last_analysis_at ?? null,
279
- };
280
-
281
- writeQuiverState(projectRoot, nextState);
282
- return nextState;
283
- }
284
-
285
406
  function listGeneratedSpecDirs(projectRoot) {
286
407
  const specsDir = path.join(projectRoot, 'specs');
287
408
 
@@ -791,6 +912,49 @@ function buildProjectScan(projectRoot) {
791
912
 
792
913
  function renderProjectMap(scan) {
793
914
  const lines = [];
915
+ const projectSlug = scan.project.name
916
+ .toLowerCase()
917
+ .replace(/[^a-z0-9]+/g, '-')
918
+ .replace(/^-+|-+$/g, '') || 'project';
919
+ const docsFiles = new Set(scan.docs.files);
920
+ const hasDecisionLog = docsFiles.has('docs/DECISIONS.md');
921
+ const hasAiPrompt = docsFiles.has('docs/AI_ONBOARDING_PROMPT.md');
922
+ const sourceDirs = scan.structure.source_directories.length > 0 ? scan.structure.source_directories : [];
923
+ const configFiles = scan.structure.config_files.length > 0 ? scan.structure.config_files : [];
924
+ const highSignalFiles = [
925
+ 'README.md',
926
+ 'docs/INDEX.md',
927
+ 'docs/AI_CONTEXT.md',
928
+ 'docs/DECISIONS.md',
929
+ 'docs/PROJECT_SCAN.json',
930
+ 'docs/PROJECT_MAP.md',
931
+ 'docs/AI_ONBOARDING_PROMPT.md',
932
+ 'docs/CONTEXTO.md',
933
+ 'docs/WORKFLOW.md',
934
+ 'docs/SUPPORT_MATRIX.md',
935
+ 'docs/TROUBLESHOOTING.md',
936
+ 'package.json',
937
+ ...configFiles,
938
+ ].filter((value, index, array) => array.indexOf(value) === index);
939
+ const likelyTestCommands = [
940
+ ['Install', scan.commands.install || 'npm install'],
941
+ ['dev', scan.commands.common.dev || 'not defined'],
942
+ ['build', scan.commands.common.build || 'not defined'],
943
+ ['test', scan.commands.common.test || 'not defined'],
944
+ ['lint', scan.commands.common.lint || 'not defined'],
945
+ ];
946
+ const readingOrder = [
947
+ 'README.md',
948
+ 'docs/INDEX.md',
949
+ 'docs/AI_CONTEXT.md',
950
+ 'docs/PROJECT_SCAN.json',
951
+ 'docs/PROJECT_MAP.md',
952
+ hasDecisionLog ? 'docs/DECISIONS.md' : 'docs/DECISIONS.md (create with migrate if missing)',
953
+ 'docs/CONTEXTO.md',
954
+ 'docs/WORKFLOW.md',
955
+ 'docs/SUPPORT_MATRIX.md',
956
+ 'docs/TROUBLESHOOTING.md',
957
+ ];
794
958
 
795
959
  lines.push('# Project Map');
796
960
  lines.push('');
@@ -804,37 +968,83 @@ function renderProjectMap(scan) {
804
968
  }
805
969
 
806
970
  lines.push('');
807
- lines.push('## Stack');
808
- lines.push(`- Primary: ${scan.stack.primary}`);
809
- lines.push(`- Frameworks: ${scan.stack.frameworks.length > 0 ? scan.stack.frameworks.join(', ') : 'none detected'}`);
810
- lines.push(`- Languages: ${scan.stack.languages.length > 0 ? scan.stack.languages.join(', ') : 'none detected'}`);
971
+ lines.push('## Suggested Reading Order');
972
+ for (const item of readingOrder) {
973
+ lines.push(`- ${item}`);
974
+ }
811
975
 
812
- if (scan.stack.evidence.length > 0) {
813
- lines.push('');
814
- lines.push('### Evidence');
815
- for (const item of scan.stack.evidence) {
816
- lines.push(`- ${item.framework}: ${item.signals.join(', ')}`);
976
+ if (hasAiPrompt) {
977
+ lines.push('- docs/AI_ONBOARDING_PROMPT.md');
978
+ }
979
+
980
+ lines.push(`- specs/${projectSlug}/SPEC.md`);
981
+ if (sourceDirs.length > 0) {
982
+ for (const sourceDir of sourceDirs) {
983
+ lines.push(`- ${sourceDir}/...`);
984
+ }
985
+ }
986
+
987
+ lines.push('');
988
+ lines.push('## Entry Points');
989
+ lines.push(`- Project overview: ${scan.docs.has_readme ? 'README.md' : 'docs/CONTEXTO.md'}`);
990
+ lines.push(`- AI context: ${hasDecisionLog ? 'docs/AI_CONTEXT.md + docs/DECISIONS.md' : 'docs/AI_CONTEXT.md'}`);
991
+ lines.push('- Analysis outputs: docs/PROJECT_SCAN.json, docs/PROJECT_MAP.md');
992
+ lines.push(`- Workflow contract: docs/WORKFLOW.md`);
993
+ lines.push(`- Spec contract: specs/${projectSlug}/SPEC.md`);
994
+ if (sourceDirs.length > 0) {
995
+ lines.push(`- Source roots: ${sourceDirs.join(', ')}`);
996
+ } else {
997
+ lines.push('- Source roots: none detected');
998
+ }
999
+
1000
+ lines.push('');
1001
+ lines.push('## Primary Config Files');
1002
+ if (configFiles.length > 0) {
1003
+ for (const configFile of configFiles) {
1004
+ lines.push(`- ${configFile}`);
817
1005
  }
1006
+ } else {
1007
+ lines.push('- none detected');
818
1008
  }
819
1009
 
820
1010
  lines.push('');
821
1011
  lines.push('## Commands');
1012
+ lines.push('See **Likely Test Commands** for the current read-friendly command summary.');
1013
+
1014
+ lines.push('');
1015
+ lines.push('## Likely Test Commands');
822
1016
  lines.push('| Command | Value |');
823
1017
  lines.push('|---------|-------|');
824
- lines.push(`| Install | ${escapeMarkdownCell(scan.commands.install || 'npm install')} |`);
825
- lines.push(`| dev | ${escapeMarkdownCell(scan.commands.common.dev || 'not defined')} |`);
826
- lines.push(`| build | ${escapeMarkdownCell(scan.commands.common.build || 'not defined')} |`);
827
- lines.push(`| test | ${escapeMarkdownCell(scan.commands.common.test || 'not defined')} |`);
828
- lines.push(`| lint | ${escapeMarkdownCell(scan.commands.common.lint || 'not defined')} |`);
1018
+ for (const [name, value] of likelyTestCommands) {
1019
+ lines.push(`| ${name} | ${escapeMarkdownCell(value)} |`);
1020
+ }
1021
+
1022
+ const relevantScripts = Object.entries(scan.commands.scripts)
1023
+ .filter(([name]) => /(^|:)(analyze|doctor|migrate|test|build|lint|dev|start|check)(:|$)|analyze|doctor|migrate|test|build|lint|dev|start|check/i.test(name))
1024
+ .slice(0, 12);
829
1025
 
830
- if (Object.keys(scan.commands.scripts).length > 0) {
1026
+ if (relevantScripts.length > 0) {
831
1027
  lines.push('');
832
1028
  lines.push('### package.json scripts');
833
- for (const [name, command] of Object.entries(scan.commands.scripts)) {
1029
+ for (const [name, command] of relevantScripts) {
834
1030
  lines.push(`- ${name}: \`${command}\``);
835
1031
  }
836
1032
  }
837
1033
 
1034
+ lines.push('');
1035
+ lines.push('## Stack');
1036
+ lines.push(`- Primary: ${scan.stack.primary}`);
1037
+ lines.push(`- Frameworks: ${scan.stack.frameworks.length > 0 ? scan.stack.frameworks.join(', ') : 'none detected'}`);
1038
+ lines.push(`- Languages: ${scan.stack.languages.length > 0 ? scan.stack.languages.join(', ') : 'none detected'}`);
1039
+
1040
+ if (scan.stack.evidence.length > 0) {
1041
+ lines.push('');
1042
+ lines.push('### Evidence');
1043
+ for (const item of scan.stack.evidence) {
1044
+ lines.push(`- ${item.framework}: ${item.signals.join(', ')}`);
1045
+ }
1046
+ }
1047
+
838
1048
  lines.push('');
839
1049
  lines.push('## Structure');
840
1050
  lines.push(`- Top-level directories: ${scan.structure.top_level_directories.length > 0 ? scan.structure.top_level_directories.join(', ') : 'none detected'}`);
@@ -849,6 +1059,14 @@ function renderProjectMap(scan) {
849
1059
  lines.push('## Docs');
850
1060
  lines.push(`- README present: ${scan.docs.has_readme ? 'yes' : 'no'}`);
851
1061
  lines.push(`- Docs files: ${scan.docs.files.length > 0 ? scan.docs.files.join(', ') : 'none detected'}`);
1062
+ lines.push(`- Decision log: ${hasDecisionLog ? 'present' : 'missing'}`);
1063
+ lines.push(`- AI onboarding prompt: ${hasAiPrompt ? 'present' : 'missing'}`);
1064
+
1065
+ lines.push('');
1066
+ lines.push('## High-Signal Files');
1067
+ for (const file of highSignalFiles) {
1068
+ lines.push(`- ${file}`);
1069
+ }
852
1070
 
853
1071
  lines.push('');
854
1072
  lines.push('## Risks');
@@ -870,6 +1088,16 @@ function renderProjectMap(scan) {
870
1088
  lines.push('- None');
871
1089
  }
872
1090
 
1091
+ lines.push('');
1092
+ lines.push('## Do Not Read First');
1093
+ if (scan.skipped_paths.length > 0) {
1094
+ for (const skippedPath of scan.skipped_paths) {
1095
+ lines.push(`- ${skippedPath}`);
1096
+ }
1097
+ } else {
1098
+ lines.push('- None detected, but still prioritize docs and config files before source trees.');
1099
+ }
1100
+
873
1101
  lines.push('');
874
1102
  return lines.join('\n');
875
1103
  }
@@ -888,7 +1116,7 @@ function writeProjectScanArtifacts(projectRoot, scan) {
888
1116
  }
889
1117
 
890
1118
  function runAnalyze(targetDir) {
891
- const projectRoot = path.resolve(process.cwd(), targetDir);
1119
+ const projectRoot = resolveTargetRoot(process.cwd(), targetDir);
892
1120
 
893
1121
  if (!fs.existsSync(projectRoot)) {
894
1122
  throw new Error(formatError(`target directory does not exist: ${projectRoot}`));
@@ -896,22 +1124,26 @@ function runAnalyze(targetDir) {
896
1124
 
897
1125
  const scan = buildProjectScan(projectRoot);
898
1126
  const artifacts = writeProjectScanArtifacts(projectRoot, scan);
899
- updateQuiverStateForAnalyze(projectRoot);
1127
+ updateStateForAnalyze(projectRoot, CLI_VERSION);
900
1128
 
901
1129
  console.log(`Project analysis completed for ${projectRoot}`);
902
- console.log(`Wrote ${path.relative(projectRoot, artifacts.jsonPath)}`);
903
- console.log(`Wrote ${path.relative(projectRoot, artifacts.mdPath)}`);
1130
+ console.log(`Wrote ${relativePosixPath(projectRoot, artifacts.jsonPath)}`);
1131
+ console.log(`Wrote ${relativePosixPath(projectRoot, artifacts.mdPath)}`);
904
1132
  console.log(`Detected primary stack: ${scan.stack.primary}`);
905
1133
  console.log(`Detected package manager: ${scan.project.package_manager}`);
906
1134
  }
907
1135
 
908
1136
  function runMigrate(targetDir) {
909
- const projectRoot = path.resolve(process.cwd(), targetDir);
1137
+ const projectRoot = resolveTargetRoot(process.cwd(), targetDir);
910
1138
 
911
1139
  if (!fs.existsSync(projectRoot)) {
912
1140
  throw new Error(formatError(`target directory does not exist: ${projectRoot}`));
913
1141
  }
914
1142
 
1143
+ if (!hasQuiverInitializationEvidence(projectRoot)) {
1144
+ throw new Error(formatError('migrate requires a project previously initialized by Quiver.\nRun: npx create-quiver --name "Project Name"'));
1145
+ }
1146
+
915
1147
  const packageJson = loadPackageJson(projectRoot);
916
1148
  const projectName = packageJson.name || path.basename(projectRoot) || 'Quiver Project';
917
1149
  const packageRoot = path.resolve(__dirname, '../..');
@@ -920,15 +1152,13 @@ function runMigrate(targetDir) {
920
1152
  try {
921
1153
  const templateRoot = packTemplate(packageRoot, tempRoot);
922
1154
  mergeDirectoryTree(templateRoot, path.join(projectRoot, 'docs-template'));
923
- const migrationOutput = runInitDocsWithMode(projectRoot, projectName, 'migrate');
924
- updateQuiverStateForMigrate(projectRoot, projectName);
925
-
926
- if (migrationOutput.trim().length > 0) {
927
- process.stdout.write(migrationOutput);
928
- if (!migrationOutput.endsWith('\n')) {
929
- process.stdout.write('\n');
930
- }
931
- }
1155
+ initializeProjectDocs({
1156
+ projectRoot,
1157
+ projectName,
1158
+ cliVersion: CLI_VERSION,
1159
+ migrateMode: true,
1160
+ });
1161
+ updateStateForMigrate(projectRoot, projectName, CLI_VERSION);
932
1162
 
933
1163
  console.log(`Quiver migration completed for ${projectRoot}`);
934
1164
  console.log('Missing workflow files were restored without overwriting existing project files.');
@@ -938,12 +1168,16 @@ function runMigrate(targetDir) {
938
1168
  }
939
1169
 
940
1170
  function runDoctor(targetDir) {
941
- const projectRoot = path.resolve(process.cwd(), targetDir);
1171
+ const projectRoot = resolveTargetRoot(process.cwd(), targetDir);
942
1172
 
943
1173
  if (!fs.existsSync(projectRoot)) {
944
1174
  throw new Error(formatError(`target directory does not exist: ${projectRoot}`));
945
1175
  }
946
1176
 
1177
+ if (!hasQuiverInitializationEvidence(projectRoot)) {
1178
+ throw new Error(formatError('doctor requires a project previously initialized by Quiver.\nRun init first: npx create-quiver --name "Project Name"'));
1179
+ }
1180
+
947
1181
  const generatedSpecs = listGeneratedSpecDirs(projectRoot);
948
1182
  if (generatedSpecs.length !== 1) {
949
1183
  throw new Error(formatError(`expected exactly one generated spec directory, found ${generatedSpecs.length || 0}`));
@@ -951,6 +1185,7 @@ function runDoctor(targetDir) {
951
1185
 
952
1186
  const projectSlug = generatedSpecs[0];
953
1187
  const requiredFiles = [
1188
+ 'AGENTS.md',
954
1189
  'README.md',
955
1190
  'docs/INDEX.md',
956
1191
  'docs/AI_CONTEXT.md',
@@ -984,11 +1219,26 @@ function runDoctor(targetDir) {
984
1219
  const missingFiles = assertFilesExist(projectRoot, requiredFiles);
985
1220
  const nonExecutableScripts = assertExecutablesExist(projectRoot, requiredExecutables);
986
1221
  const pkg = loadPackageJson(projectRoot);
987
- const requiredScripts = ['check:slice', 'check:pr', 'start:slice', 'cleanup:slice', 'migrate'];
988
- const missingScripts = requiredScripts.filter((name) => typeof pkg.scripts?.[name] !== 'string');
1222
+ const workflowScriptGroups = [
1223
+ { label: 'migrate', node: 'quiver:migrate', legacy: 'migrate' },
1224
+ { label: 'start-slice', node: 'quiver:start-slice', legacy: 'start:slice' },
1225
+ { label: 'check-slice', node: 'quiver:check-slice', legacy: 'check:slice' },
1226
+ { label: 'check-pr', node: 'quiver:check-pr', legacy: 'check:pr' },
1227
+ { label: 'cleanup-slice', node: 'quiver:cleanup-slice', legacy: 'cleanup:slice' },
1228
+ { label: 'check-scope', node: 'quiver:check-scope', legacy: 'check:scope' },
1229
+ { label: 'refresh-active-slices', node: 'quiver:refresh-active-slices', legacy: 'refresh:active-slices' },
1230
+ ];
1231
+ const missingScripts = workflowScriptGroups
1232
+ .filter((group) => typeof pkg.scripts?.[group.node] !== 'string' && typeof pkg.scripts?.[group.legacy] !== 'string')
1233
+ .map((group) => `${group.node} (or legacy ${group.legacy})`);
1234
+ const legacyOnlyScripts = workflowScriptGroups
1235
+ .filter((group) => typeof pkg.scripts?.[group.node] !== 'string' && typeof pkg.scripts?.[group.legacy] === 'string')
1236
+ .map((group) => group.label);
1237
+ const missingNodeNativeScripts = ['quiver:migrate', 'quiver:analyze', 'quiver:doctor']
1238
+ .filter((name) => typeof pkg.scripts?.[name] !== 'string');
989
1239
  const hasScanArtifacts = fs.existsSync(path.join(projectRoot, 'docs', 'PROJECT_SCAN.json'))
990
1240
  && fs.existsSync(path.join(projectRoot, 'docs', 'PROJECT_MAP.md'));
991
- const quiverState = readQuiverState(projectRoot);
1241
+ const quiverState = readState(projectRoot);
992
1242
  const hasQuiverState = Boolean(quiverState);
993
1243
  const stateWarnings = hasQuiverState ? [] : ['missing Quiver state metadata: .quiver/state.json'];
994
1244
  const migrationProblems = [
@@ -996,9 +1246,10 @@ function runDoctor(targetDir) {
996
1246
  ...nonExecutableScripts.map((file) => `missing executable bit: ${file}`),
997
1247
  ...missingScripts.map((name) => `missing package.json script: ${name}`),
998
1248
  ];
1249
+ const softWarnings = collectDoctorWarnings(projectRoot);
999
1250
 
1000
1251
  if (migrationProblems.length > 0) {
1001
- throw new Error(formatError(`doctor failed:\n- ${migrationProblems.join('\n- ')}\n- Run migration first: npx create-quiver migrate --dir .`));
1252
+ throw new Error(formatError(`doctor failed:\n- ${migrationProblems.join('\n- ')}\n- Run migration first: npx create-quiver migrate`));
1002
1253
  }
1003
1254
 
1004
1255
  console.log(`Quiver doctor passed for ${projectRoot}`);
@@ -1007,16 +1258,26 @@ function runDoctor(targetDir) {
1007
1258
  for (const warning of stateWarnings) {
1008
1259
  console.log(`- Warning: ${warning}`);
1009
1260
  }
1261
+ for (const scriptName of missingNodeNativeScripts) {
1262
+ console.log(`- Warning: missing Node-native script: ${scriptName}`);
1263
+ }
1264
+ if (legacyOnlyScripts.length > 0) {
1265
+ console.log(`- Warning: legacy Bash workflow scripts detected for ${legacyOnlyScripts.join(', ')}. Run npx create-quiver migrate to add quiver:* npm scripts.`);
1266
+ }
1267
+ for (const warning of softWarnings) {
1268
+ console.log(`- Warning: ${warning}`);
1269
+ }
1010
1270
  if (!hasQuiverState) {
1011
- console.log('- Run migration first: npx create-quiver migrate --dir .');
1271
+ console.log('- Run migration first: npx create-quiver migrate');
1012
1272
  } else if (!hasScanArtifacts) {
1013
- console.log('- Analyze the project first: npx create-quiver analyze --dir .');
1273
+ console.log('- Analyze the project first: npx create-quiver analyze');
1014
1274
  } else {
1015
- console.log('- Ask your AI agent: Read docs/AI_ONBOARDING_PROMPT.md and execute it.');
1275
+ console.log('- Ask your AI agent: Read AGENTS.md, then docs/AI_ONBOARDING_PROMPT.md and execute it.');
1016
1276
  }
1017
- console.log(`- Start a slice: bash tools/scripts/start-slice.sh specs/${projectSlug}/slices/slice-template/slice.json`);
1018
- console.log('- Validate a slice: bash tools/scripts/check-slice-readiness.sh');
1019
- console.log('- Validate the PR gate: bash tools/scripts/check-pr-readiness.sh');
1277
+ console.log('- Check the next ready slice: npx create-quiver next');
1278
+ console.log(`- Start a slice: npx create-quiver start-slice specs/${projectSlug}/slices/slice-template/slice.json`);
1279
+ console.log(`- Validate a slice: npx create-quiver check-slice specs/${projectSlug}/slices/slice-template/slice.json`);
1280
+ console.log(`- Validate the PR gate: npx create-quiver check-pr specs/${projectSlug}/slices/slice-template/slice.json`);
1020
1281
  }
1021
1282
 
1022
1283
  function printInitNextSteps(targetDir, projectName) {
@@ -1024,10 +1285,10 @@ function printInitNextSteps(targetDir, projectName) {
1024
1285
 
1025
1286
  console.log('');
1026
1287
  console.log('Next steps:');
1027
- console.log(`- Review ${path.join(targetDir, 'docs', 'INDEX.md')}`);
1288
+ console.log(`- Review AGENTS.md, then ${path.join(targetDir, 'docs', 'INDEX.md')}`);
1028
1289
  console.log(`- Review ${path.join(targetDir, 'docs', 'WORKFLOW.md')}`);
1029
1290
  console.log(`- Create your first slice from ${path.join(targetDir, 'specs', projectSlug, 'slices', 'slice-template', 'slice.json')}`);
1030
- console.log(`- Launch slice work with ${path.join(targetDir, 'tools', 'scripts', 'start-slice.sh')}`);
1291
+ console.log(`- Launch slice work with npx create-quiver start-slice specs/${projectSlug}/slices/slice-template/slice.json`);
1031
1292
  }
1032
1293
 
1033
1294
  async function run(argv) {
@@ -1043,6 +1304,37 @@ async function run(argv) {
1043
1304
  return;
1044
1305
  }
1045
1306
 
1307
+ if (args.mode === 'plan') {
1308
+ runPlan(process.cwd(), {
1309
+ json: args.json,
1310
+ onlyReady: args.onlyReady,
1311
+ specSlug: args.specSlug,
1312
+ unicode: args.unicode,
1313
+ });
1314
+ return;
1315
+ }
1316
+
1317
+ if (args.mode === 'graph') {
1318
+ runGraph(process.cwd(), {
1319
+ format: args.format,
1320
+ json: args.json,
1321
+ level: args.level,
1322
+ showConflicts: args.showConflicts,
1323
+ unicode: args.unicode,
1324
+ });
1325
+ return;
1326
+ }
1327
+
1328
+ if (args.mode === 'next') {
1329
+ await runNext(process.cwd(), {
1330
+ allReady: args.allReady,
1331
+ autoStart: args.autoStart,
1332
+ json: args.json,
1333
+ specSlug: args.specSlug,
1334
+ });
1335
+ return;
1336
+ }
1337
+
1046
1338
  if (args.mode === 'migrate') {
1047
1339
  runMigrate(args.targetDir);
1048
1340
  return;
@@ -1053,8 +1345,66 @@ async function run(argv) {
1053
1345
  return;
1054
1346
  }
1055
1347
 
1348
+ if (args.mode === 'start-slice') {
1349
+ startSlice(path.resolve(process.cwd(), args.targetDir), { allowDraft: args.allowDraft });
1350
+ return;
1351
+ }
1352
+
1353
+ if (args.mode === 'check-slice') {
1354
+ checkSliceReadiness(path.resolve(process.cwd(), args.targetDir), {
1355
+ gate: args.gate,
1356
+ strictOverlap: args.strictOverlap,
1357
+ });
1358
+ return;
1359
+ }
1360
+
1361
+ if (args.mode === 'check-pr') {
1362
+ checkPrReadiness(path.resolve(process.cwd(), args.targetDir));
1363
+ return;
1364
+ }
1365
+
1366
+ if (args.mode === 'check-handoff') {
1367
+ const repoRoot = process.cwd();
1368
+ const handoffInput = args.targetDir;
1369
+ if (!handoffInput || handoffInput === '.') {
1370
+ throw new Error(formatError('missing handoff path. Use: npx create-quiver check-handoff specs/<spec-slug>/HANDOFF.md'));
1371
+ }
1372
+ const resolved = checkHandoff(handoffInput, repoRoot);
1373
+ console.log(`PASS: Handoff validated at ${resolved.relativePath}`);
1374
+ return;
1375
+ }
1376
+
1377
+ if (args.mode === 'new-handoff') {
1378
+ const repoRoot = process.cwd();
1379
+ const handoffSlug = args.targetDir;
1380
+ const resolved = scaffoldHandoff(handoffSlug, repoRoot);
1381
+ console.log(`PASS: Handoff scaffolded at ${resolved.relativePath}`);
1382
+ return;
1383
+ }
1384
+
1385
+ if (args.mode === 'cleanup-slice') {
1386
+ cleanupSlice(path.resolve(process.cwd(), args.targetDir), {
1387
+ closeBaseline: args.closeBaseline,
1388
+ discard: args.discard,
1389
+ dryRun: args.dryRun,
1390
+ force: args.force,
1391
+ });
1392
+ return;
1393
+ }
1394
+
1395
+ if (args.mode === 'check-scope') {
1396
+ checkScope(path.resolve(process.cwd(), args.targetDir), { strict: args.strict });
1397
+ return;
1398
+ }
1399
+
1400
+ if (args.mode === 'refresh-active-slices') {
1401
+ const outputPath = refreshActiveSlicesBoard(path.resolve(process.cwd(), '.'));
1402
+ console.log(`Active slices refreshed: ${outputPath}`);
1403
+ return;
1404
+ }
1405
+
1056
1406
  const packageRoot = path.resolve(__dirname, '../..');
1057
- const targetDir = path.resolve(process.cwd(), args.targetDir);
1407
+ const targetDir = resolveTargetRoot(process.cwd(), args.targetDir);
1058
1408
  const projectName = args.projectName || path.basename(targetDir) || 'Quiver Project';
1059
1409
  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'quiver-create-'));
1060
1410
 
@@ -1073,5 +1423,8 @@ async function run(argv) {
1073
1423
  }
1074
1424
 
1075
1425
  module.exports = {
1426
+ runAnalyze,
1427
+ runDoctor,
1428
+ runMigrate,
1076
1429
  run,
1077
1430
  };