create-quiver 0.12.0 → 0.12.1

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 (109) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +49 -17
  3. package/README_FOR_AI.md +31 -29
  4. package/ROADMAP.md +15 -3
  5. package/docs/AI_ONBOARDING_PROMPT.md.template +7 -1
  6. package/docs/COMMANDS.md.template +44 -18
  7. package/docs/STATUS.md.template +5 -1
  8. package/docs/WORKFLOW.md.template +13 -11
  9. package/package.json +9 -3
  10. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/EVIDENCE_REPORT.md +293 -0
  11. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/EXECUTION_PLAN.md +58 -0
  12. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/SPEC.md +242 -0
  13. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/STATUS.md +35 -0
  14. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/pr.md +77 -0
  15. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +34 -0
  16. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
  17. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/slice.json +52 -0
  18. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/CLOSURE_BRIEF.md +36 -0
  19. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/EXECUTION_BRIEF.md +52 -0
  20. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/slice.json +56 -0
  21. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/CLOSURE_BRIEF.md +43 -0
  22. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/EXECUTION_BRIEF.md +54 -0
  23. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/slice.json +52 -0
  24. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/CLOSURE_BRIEF.md +35 -0
  25. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/EXECUTION_BRIEF.md +53 -0
  26. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/slice.json +54 -0
  27. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/CLOSURE_BRIEF.md +34 -0
  28. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/EXECUTION_BRIEF.md +54 -0
  29. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/slice.json +52 -0
  30. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/CLOSURE_BRIEF.md +34 -0
  31. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/EXECUTION_BRIEF.md +54 -0
  32. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/slice.json +53 -0
  33. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/CLOSURE_BRIEF.md +33 -0
  34. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/EXECUTION_BRIEF.md +56 -0
  35. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/slice.json +55 -0
  36. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/CLOSURE_BRIEF.md +33 -0
  37. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/EXECUTION_BRIEF.md +54 -0
  38. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/slice.json +52 -0
  39. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/CLOSURE_BRIEF.md +39 -0
  40. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/EXECUTION_BRIEF.md +56 -0
  41. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/slice.json +53 -0
  42. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/CLOSURE_BRIEF.md +38 -0
  43. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/EXECUTION_BRIEF.md +57 -0
  44. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/slice.json +52 -0
  45. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/CLOSURE_BRIEF.md +39 -0
  46. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/EXECUTION_BRIEF.md +55 -0
  47. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/slice.json +56 -0
  48. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/CLOSURE_BRIEF.md +36 -0
  49. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/EXECUTION_BRIEF.md +54 -0
  50. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/slice.json +53 -0
  51. package/specs/quiver-v26-0121-smoke-hardening/EVIDENCE_REPORT.md +208 -0
  52. package/specs/quiver-v26-0121-smoke-hardening/EXECUTION_PLAN.md +57 -0
  53. package/specs/quiver-v26-0121-smoke-hardening/SPEC.md +137 -0
  54. package/specs/quiver-v26-0121-smoke-hardening/STATUS.md +32 -0
  55. package/specs/quiver-v26-0121-smoke-hardening/pr.md +96 -0
  56. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/CLOSURE_BRIEF.md +35 -0
  57. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/EXECUTION_BRIEF.md +55 -0
  58. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/slice.json +73 -0
  59. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/CLOSURE_BRIEF.md +38 -0
  60. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/EXECUTION_BRIEF.md +51 -0
  61. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/slice.json +76 -0
  62. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/CLOSURE_BRIEF.md +37 -0
  63. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/EXECUTION_BRIEF.md +52 -0
  64. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/slice.json +75 -0
  65. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/CLOSURE_BRIEF.md +37 -0
  66. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/EXECUTION_BRIEF.md +53 -0
  67. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/slice.json +77 -0
  68. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/CLOSURE_BRIEF.md +35 -0
  69. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/EXECUTION_BRIEF.md +52 -0
  70. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/slice.json +77 -0
  71. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/CLOSURE_BRIEF.md +34 -0
  72. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/EXECUTION_BRIEF.md +54 -0
  73. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/slice.json +84 -0
  74. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/CLOSURE_BRIEF.md +35 -0
  75. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/EXECUTION_BRIEF.md +53 -0
  76. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/slice.json +82 -0
  77. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/CLOSURE_BRIEF.md +35 -0
  78. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/EXECUTION_BRIEF.md +55 -0
  79. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/slice.json +92 -0
  80. package/src/create-quiver/commands/ai.js +577 -27
  81. package/src/create-quiver/commands/flow.js +6 -5
  82. package/src/create-quiver/commands/graph.js +6 -4
  83. package/src/create-quiver/commands/plan.js +3 -3
  84. package/src/create-quiver/index.js +328 -12
  85. package/src/create-quiver/lib/actionable-error.js +27 -0
  86. package/src/create-quiver/lib/agent-profiles.js +1 -1
  87. package/src/create-quiver/lib/ai/context-packs.js +4 -0
  88. package/src/create-quiver/lib/ai/execution-plan.js +7 -1
  89. package/src/create-quiver/lib/ai/executor.js +270 -20
  90. package/src/create-quiver/lib/ai/export-state.js +534 -0
  91. package/src/create-quiver/lib/ai/github.js +83 -0
  92. package/src/create-quiver/lib/ai/onboarding-template.js +215 -2
  93. package/src/create-quiver/lib/ai/plan-review.js +5 -2
  94. package/src/create-quiver/lib/ai/providers.js +4 -3
  95. package/src/create-quiver/lib/ai/run-state.js +414 -0
  96. package/src/create-quiver/lib/ai/spec-generator.js +12 -0
  97. package/src/create-quiver/lib/ai/spec-templates.js +78 -9
  98. package/src/create-quiver/lib/approvals.js +22 -3
  99. package/src/create-quiver/lib/demo.js +189 -14
  100. package/src/create-quiver/lib/doctor.js +75 -0
  101. package/src/create-quiver/lib/handoff.js +81 -12
  102. package/src/create-quiver/lib/init-docs.js +24 -6
  103. package/src/create-quiver/lib/init-layout.js +8 -0
  104. package/src/create-quiver/lib/json.js +53 -3
  105. package/src/create-quiver/lib/readiness.js +18 -3
  106. package/src/create-quiver/lib/scope.js +50 -7
  107. package/src/create-quiver/lib/slice-graph.js +138 -38
  108. package/src/create-quiver/lib/slice.js +6 -1
  109. package/src/create-quiver/lib/spec-worktrees.js +16 -2
