create-quiver 0.15.1 → 0.15.3

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 (136) hide show
  1. package/.github/workflows/ci.yml +3 -0
  2. package/README.md +3 -0
  3. package/README_FOR_AI.md +11 -7
  4. package/docs/CLI_UX_GUIDE.md +16 -2
  5. package/docs/COMMANDS.md.template +16 -4
  6. package/docs/INDEX.md +87 -0
  7. package/docs/WORKFLOW.md.template +4 -4
  8. package/docs/reference/commands.md +23 -5
  9. package/package.json +3 -1
  10. package/specs/quiver-v33-approval-ux-and-planner-progress/EVIDENCE_REPORT.md +93 -0
  11. package/specs/quiver-v33-approval-ux-and-planner-progress/EXECUTION_PLAN.md +83 -0
  12. package/specs/quiver-v33-approval-ux-and-planner-progress/SPEC.md +158 -0
  13. package/specs/quiver-v33-approval-ux-and-planner-progress/STATUS.md +31 -0
  14. package/specs/quiver-v33-approval-ux-and-planner-progress/pr.md +109 -0
  15. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-00-approval-ux-foundation/CLOSURE_BRIEF.md +30 -0
  16. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-00-approval-ux-foundation/EXECUTION_BRIEF.md +56 -0
  17. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-00-approval-ux-foundation/slice.json +65 -0
  18. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-01-approval-candidates-model/CLOSURE_BRIEF.md +19 -0
  19. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-01-approval-candidates-model/EXECUTION_BRIEF.md +51 -0
  20. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-01-approval-candidates-model/slice.json +74 -0
  21. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-02-approve-interactive-selection/CLOSURE_BRIEF.md +20 -0
  22. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-02-approve-interactive-selection/EXECUTION_BRIEF.md +53 -0
  23. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-02-approve-interactive-selection/slice.json +79 -0
  24. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-03-technical-plan-review-decision-data/CLOSURE_BRIEF.md +19 -0
  25. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-03-technical-plan-review-decision-data/EXECUTION_BRIEF.md +50 -0
  26. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-03-technical-plan-review-decision-data/slice.json +75 -0
  27. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-04-revise-input-guardrails/CLOSURE_BRIEF.md +19 -0
  28. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-04-revise-input-guardrails/EXECUTION_BRIEF.md +51 -0
  29. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-04-revise-input-guardrails/slice.json +73 -0
  30. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-05-provider-progress-alignment/CLOSURE_BRIEF.md +20 -0
  31. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-05-provider-progress-alignment/EXECUTION_BRIEF.md +51 -0
  32. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-05-provider-progress-alignment/slice.json +91 -0
  33. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-06-workflow-surface-integration/CLOSURE_BRIEF.md +20 -0
  34. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-06-workflow-surface-integration/EXECUTION_BRIEF.md +53 -0
  35. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-06-workflow-surface-integration/slice.json +87 -0
  36. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-07-docs-tests-release-readiness/CLOSURE_BRIEF.md +21 -0
  37. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-07-docs-tests-release-readiness/EXECUTION_BRIEF.md +55 -0
  38. package/specs/quiver-v33-approval-ux-and-planner-progress/slices/slice-07-docs-tests-release-readiness/slice.json +97 -0
  39. package/specs/quiver-v34-cli-dashboard-status/EVIDENCE_REPORT.md +119 -0
  40. package/specs/quiver-v34-cli-dashboard-status/EXECUTION_PLAN.md +77 -0
  41. package/specs/quiver-v34-cli-dashboard-status/SPEC.md +152 -0
  42. package/specs/quiver-v34-cli-dashboard-status/STATUS.md +29 -0
  43. package/specs/quiver-v34-cli-dashboard-status/pr.md +99 -0
  44. package/specs/quiver-v34-cli-dashboard-status/slices/slice-00-dashboard-foundation/CLOSURE_BRIEF.md +19 -0
  45. package/specs/quiver-v34-cli-dashboard-status/slices/slice-00-dashboard-foundation/EXECUTION_BRIEF.md +49 -0
  46. package/specs/quiver-v34-cli-dashboard-status/slices/slice-00-dashboard-foundation/slice.json +68 -0
  47. package/specs/quiver-v34-cli-dashboard-status/slices/slice-01-dashboard-report-contract/CLOSURE_BRIEF.md +19 -0
  48. package/specs/quiver-v34-cli-dashboard-status/slices/slice-01-dashboard-report-contract/EXECUTION_BRIEF.md +53 -0
  49. package/specs/quiver-v34-cli-dashboard-status/slices/slice-01-dashboard-report-contract/slice.json +78 -0
  50. package/specs/quiver-v34-cli-dashboard-status/slices/slice-02-dashboard-command-rendering/CLOSURE_BRIEF.md +19 -0
  51. package/specs/quiver-v34-cli-dashboard-status/slices/slice-02-dashboard-command-rendering/EXECUTION_BRIEF.md +53 -0
  52. package/specs/quiver-v34-cli-dashboard-status/slices/slice-02-dashboard-command-rendering/slice.json +82 -0
  53. package/specs/quiver-v34-cli-dashboard-status/slices/slice-03-dashboard-edge-cases-and-guardrails/CLOSURE_BRIEF.md +19 -0
  54. package/specs/quiver-v34-cli-dashboard-status/slices/slice-03-dashboard-edge-cases-and-guardrails/EXECUTION_BRIEF.md +54 -0
  55. package/specs/quiver-v34-cli-dashboard-status/slices/slice-03-dashboard-edge-cases-and-guardrails/slice.json +77 -0
  56. package/specs/quiver-v34-cli-dashboard-status/slices/slice-04-docs-templates-and-scripts/CLOSURE_BRIEF.md +19 -0
  57. package/specs/quiver-v34-cli-dashboard-status/slices/slice-04-docs-templates-and-scripts/EXECUTION_BRIEF.md +54 -0
  58. package/specs/quiver-v34-cli-dashboard-status/slices/slice-04-docs-templates-and-scripts/slice.json +88 -0
  59. package/specs/quiver-v34-cli-dashboard-status/slices/slice-05-tests-smokes-release-readiness/CLOSURE_BRIEF.md +26 -0
  60. package/specs/quiver-v34-cli-dashboard-status/slices/slice-05-tests-smokes-release-readiness/EXECUTION_BRIEF.md +57 -0
  61. package/specs/quiver-v34-cli-dashboard-status/slices/slice-05-tests-smokes-release-readiness/slice.json +85 -0
  62. package/specs/quiver-v35-compact-dashboard-version-ux/EVIDENCE_REPORT.md +43 -0
  63. package/specs/quiver-v35-compact-dashboard-version-ux/EXECUTION_PLAN.md +85 -0
  64. package/specs/quiver-v35-compact-dashboard-version-ux/SPEC.md +147 -0
  65. package/specs/quiver-v35-compact-dashboard-version-ux/STATUS.md +33 -0
  66. package/specs/quiver-v35-compact-dashboard-version-ux/pr.md +106 -0
  67. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-00-foundation-and-doc-router/CLOSURE_BRIEF.md +19 -0
  68. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-00-foundation-and-doc-router/EXECUTION_BRIEF.md +38 -0
  69. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-00-foundation-and-doc-router/slice.json +64 -0
  70. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-01-dashboard-cli-contract/CLOSURE_BRIEF.md +19 -0
  71. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-01-dashboard-cli-contract/EXECUTION_BRIEF.md +49 -0
  72. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-01-dashboard-cli-contract/slice.json +80 -0
  73. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-02-dashboard-compact-renderer/CLOSURE_BRIEF.md +19 -0
  74. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-02-dashboard-compact-renderer/EXECUTION_BRIEF.md +48 -0
  75. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-02-dashboard-compact-renderer/slice.json +73 -0
  76. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-03-dashboard-details-sections/CLOSURE_BRIEF.md +19 -0
  77. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-03-dashboard-details-sections/EXECUTION_BRIEF.md +48 -0
  78. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-03-dashboard-details-sections/slice.json +72 -0
  79. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-04-version-command/CLOSURE_BRIEF.md +19 -0
  80. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-04-version-command/EXECUTION_BRIEF.md +49 -0
  81. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-04-version-command/slice.json +82 -0
  82. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-05-docs-help-generated-guidance/CLOSURE_BRIEF.md +19 -0
  83. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-05-docs-help-generated-guidance/EXECUTION_BRIEF.md +50 -0
  84. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-05-docs-help-generated-guidance/slice.json +90 -0
  85. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-06-tests-smokes-release-readiness/CLOSURE_BRIEF.md +21 -0
  86. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-06-tests-smokes-release-readiness/EXECUTION_BRIEF.md +51 -0
  87. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-06-tests-smokes-release-readiness/slice.json +85 -0
  88. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-07-package-and-cross-platform-smoke/CLOSURE_BRIEF.md +20 -0
  89. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-07-package-and-cross-platform-smoke/EXECUTION_BRIEF.md +49 -0
  90. package/specs/quiver-v35-compact-dashboard-version-ux/slices/slice-07-package-and-cross-platform-smoke/slice.json +79 -0
  91. package/specs/quiver-v36-ai-run-watch-portable/EVIDENCE_REPORT.md +33 -0
  92. package/specs/quiver-v36-ai-run-watch-portable/EXECUTION_PLAN.md +39 -0
  93. package/specs/quiver-v36-ai-run-watch-portable/SPEC.md +166 -0
  94. package/specs/quiver-v36-ai-run-watch-portable/STATUS.md +31 -0
  95. package/specs/quiver-v36-ai-run-watch-portable/pr.md +78 -0
  96. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-00-foundation-and-handoffs/CLOSURE_BRIEF.md +19 -0
  97. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-00-foundation-and-handoffs/EXECUTION_BRIEF.md +43 -0
  98. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-00-foundation-and-handoffs/slice.json +61 -0
  99. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-01-run-schema-path-safety/CLOSURE_BRIEF.md +18 -0
  100. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-01-run-schema-path-safety/EXECUTION_BRIEF.md +43 -0
  101. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-01-run-schema-path-safety/slice.json +65 -0
  102. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-02-event-writer-redacted-logs/CLOSURE_BRIEF.md +18 -0
  103. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-02-event-writer-redacted-logs/EXECUTION_BRIEF.md +43 -0
  104. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-02-event-writer-redacted-logs/slice.json +66 -0
  105. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-03-provider-streaming-integration/CLOSURE_BRIEF.md +18 -0
  106. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-03-provider-streaming-integration/EXECUTION_BRIEF.md +41 -0
  107. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-03-provider-streaming-integration/slice.json +71 -0
  108. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-04-ai-run-watch-command/CLOSURE_BRIEF.md +18 -0
  109. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-04-ai-run-watch-command/EXECUTION_BRIEF.md +44 -0
  110. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-04-ai-run-watch-command/slice.json +73 -0
  111. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-05-main-progress-user-guidance/CLOSURE_BRIEF.md +18 -0
  112. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-05-main-progress-user-guidance/EXECUTION_BRIEF.md +44 -0
  113. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-05-main-progress-user-guidance/slice.json +71 -0
  114. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-06-docs-generated-guidance/CLOSURE_BRIEF.md +19 -0
  115. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-06-docs-generated-guidance/EXECUTION_BRIEF.md +45 -0
  116. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-06-docs-generated-guidance/slice.json +77 -0
  117. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-07-tests-cross-platform-readiness/CLOSURE_BRIEF.md +22 -0
  118. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-07-tests-cross-platform-readiness/EXECUTION_BRIEF.md +46 -0
  119. package/specs/quiver-v36-ai-run-watch-portable/slices/slice-07-tests-cross-platform-readiness/slice.json +87 -0
  120. package/src/create-quiver/commands/ai.js +112 -12
  121. package/src/create-quiver/commands/dashboard.js +31 -0
  122. package/src/create-quiver/commands/flow.js +74 -12
  123. package/src/create-quiver/commands/spec.js +8 -1
  124. package/src/create-quiver/index.js +107 -4
  125. package/src/create-quiver/lib/ai/approval-candidates.js +86 -0
  126. package/src/create-quiver/lib/ai/plan-review.js +77 -1
  127. package/src/create-quiver/lib/ai/run-state.js +21 -4
  128. package/src/create-quiver/lib/approvals.js +103 -0
  129. package/src/create-quiver/lib/cli/ux-flags.js +6 -0
  130. package/src/create-quiver/lib/dashboard.js +896 -0
  131. package/src/create-quiver/lib/git.js +13 -4
  132. package/src/create-quiver/lib/init-docs.js +6 -0
  133. package/src/create-quiver/lib/init-layout.js +2 -0
  134. package/src/create-quiver/lib/paths.js +45 -3
  135. package/src/create-quiver/lib/project-state-resolver.js +22 -2
  136. package/src/create-quiver/lib/version.js +157 -0
