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
@@ -0,0 +1,205 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { relativePosixPath } = require('../lib/paths');
4
+ const { buildGraph, readAllSlices, topoSort } = require('../lib/slice-graph');
5
+
6
+ const EXCLUDED_STATUSES = new Set(['completed', 'skipped', 'cancelled']);
7
+
8
+ function toHourCount(value) {
9
+ const parsed = Number(value);
10
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
11
+ }
12
+
13
+ function compareRefs(left, right) {
14
+ return String(left || '').localeCompare(String(right || ''));
15
+ }
16
+
17
+ function sliceToPlanItem(repoRoot, slice, index, readySet) {
18
+ return {
19
+ index,
20
+ ref: slice.ref,
21
+ spec_family: slice.specFamily || '',
22
+ spec_slug: slice.specSlug,
23
+ slice_id: slice.sliceId,
24
+ slice_path: relativePosixPath(repoRoot, slice.slicePath),
25
+ ticket: slice.ticket || '',
26
+ title: slice.title || slice.sliceId,
27
+ status: slice.status || 'draft',
28
+ hours: toHourCount(slice.json?.estimated_hours),
29
+ files: Array.isArray(slice.files) ? slice.files : [],
30
+ depends_on: Array.isArray(slice.depends_on) ? slice.depends_on : [],
31
+ ready: readySet.has(slice.ref),
32
+ };
33
+ }
34
+
35
+ function buildSubgraph(graph, refs) {
36
+ const refSet = new Set(refs);
37
+ return {
38
+ nodes: graph.nodes.filter((node) => refSet.has(node.ref)),
39
+ edges: graph.edges.filter((edge) => refSet.has(edge.from) && refSet.has(edge.to)),
40
+ cycles: graph.cycles.filter((cycle) => cycle.every((ref) => refSet.has(ref))),
41
+ };
42
+ }
43
+
44
+ function buildReadySet(graph, pendingRefs) {
45
+ const pendingSet = new Set(pendingRefs);
46
+ const incomingCounts = new Map(pendingRefs.map((ref) => [ref, 0]));
47
+
48
+ for (const edge of graph.edges) {
49
+ if (!pendingSet.has(edge.from) || !pendingSet.has(edge.to)) {
50
+ continue;
51
+ }
52
+ incomingCounts.set(edge.to, (incomingCounts.get(edge.to) || 0) + 1);
53
+ }
54
+
55
+ return new Set(Array.from(incomingCounts.entries()).filter(([, count]) => count === 0).map(([ref]) => ref));
56
+ }
57
+
58
+ function buildCriticalPath(graph, refs) {
59
+ if (refs.length === 0) {
60
+ return [];
61
+ }
62
+
63
+ const subgraph = buildSubgraph(graph, refs);
64
+ const ordered = topoSort(subgraph);
65
+ const incoming = new Map(ordered.map((node) => [node.ref, []]));
66
+
67
+ for (const edge of subgraph.edges) {
68
+ if (!incoming.has(edge.to)) {
69
+ continue;
70
+ }
71
+ incoming.get(edge.to).push(edge.from);
72
+ }
73
+
74
+ const best = new Map();
75
+
76
+ for (const node of ordered) {
77
+ const hours = toHourCount(node.json?.estimated_hours);
78
+ const predecessors = incoming.get(node.ref) || [];
79
+ let candidate = {
80
+ hours,
81
+ path: [node.ref],
82
+ };
83
+
84
+ for (const pred of predecessors) {
85
+ const prev = best.get(pred);
86
+ if (!prev) {
87
+ continue;
88
+ }
89
+ const nextCandidate = {
90
+ hours: prev.hours + hours,
91
+ path: [...prev.path, node.ref],
92
+ };
93
+ const pathLabel = nextCandidate.path.join('>');
94
+ const bestLabel = candidate.path.join('>');
95
+ if (nextCandidate.hours > candidate.hours || (nextCandidate.hours === candidate.hours && compareRefs(pathLabel, bestLabel) < 0)) {
96
+ candidate = nextCandidate;
97
+ }
98
+ }
99
+
100
+ best.set(node.ref, candidate);
101
+ }
102
+
103
+ let winner = null;
104
+ for (const node of ordered) {
105
+ const candidate = best.get(node.ref);
106
+ if (!candidate) {
107
+ continue;
108
+ }
109
+ if (!winner || candidate.hours > winner.hours || (candidate.hours === winner.hours && compareRefs(candidate.path.join('>'), winner.path.join('>')) < 0)) {
110
+ winner = candidate;
111
+ }
112
+ }
113
+
114
+ return winner ? winner.path : [];
115
+ }
116
+
117
+ function collectPlan(repoRoot, options = {}) {
118
+ const allSlices = readAllSlices(repoRoot);
119
+ const graph = buildGraph(allSlices);
120
+ const topo = topoSort(graph);
121
+ const excluded = EXCLUDED_STATUSES;
122
+ const specSlug = options.specSlug ? String(options.specSlug).trim() : '';
123
+
124
+ const pendingRefs = new Set(
125
+ graph.nodes
126
+ .filter((node) => !excluded.has(String(node.status || '').toLowerCase()))
127
+ .map((node) => node.ref),
128
+ );
129
+
130
+ const readyRefs = buildReadySet(graph, Array.from(pendingRefs));
131
+
132
+ const selectedNodes = topo.filter((node) => {
133
+ if (!pendingRefs.has(node.ref)) {
134
+ return false;
135
+ }
136
+ if (specSlug && node.specSlug !== specSlug) {
137
+ return false;
138
+ }
139
+ return true;
140
+ });
141
+
142
+ const readyNodes = selectedNodes.filter((node) => readyRefs.has(node.ref));
143
+ const targetNodes = options.onlyReady ? readyNodes : selectedNodes;
144
+ const criticalPath = buildCriticalPath(graph, targetNodes.map((node) => node.ref));
145
+ const totalHours = targetNodes.reduce((sum, node) => sum + toHourCount(node.json?.estimated_hours), 0);
146
+ const plan = targetNodes.map((node, index) => sliceToPlanItem(repoRoot, node, index + 1, readyRefs));
147
+
148
+ return {
149
+ critical_path: criticalPath,
150
+ plan,
151
+ total_hours: totalHours,
152
+ };
153
+ }
154
+
155
+ function formatHumanPlan(report, options = {}) {
156
+ const unicode = Boolean(options.unicode) || /UTF-8/i.test(process.env.LANG || '');
157
+ const title = options.onlyReady ? 'Ready slices' : 'Quiver plan';
158
+ const pathSeparator = unicode ? ' → ' : ' -> ';
159
+ const lines = [title, `Total hours: ${report.total_hours}`, `Critical path: ${report.critical_path.length > 0 ? report.critical_path.join(pathSeparator) : '-'}`, ''];
160
+
161
+ if (report.plan.length === 0) {
162
+ lines.push('No pending slices found.');
163
+ return `${lines.join('\n')}\n`;
164
+ }
165
+
166
+ const rows = report.plan.map((item) => [
167
+ `[${item.index}]`,
168
+ item.ticket || '-',
169
+ item.ref,
170
+ item.title,
171
+ `${item.hours}`,
172
+ item.status,
173
+ ]);
174
+
175
+ const widths = rows[0].map((_, colIndex) => Math.max(
176
+ rows.reduce((max, row) => Math.max(max, row[colIndex].length), 0),
177
+ ['[N]', 'TICKET', 'SPEC/SLICE', 'TITLE', 'HOURS', 'STATUS'][colIndex].length,
178
+ ));
179
+
180
+ lines.push(['[N]', 'TICKET', 'SPEC/SLICE', 'TITLE', 'HOURS', 'STATUS'].map((label, index) => label.padEnd(widths[index])).join(' '));
181
+ lines.push(widths.map((width) => '-'.repeat(width)).join(' '));
182
+
183
+ for (const row of rows) {
184
+ lines.push(row.map((value, index) => value.padEnd(widths[index])).join(' '));
185
+ }
186
+
187
+ return `${lines.join('\n')}\n`;
188
+ }
189
+
190
+ function runPlan(repoRoot, options = {}) {
191
+ const report = collectPlan(repoRoot, options);
192
+ if (options.json) {
193
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
194
+ return report;
195
+ }
196
+
197
+ process.stdout.write(formatHumanPlan(report, options));
198
+ return report;
199
+ }
200
+
201
+ module.exports = {
202
+ collectPlan,
203
+ formatHumanPlan,
204
+ runPlan,
205
+ };