@@ -114,6 +114,119 @@ function markPendingConfirmation(value) {
114
114
  return `Pending confirmation: ${text}`;
115
115
  }
116
116
 
117
+ function readJsonIfExists(filePath) {
118
+ if (!fs.existsSync(filePath)) {
119
+ return null;
120
+ }
121
+
122
+ try {
123
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
124
+ } catch {
125
+ return null;
126
+ }
127
+ }
128
+
129
+ function detectPackageManager(projectRoot) {
130
+ if (hasPath(projectRoot, 'bun.lockb') || hasPath(projectRoot, 'bun.lock')) return 'bun';
131
+ if (hasPath(projectRoot, 'pnpm-lock.yaml')) return 'pnpm';
132
+ if (hasPath(projectRoot, 'yarn.lock')) return 'yarn';
133
+ return 'npm';
134
+ }
135
+
136
+ function detectSourceDirectories(projectRoot) {
137
+ const names = ['src', 'app', 'apps', 'packages', 'lib', 'server', 'client', 'web'];
138
+ return names.filter((name) => {
139
+ try {
140
+ return fs.statSync(path.join(projectRoot, name)).isDirectory();
141
+ } catch {
142
+ return false;
143
+ }
144
+ });
145
+ }
146
+
147
+ function collectRootNames(projectRoot) {
148
+ try {
149
+ return fs.readdirSync(projectRoot, { withFileTypes: true })
150
+ .filter((entry) => !entry.name.startsWith('.') && entry.name !== 'node_modules')
151
+ .map((entry) => `${entry.name}${entry.isDirectory() ? '/' : ''}`)
152
+ .slice(0, 20);
153
+ } catch {
154
+ return [];
155
+ }
156
+ }
157
+
158
+ function detectStackSummary(packageJson, projectRoot) {
159
+ const dependencies = {
160
+ ...(packageJson?.dependencies || {}),
161
+ ...(packageJson?.devDependencies || {}),
162
+ };
163
+ const signals = [];
164
+
165
+ if (dependencies.next || hasPath(projectRoot, 'next.config.js') || hasPath(projectRoot, 'next.config.mjs')) signals.push('Next.js');
166
+ if (dependencies.vite || hasPath(projectRoot, 'vite.config.js') || hasPath(projectRoot, 'vite.config.ts')) signals.push('Vite');
167
+ if (dependencies.react) signals.push('React');
168
+ if (dependencies.vue) signals.push('Vue');
169
+ if (dependencies.angular || dependencies['@angular/core'] || hasPath(projectRoot, 'angular.json')) signals.push('Angular');
170
+ if (dependencies.svelte || hasPath(projectRoot, 'svelte.config.js')) signals.push('Svelte');
171
+ if (dependencies.express) signals.push('Express');
172
+ if (hasPath(projectRoot, 'pyproject.toml') || hasPath(projectRoot, 'requirements.txt')) signals.push('Python');
173
+ if (hasPath(projectRoot, 'go.mod')) signals.push('Go');
174
+
175
+ return signals.length > 0 ? signals.join(', ') : 'Pending confirmation: no primary stack could be inferred from root signals.';
176
+ }
177
+
178
+ function collectProjectFacts(projectRoot) {
179
+ const packageJson = readJsonIfExists(path.join(projectRoot, 'package.json'));
180
+ const scripts = packageJson?.scripts && typeof packageJson.scripts === 'object' ? packageJson.scripts : {};
181
+ const packageManager = packageJson?.packageManager
182
+ ? String(packageJson.packageManager).split('@')[0]
183
+ : detectPackageManager(projectRoot);
184
+
185
+ return {
186
+ packageJsonPresent: Boolean(packageJson),
187
+ packageManager,
188
+ stackSummary: detectStackSummary(packageJson, projectRoot),
189
+ scripts,
190
+ rootNames: collectRootNames(projectRoot),
191
+ sourceDirectories: detectSourceDirectories(projectRoot),
192
+ commands: {
193
+ install: packageManager === 'pnpm' ? 'pnpm install' : packageManager === 'yarn' ? 'yarn install' : packageManager === 'bun' ? 'bun install' : 'npm install',
194
+ dev: scripts.dev || scripts.start || 'Pending confirmation: no dev/start script detected.',
195
+ build: scripts.build || 'Pending confirmation: no build script detected.',
196
+ test: scripts.test || 'Pending confirmation: no test script detected.',
197
+ lint: scripts.lint || 'Pending confirmation: no lint script detected.',
198
+ },
199
+ };
200
+ }
201
+
202
+ function readProjectMapField(projectRoot, label) {
203
+ const filePath = path.join(projectRoot, 'docs', 'PROJECT_MAP.md');
204
+ if (!fs.existsSync(filePath)) {
205
+ return '';
206
+ }
207
+
208
+ const text = fs.readFileSync(filePath, 'utf8');
209
+ const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
210
+ const match = text.match(new RegExp(`^- ${escaped}:\\s*(.+)$`, 'mi'));
211
+ return match ? match[1].trim() : '';
212
+ }
213
+
214
+ function collectContextContradictions(projectRoot, plan, facts) {
215
+ const contradictions = [];
216
+ const mappedName = readProjectMapField(projectRoot, 'Name');
217
+ const mappedPackageManager = readProjectMapField(projectRoot, 'Package manager');
218
+
219
+ if (mappedName && mappedName !== plan.projectName) {
220
+ contradictions.push(`docs/PROJECT_MAP.md reports project name '${mappedName}', but package/root identity resolves to '${plan.projectName}'.`);
221
+ }
222
+
223
+ if (mappedPackageManager && mappedPackageManager !== facts.packageManager) {
224
+ contradictions.push(`docs/PROJECT_MAP.md reports package manager '${mappedPackageManager}', but current root signals resolve to '${facts.packageManager}'.`);
225
+ }
226
+
227
+ return contradictions.map(markPendingConfirmation);
228
+ }
229
+
117
230
  function formatDocStatusLines(items) {
118
231
  if (!Array.isArray(items) || items.length === 0) {
119
232
  return ['- none'];
@@ -182,6 +295,7 @@ function collectOnboardingContextPlan(projectRoot) {
182
295
  function collectContextPreparationPlan(projectRoot) {
183
296
  const onboardingPlan = collectOnboardingContextPlan(projectRoot);
184
297
  const identity = resolveProjectIdentity(projectRoot);
298
+ const facts = collectProjectFacts(projectRoot);
185
299
  const filesConsidered = CONTEXT_PREP_SOURCE_DOCS.map(([relativePath, reason]) => ({
186
300
  path: relativePath,
187
301
  reason,
@@ -202,8 +316,7 @@ function collectContextPreparationPlan(projectRoot) {
202
316
  ? 'Pending confirmation: docs/INDEX.md is missing, so navigation should stay conservative and index-first.'
203
317
  : null,
204
318
  ]);
205
-
206
- return {
319
+ const plan = {
207
320
  ...onboardingPlan,
208
321
  ...identity,
209
322
  approvedDocPaths: getPreparedContextDocPaths(),
@@ -211,6 +324,12 @@ function collectContextPreparationPlan(projectRoot) {
211
324
  omittedPaths: onboardingPlan.omittedByDefault.slice(),
212
325
  assumptions,
213
326
  risks,
327
+ facts,
328
+ };
329
+
330
+ return {
331
+ ...plan,
332
+ contradictions: collectContextContradictions(projectRoot, plan, facts),
214
333
  };
215
334
  }
216
335
 
@@ -230,6 +349,9 @@ function buildContextPreparationNotes(plan) {
230
349
  '### Risks',
231
350
  ...formatSimpleBullets(plan.risks, 'none'),
232
351
  '',
352
+ '### Contradictions',
353
+ ...formatSimpleBullets(plan.contradictions, 'none'),
354
+ '',
233
355
  '### Omitted Paths',
234
356
  ...formatSimpleBullets(plan.omittedPaths, 'none'),
235
357
  ];
@@ -247,6 +369,76 @@ function readTemplate(relativePath) {
247
369
  return fs.readFileSync(path.join(PACKAGE_ROOT, relativePath), 'utf8');
248
370
  }
249
371
 
372
+ function renderProjectMapDraft(plan) {
373
+ const facts = plan.facts;
374
+ const lines = [
375
+ '# Project Map',
376
+ '',
377
+ 'This file was prepared by `npx create-quiver ai prepare-context`.',
378
+ 'Run `npx create-quiver analyze` to refresh it with a deeper repository scan.',
379
+ '',
380
+ '## Project',
381
+ `- Name: ${plan.projectName}`,
382
+ `- Slug: ${plan.projectSlug}`,
383
+ `- Package manager: ${facts.packageManager}`,
384
+ `- package.json present: ${facts.packageJsonPresent ? 'yes' : 'no'}`,
385
+ `- Stack summary: ${facts.stackSummary}`,
386
+ '',
387
+ '## Commands',
388
+ `- Install: ${facts.commands.install}`,
389
+ `- Dev: ${facts.commands.dev}`,
390
+ `- Build: ${facts.commands.build}`,
391
+ `- Test: ${facts.commands.test}`,
392
+ `- Lint: ${facts.commands.lint}`,
393
+ '',
394
+ '## Structure',
395
+ `- Source directories: ${facts.sourceDirectories.length > 0 ? facts.sourceDirectories.join(', ') : 'Pending confirmation: no common source directory detected.'}`,
396
+ `- Root entries: ${facts.rootNames.length > 0 ? facts.rootNames.join(', ') : 'Pending confirmation: root entries could not be listed.'}`,
397
+ '',
398
+ '## Assumptions',
399
+ ...formatSimpleBullets(plan.assumptions, 'none'),
400
+ '',
401
+ '## Risks',
402
+ ...formatSimpleBullets(plan.risks, 'none'),
403
+ '',
404
+ '## Contradictions',
405
+ ...formatSimpleBullets(plan.contradictions, 'none'),
406
+ ];
407
+
408
+ return `${lines.join('\n')}\n`;
409
+ }
410
+
411
+ function renderArchitectureDraft(plan) {
412
+ const facts = plan.facts;
413
+ const lines = [
414
+ `# ${plan.projectName} Architecture`,
415
+ '',
416
+ 'This document captures only what Quiver can infer safely from repository structure and docs.',
417
+ '',
418
+ '## Current Understanding',
419
+ `- Stack: ${facts.stackSummary}`,
420
+ `- Source directories: ${facts.sourceDirectories.length > 0 ? facts.sourceDirectories.join(', ') : 'Pending confirmation: no common source directory detected.'}`,
421
+ `- Package manager: ${facts.packageManager}`,
422
+ '',
423
+ '## Boundaries',
424
+ '- TODO: confirm application boundaries with the team.',
425
+ '- Pending confirmation: no architecture decision should be treated as approved unless it appears in `docs/DECISIONS.md` or an approved spec.',
426
+ '',
427
+ '## Commands That Shape Architecture',
428
+ `- Build: ${facts.commands.build}`,
429
+ `- Test: ${facts.commands.test}`,
430
+ `- Lint: ${facts.commands.lint}`,
431
+ '',
432
+ '## Risks',
433
+ ...formatSimpleBullets(plan.risks, 'none'),
434
+ '',
435
+ '## Contradictions',
436
+ ...formatSimpleBullets(plan.contradictions, 'none'),
437
+ ];
438
+
439
+ return `${lines.join('\n')}\n`;
440
+ }
441
+
250
442
  function buildContextPreparationDrafts(projectRoot) {
251
443
  const plan = collectContextPreparationPlan(projectRoot);
252
444
  const currentDate = new Date().toISOString().slice(0, 10);
@@ -257,6 +449,11 @@ function buildContextPreparationDrafts(projectRoot) {
257
449
  estado: 'En preparación',
258
450
  fase: 'Fase 0',
259
451
  progress: 0,
452
+ packageManager: plan.facts.packageManager,
453
+ stackSummary: plan.facts.stackSummary,
454
+ primaryInstall: plan.facts.commands.install,
455
+ primaryDev: plan.facts.commands.dev,
456
+ primaryTest: plan.facts.commands.test,
260
457
  };
261
458
  const notes = buildContextPreparationNotes(plan);
262
459
  const decisionSection = [
@@ -266,6 +463,14 @@ function buildContextPreparationDrafts(projectRoot) {
266
463
  `| ${currentDate} | ai prepare-context must remain docs-only | Keeps context prep from touching product code. | Broader write targets | Draft generation stays safe and reviewable |`,
267
464
  ].join('\n');
268
465
  const docs = [
466
+ {
467
+ path: 'docs/INDEX.md',
468
+ content: appendNotes(renderTemplate(readTemplate('docs/INDEX.md.template'), replacements), notes),
469
+ },
470
+ {
471
+ path: 'docs/PROJECT_MAP.md',
472
+ content: appendNotes(renderProjectMapDraft(plan), notes),
473
+ },
269
474
  {
270
475
  path: 'docs/AI_CONTEXT.md',
271
476
  content: appendNotes(renderTemplate(readTemplate('docs/AI_CONTEXT.md.template'), replacements), notes),
@@ -278,6 +483,14 @@ function buildContextPreparationDrafts(projectRoot) {
278
483
  path: 'docs/CONTEXTO.md',
279
484
  content: appendNotes(renderTemplate(readTemplate('docs/CONTEXTO.md.template'), replacements), notes),
280
485
  },
486
+ {
487
+ path: 'docs/WORKFLOW.md',
488
+ content: appendNotes(renderTemplate(readTemplate('docs/WORKFLOW.md.template'), replacements), notes),
489
+ },
490
+ {
491
+ path: 'docs/ARCHITECTURE.md',
492
+ content: appendNotes(renderArchitectureDraft(plan), notes),
493
+ },
281
494
  {
282
495
  path: 'docs/STATUS.md',
283
496
  content: appendNotes(renderTemplate(readTemplate('docs/STATUS.md.template'), replacements), notes),
@@ -208,8 +208,11 @@ function assertPlanReviewed(projectRoot) {
208
208
  if (review.status !== 'reviewed') {
209
209
  const nextCommand = review.status === 'unapproved'
210
210
  ? 'npx create-quiver ai approve --phase technical-plan --version <n>'
211
- : 'npx create-quiver ai review-plan';
212
- throw new Error(formatError(`ai plan phase 'spec' requires a reviewed and approved technical-plan input; current review status: ${review.status}. Run \`${nextCommand}\`.`));
211
+ : 'npx create-quiver ai review-plan --dry-run';
212
+ const followUp = review.status === 'unapproved'
213
+ ? ''
214
+ : ' Preview the review first, then run `npx create-quiver ai review-plan` to persist it.';
215
+ throw new Error(formatError(`ai plan phase 'spec' requires a reviewed and approved technical-plan input; current review status: ${review.status}. Run \`${nextCommand}\`.${followUp}`));
213
216
  }
214
217
  return review;
215
218
  }
@@ -2,6 +2,7 @@ const fs = require('node:fs');
2
2
  const { spawn } = require('node:child_process');
3
3
 
4
4
  const { finalizePromptTransport, preparePromptTransport, describePromptTransport } = require('./prompt-transport');
5
+ const { redactSecrets } = require('../evidence');
5
6
 
6
7
  const SUPPORTED_PROVIDERS = ['codex', 'claude', 'gemini'];
7
8
 
@@ -107,7 +108,7 @@ function serializeError(error, provider, invocation) {
107
108
 
108
109
  return {
109
110
  code: error.code || 'PROVIDER_ERROR',
110
- message: error.message || String(error),
111
+ message: redactSecrets(error.message || String(error)),
111
112
  provider,
112
113
  command: invocation.command,
113
114
  args: invocation.args.slice(),
@@ -178,8 +179,8 @@ function runSpawn(command, args, options = {}) {
178
179
  ok: payload.exitCode === 0,
179
180
  exitCode: payload.exitCode,
180
181
  signal: payload.signal || null,
181
- stdout,
182
- stderr,
182
+ stdout: redactSecrets(stdout),
183
+ stderr: redactSecrets(stderr),
183
184
  error: payload.error ? serializeError(payload.error, options.provider, options.invocation) : null,
184
185
  });
185
186
  };