@@ -19,6 +19,14 @@ function tryGit(args, cwd, options = {}) {
19
19
  }
20
20
  }
21
21
 
22
+ function withWindowsLongPaths(args, options = {}) {
23
+ const platform = options.platform || process.platform;
24
+ if (platform !== 'win32') {
25
+ return args;
26
+ }
27
+ return ['-c', 'core.longpaths=true', ...args];
28
+ }
29
+
22
30
  function hasRef(repoRoot, ref) {
23
31
  try {
24
32
  runGit(['show-ref', '--verify', '--quiet', ref], repoRoot);
@@ -45,11 +53,11 @@ function fetchRemote(repoRoot, remote = 'origin', args = ['--prune']) {
45
53
  }
46
54
 
47
55
  function worktreePrune(repoRoot) {
48
- tryGit(['worktree', 'prune'], repoRoot);
56
+ tryGit(withWindowsLongPaths(['worktree', 'prune']), repoRoot);
49
57
  }
50
58
 
51
59
  function worktreeList(repoRoot) {
52
- const text = tryGit(['worktree', 'list', '--porcelain'], repoRoot);
60
+ const text = tryGit(withWindowsLongPaths(['worktree', 'list', '--porcelain']), repoRoot);
53
61
  const entries = [];
54
62
  const chunks = text.trim().split('\n\n').filter(Boolean);
55
63
 
@@ -79,7 +87,7 @@ function worktreeAdd(repoRoot, worktreePath, ref, options = {}) {
79
87
  args.push('--force');
80
88
  }
81
89
  args.push(worktreePath, ref);
82
- return runGit(args, repoRoot);
90
+ return runGit(withWindowsLongPaths(args, options), repoRoot);
83
91
  }
84
92
 
85
93
  function worktreeRemove(repoRoot, worktreePath, force = false) {
@@ -88,7 +96,7 @@ function worktreeRemove(repoRoot, worktreePath, force = false) {
88
96
  args.push('--force');
89
97
  }
90
98
  args.push(worktreePath);
91
- return runGit(args, repoRoot);
99
+ return runGit(withWindowsLongPaths(args), repoRoot);
92
100
  }
93
101
 
94
102
  function branchDelete(repoRoot, branchName, force = false) {
@@ -207,6 +215,7 @@ module.exports = {
207
215
  runGit,
208
216
  statusPorcelain,
209
217
  tryGit,
218
+ withWindowsLongPaths,
210
219
  worktreeAdd,
211
220
  worktreeList,
212
221
  worktreePrune,
@@ -398,7 +398,9 @@ npm run quiver:ai:execute-plan -- --dry-run --commit --mode delegated
398
398
  The generated project includes \`quiver:*\` npm scripts that call the Node CLI:
399
399
 
400
400
  \`\`\`bash
401
+ npm run quiver:version
401
402
  npm run quiver:analyze
403
+ npm run quiver:dashboard
402
404
  npm run quiver:prepare -- --dry-run
403
405
  npm run quiver:plan
404
406
  npm run quiver:graph
@@ -504,7 +506,9 @@ Remove \`--dry-run\` only after the phase output is approved and the local provi
504
506
  The generated project includes \`quiver:*\` npm scripts that call the Node CLI and are the preferred repeatable workflow:
505
507
 
506
508
  \`\`\`bash
509
+ npm run quiver:version
507
510
  npm run quiver:analyze
511
+ npm run quiver:dashboard
508
512
  npm run quiver:prepare -- --dry-run
509
513
  npm run quiver:plan
510
514
  npm run quiver:graph
@@ -538,6 +542,8 @@ npm run quiver:refresh-active-slices
538
542
  \`\`\`
539
543
 
540
544
  The \`quiver:graph\` script prints the tree view by default; use \`npx create-quiver graph --format mermaid\` for PR-ready Markdown and \`--format dot\` when you want Graphviz source.
545
+ The \`quiver:version\` script shows the Quiver-branded version report; add \`--json\` for automation while top-level \`--version\` stays semver-only.
546
+ The \`quiver:dashboard\` script shows compact read-only project, spec, slice, run, approval, and agent status by default; use \`--details\` for the full report, \`--section <name>\` for focused inspection, and \`--json\` for automation.
541
547
  The \`quiver:next\` script points to the next ready slice and can auto-start it behind a confirmation prompt.
542
548
  The \`quiver:ai:*\` scripts standardize planner/executor AI flows. Use dry-run first: onboarding and planning dry-runs do not require provider auth, \`quiver:ai:execute-plan -- --dry-run --commit --mode manual\` prints manual prompts, \`--mode delegated\` prints safe waves, \`quiver:ai:inspect\` shows lifecycle state, \`quiver:ai:export -- --format json|markdown\` emits dashboard/agent-friendly state, and \`quiver:ai:pr -- --dry-run\` validates \`gh\`, GitFlow docs, branch/worktree state, SSH inputs, and \`pr.md\` without creating a PR. Add \`--create\` only after reviewing the plan.
543
549
  Use \`quiver:spec:create\`, \`quiver:spec:start\`, \`quiver:spec:status\`, and \`quiver:spec:close\` for one spec generation and worktree per spec.
@@ -181,8 +181,10 @@ function resolveInitVisibleDirectories(profile, projectSlug) {
181
181
  function resolveInitPackageScripts(profile, options = {}) {
182
182
  const baseScripts = {
183
183
  'quiver:migrate': 'npx create-quiver migrate',
184
+ 'quiver:version': 'npx create-quiver version',
184
185
  'quiver:analyze': 'npx create-quiver analyze',
185
186
  'quiver:flow': 'npx create-quiver flow',
187
+ 'quiver:dashboard': 'npx create-quiver dashboard',
186
188
  'quiver:prepare': 'npx create-quiver prepare',
187
189
  'quiver:plan': 'npx create-quiver plan',
188
190
  'quiver:graph': 'npx create-quiver graph',
@@ -84,9 +84,42 @@ function realpathOrResolve(filePath, pathLib = path) {
84
84
  }
85
85
  }
86
86
 
87
- function isPathInsideRoot(root, target, pathLib = path) {
88
- const rootPath = realpathOrResolve(root, pathLib);
89
- const targetPath = realpathOrResolve(target, pathLib);
87
+ function realpathCandidates(filePath, pathLib = path) {
88
+ const normalized = normalizeGitBashDrivePath(filePath, pathLib);
89
+ const candidates = [];
90
+
91
+ const add = (candidate) => {
92
+ if (!candidate) {
93
+ return;
94
+ }
95
+ const resolved = pathLib.resolve(normalizeGitBashDrivePath(candidate, pathLib));
96
+ if (!candidates.includes(resolved)) {
97
+ candidates.push(resolved);
98
+ }
99
+ };
100
+
101
+ try {
102
+ add(fs.realpathSync(normalized));
103
+ } catch {
104
+ // Fall back below for paths that do not exist yet.
105
+ }
106
+
107
+ if (typeof fs.realpathSync.native === 'function') {
108
+ try {
109
+ add(fs.realpathSync.native(normalized));
110
+ } catch {
111
+ // Fall back below for paths that do not exist yet.
112
+ }
113
+ }
114
+
115
+ if (candidates.length === 0) {
116
+ add(normalized);
117
+ }
118
+
119
+ return candidates;
120
+ }
121
+
122
+ function isCandidateInsideRoot(rootPath, targetPath, pathLib = path) {
90
123
  const windowsPath = pathLib === path.win32 || process.platform === 'win32';
91
124
  const comparableRoot = windowsPath ? rootPath.toLowerCase() : rootPath;
92
125
  const comparableTarget = windowsPath ? targetPath.toLowerCase() : targetPath;
@@ -99,6 +132,15 @@ function isPathInsideRoot(root, target, pathLib = path) {
99
132
  return Boolean(relative && !relative.startsWith('..') && !pathLib.isAbsolute(relative));
100
133
  }
101
134
 
135
+ function isPathInsideRoot(root, target, pathLib = path) {
136
+ const rootCandidates = realpathCandidates(root, pathLib);
137
+ const targetCandidates = realpathCandidates(target, pathLib);
138
+
139
+ return rootCandidates.some((rootPath) => targetCandidates.some((targetPath) => (
140
+ isCandidateInsideRoot(rootPath, targetPath, pathLib)
141
+ )));
142
+ }
143
+
102
144
  function assertPathInsideRoot(root, target, label = 'path', pathLib = path) {
103
145
  if (!isPathInsideRoot(root, target, pathLib)) {
104
146
  throw new Error(formatError(`${label} must stay inside the project root: ${toPosixPath(target, pathLib)}`));
@@ -83,8 +83,28 @@ function safeBuildGraph(slices, allowGraphErrors) {
83
83
  function resolveProjectState(projectRoot, options = {}) {
84
84
  const specSlug = options.specSlug ? String(options.specSlug).trim() : '';
85
85
  const rawSlices = readResolverSlices(projectRoot, specSlug);
86
- const graph = safeBuildGraph(rawSlices, options.allowGraphErrors === true);
87
- const orderedSlices = graph.ok ? topoSort(graph).map(normalizeSliceRecord) : graph.nodes.slice().sort((left, right) => compareRefs(left.ref, right.ref));
86
+ let graph = safeBuildGraph(rawSlices, options.allowGraphErrors === true);
87
+ let orderedSlices;
88
+
89
+ try {
90
+ orderedSlices = graph.ok ? topoSort(graph).map(normalizeSliceRecord) : graph.nodes.slice().sort((left, right) => compareRefs(left.ref, right.ref));
91
+ } catch (error) {
92
+ if (!options.allowGraphErrors || !(error instanceof SliceGraphError)) {
93
+ throw error;
94
+ }
95
+
96
+ graph = {
97
+ ok: false,
98
+ nodes: inferDependencies(rawSlices).map(normalizeSliceRecord),
99
+ edges: [],
100
+ cycles: Array.isArray(graph.cycles) ? graph.cycles : [],
101
+ error: {
102
+ code: error.code,
103
+ message: error.message,
104
+ },
105
+ };
106
+ orderedSlices = graph.nodes.slice().sort((left, right) => compareRefs(left.ref, right.ref));
107
+ }
88
108
 
89
109
  return {
90
110
  graph,
@@ -0,0 +1,157 @@
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+
4
+ const { resolveTheme } = require('./cli/theme');
5
+
6
+ const VERSION_SCHEMA_VERSION = 1;
7
+ const PACKAGE_ROOT = path.resolve(__dirname, '../../..');
8
+ const PACKAGE_JSON = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8'));
9
+
10
+ function readJsonIfExists(filePath) {
11
+ if (!fs.existsSync(filePath)) {
12
+ return null;
13
+ }
14
+
15
+ try {
16
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
17
+ } catch {
18
+ return null;
19
+ }
20
+ }
21
+
22
+ function parsePackageManagerField(value) {
23
+ const text = String(value || '').trim();
24
+ if (!text) return null;
25
+ const [name, version] = text.split('@');
26
+ return {
27
+ name: name || null,
28
+ version: version || null,
29
+ source: 'package.json',
30
+ };
31
+ }
32
+
33
+ function parseUserAgent(value) {
34
+ const text = String(value || '').trim();
35
+ if (!text) return null;
36
+ const first = text.split(/\s+/)[0] || '';
37
+ const [name, version] = first.split('/');
38
+ if (!name) return null;
39
+ return {
40
+ name,
41
+ version: version || null,
42
+ source: 'npm_config_user_agent',
43
+ };
44
+ }
45
+
46
+ function detectPackageManager(projectRoot, env = process.env) {
47
+ const packageJson = readJsonIfExists(path.join(projectRoot, 'package.json'));
48
+ const packageManagerField = parsePackageManagerField(packageJson?.packageManager);
49
+ if (packageManagerField) return packageManagerField;
50
+
51
+ const signals = [
52
+ ['bun', 'bun.lockb'],
53
+ ['bun', 'bun.lock'],
54
+ ['pnpm', 'pnpm-lock.yaml'],
55
+ ['yarn', 'yarn.lock'],
56
+ ['npm', 'package-lock.json'],
57
+ ];
58
+
59
+ for (const [name, filename] of signals) {
60
+ if (fs.existsSync(path.join(projectRoot, filename))) {
61
+ return { name, version: null, source: filename };
62
+ }
63
+ }
64
+
65
+ return parseUserAgent(env.npm_config_user_agent) || {
66
+ name: 'unknown',
67
+ version: null,
68
+ source: 'none',
69
+ };
70
+ }
71
+
72
+ function collectProjectInfo(projectRoot) {
73
+ const packageJson = readJsonIfExists(path.join(projectRoot, 'package.json'));
74
+ const state = readJsonIfExists(path.join(projectRoot, '.quiver', 'state.json'));
75
+ const hasProjectSignals = Boolean(packageJson || state);
76
+
77
+ if (!hasProjectSignals) {
78
+ return {
79
+ name: null,
80
+ path: null,
81
+ quiver_initialized: false,
82
+ quiver_version: null,
83
+ };
84
+ }
85
+
86
+ return {
87
+ name: packageJson?.name || state?.project_name || path.basename(projectRoot),
88
+ path: projectRoot,
89
+ quiver_initialized: Boolean(state?.initialized_version || state?.quiver_version),
90
+ quiver_version: state?.quiver_version || state?.initialized_version || null,
91
+ };
92
+ }
93
+
94
+ function collectVersionReport(projectRoot = process.cwd(), options = {}) {
95
+ return {
96
+ version_schema_version: VERSION_SCHEMA_VERSION,
97
+ cli: {
98
+ name: PACKAGE_JSON.name || 'create-quiver',
99
+ version: options.cliVersion || PACKAGE_JSON.version || '0.0.0',
100
+ },
101
+ runtime: {
102
+ node: process.version,
103
+ platform: process.platform,
104
+ arch: process.arch,
105
+ },
106
+ package_manager: detectPackageManager(projectRoot, options.env || process.env),
107
+ project: collectProjectInfo(projectRoot),
108
+ };
109
+ }
110
+
111
+ function formatPackageManager(packageManager) {
112
+ if (!packageManager?.name || packageManager.name === 'unknown') {
113
+ return 'unknown';
114
+ }
115
+ return packageManager.version ? `${packageManager.name}@${packageManager.version}` : packageManager.name;
116
+ }
117
+
118
+ function quiverBanner(theme) {
119
+ const lines = [
120
+ ' ___ _ ',
121
+ ' / _ \\ _ _(_)_ _____ _ __ ',
122
+ '| | | | | | | \\ \\ / / _ \\ \'__|',
123
+ '| |_| | |_| | |\\ V / __/ | ',
124
+ ' \\__\\_\\\\__,_|_| \\_/ \\___|_| ',
125
+ ];
126
+ const colors = ['sky', 'blue', 'periwinkle', 'violet', 'magenta'];
127
+ return lines.map((line, index) => theme.colorize(line, colors[index])).join('\n');
128
+ }
129
+
130
+ function formatHumanVersionReport(report, options = {}) {
131
+ const theme = resolveTheme({ noColor: options.noColor }, options.env || process.env, {
132
+ stdout: options.stdoutIsTTY ?? Boolean(process.stdout.isTTY),
133
+ });
134
+ const project = report.project?.name
135
+ ? `${report.project.name}${report.project.quiver_initialized ? ' (Quiver project)' : ''}`
136
+ : 'none';
137
+ const lines = [
138
+ quiverBanner(theme),
139
+ '',
140
+ `Quiver CLI: ${report.cli.version}`,
141
+ `Node: ${report.runtime.node}`,
142
+ `Package manager: ${formatPackageManager(report.package_manager)}`,
143
+ `OS: ${report.runtime.platform} ${report.runtime.arch}`,
144
+ `Project: ${project}`,
145
+ '',
146
+ ];
147
+
148
+ return `${lines.join('\n')}`;
149
+ }
150
+
151
+ module.exports = {
152
+ VERSION_SCHEMA_VERSION,
153
+ collectVersionReport,
154
+ detectPackageManager,
155
+ formatHumanVersionReport,
156
+ quiverBanner,
157
+ };