create-quiver 0.15.4 → 0.17.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 (199) hide show
  1. package/.github/pull_request_template.md +17 -0
  2. package/.github/workflows/ci.yml +76 -0
  3. package/.markdown-link-check.json +15 -0
  4. package/.markdownlint.json +11 -0
  5. package/ARCHITECTURE.md +133 -0
  6. package/CHANGELOG.md +16 -0
  7. package/CONTRIBUTING.md +174 -9
  8. package/README.md +17 -2
  9. package/README_FOR_AI.md +4 -1
  10. package/ROADMAP.md +4 -0
  11. package/SECURITY.md +9 -2
  12. package/docs/AI_CONTEXT.md.es.template +3 -1
  13. package/docs/AI_CONTEXT.md.template +3 -1
  14. package/docs/CLI_UX_GUIDE.md +20 -1
  15. package/docs/COMMANDS.md.template +20 -6
  16. package/docs/GITFLOW_PR_GUIDE.md +73 -11
  17. package/docs/GITFLOW_PR_GUIDE.md.es.template +61 -2
  18. package/docs/GITFLOW_PR_GUIDE.md.template +72 -10
  19. package/docs/INDEX.md +6 -1
  20. package/docs/QUICK.md.template +2 -1
  21. package/docs/STANDARD.md.template +2 -1
  22. package/docs/WORKFLOW.md.es.template +3 -1
  23. package/docs/WORKFLOW.md.template +6 -4
  24. package/docs/getting-started/installation.md +7 -0
  25. package/docs/reference/commands.md +138 -6
  26. package/docs/reference/slice-schema.md +37 -0
  27. package/docs/schema/slice.schema.json +221 -0
  28. package/docs/specs/01-spec/01-slice/01-slice.json +36 -0
  29. package/docs/specs/01-spec/01-slice/01-slice.md +106 -0
  30. package/docs/specs/01-spec/01-slice/CLOSURE_BRIEF.md +80 -0
  31. package/docs/specs/01-spec/01-slice/EXECUTION_BRIEF.md +39 -0
  32. package/docs/specs/01-spec/02-slice/02-slice.json +36 -0
  33. package/docs/specs/01-spec/02-slice/02-slice.md +108 -0
  34. package/docs/specs/01-spec/02-slice/CLOSURE_BRIEF.md +88 -0
  35. package/docs/specs/01-spec/02-slice/EXECUTION_BRIEF.md +40 -0
  36. package/docs/specs/01-spec/03-slice/03-slice.json +36 -0
  37. package/docs/specs/01-spec/03-slice/03-slice.md +103 -0
  38. package/docs/specs/01-spec/03-slice/CLOSURE_BRIEF.md +54 -0
  39. package/docs/specs/01-spec/03-slice/EXECUTION_BRIEF.md +39 -0
  40. package/docs/specs/01-spec/04-slice/04-slice.json +36 -0
  41. package/docs/specs/01-spec/04-slice/04-slice.md +107 -0
  42. package/docs/specs/01-spec/04-slice/CLOSURE_BRIEF.md +46 -0
  43. package/docs/specs/01-spec/04-slice/EXECUTION_BRIEF.md +39 -0
  44. package/docs/specs/01-spec/05-slice/05-slice.json +36 -0
  45. package/docs/specs/01-spec/05-slice/05-slice.md +106 -0
  46. package/docs/specs/01-spec/05-slice/CLOSURE_BRIEF.md +84 -0
  47. package/docs/specs/01-spec/05-slice/EXECUTION_BRIEF.md +109 -0
  48. package/docs/specs/01-spec/06-slice/06-slice.json +36 -0
  49. package/docs/specs/01-spec/06-slice/06-slice.md +107 -0
  50. package/docs/specs/01-spec/06-slice/CLOSURE_BRIEF.md +67 -0
  51. package/docs/specs/01-spec/06-slice/EXECUTION_BRIEF.md +39 -0
  52. package/docs/specs/01-spec/07-slice/07-slice.json +36 -0
  53. package/docs/specs/01-spec/07-slice/07-slice.md +105 -0
  54. package/docs/specs/01-spec/07-slice/CLOSURE_BRIEF.md +71 -0
  55. package/docs/specs/01-spec/07-slice/EXECUTION_BRIEF.md +39 -0
  56. package/docs/specs/01-spec/08-slice/08-slice.json +36 -0
  57. package/docs/specs/01-spec/08-slice/08-slice.md +105 -0
  58. package/docs/specs/01-spec/08-slice/CLOSURE_BRIEF.md +114 -0
  59. package/docs/specs/01-spec/08-slice/EXECUTION_BRIEF.md +39 -0
  60. package/docs/specs/01-spec/CLOSURE_BRIEF.md +87 -0
  61. package/docs/specs/01-spec/spec.md +197 -0
  62. package/docs/workflows/full-ai-spec-to-pr.md +46 -3
  63. package/i18n/es/docs/GITFLOW_PR_GUIDE.md.template +38 -1
  64. package/package.json +27 -1
  65. package/scripts/package-quiver.sh +82 -2
  66. package/scripts/release-quiver.sh +14 -3
  67. package/specs/[project-name]/slices/pr.md.template +19 -0
  68. package/specs/quiver-v43-cli-i18n-audit-release-readiness/command-language-mode-matrix.json +122 -1
  69. package/specs/quiver-v46-deep-project-analysis/EVIDENCE_REPORT.md +94 -0
  70. package/specs/quiver-v46-deep-project-analysis/EXECUTION_PLAN.md +26 -0
  71. package/specs/quiver-v46-deep-project-analysis/SPEC.md +157 -0
  72. package/specs/quiver-v46-deep-project-analysis/STATUS.md +26 -0
  73. package/specs/quiver-v46-deep-project-analysis/pr.md +131 -0
  74. package/specs/quiver-v46-deep-project-analysis/slices/slice-00-analysis-contract-foundation/CLOSURE_BRIEF.md +14 -0
  75. package/specs/quiver-v46-deep-project-analysis/slices/slice-00-analysis-contract-foundation/EXECUTION_BRIEF.md +41 -0
  76. package/specs/quiver-v46-deep-project-analysis/slices/slice-00-analysis-contract-foundation/slice.json +61 -0
  77. package/specs/quiver-v46-deep-project-analysis/slices/slice-01-stack-agnostic-discovery-sampling/CLOSURE_BRIEF.md +22 -0
  78. package/specs/quiver-v46-deep-project-analysis/slices/slice-01-stack-agnostic-discovery-sampling/EXECUTION_BRIEF.md +33 -0
  79. package/specs/quiver-v46-deep-project-analysis/slices/slice-01-stack-agnostic-discovery-sampling/slice.json +80 -0
  80. package/specs/quiver-v46-deep-project-analysis/slices/slice-02-provider-analysis-json-contract/CLOSURE_BRIEF.md +21 -0
  81. package/specs/quiver-v46-deep-project-analysis/slices/slice-02-provider-analysis-json-contract/EXECUTION_BRIEF.md +34 -0
  82. package/specs/quiver-v46-deep-project-analysis/slices/slice-02-provider-analysis-json-contract/slice.json +79 -0
  83. package/specs/quiver-v46-deep-project-analysis/slices/slice-03-doc-proposal-review-safe-writes/CLOSURE_BRIEF.md +19 -0
  84. package/specs/quiver-v46-deep-project-analysis/slices/slice-03-doc-proposal-review-safe-writes/EXECUTION_BRIEF.md +33 -0
  85. package/specs/quiver-v46-deep-project-analysis/slices/slice-03-doc-proposal-review-safe-writes/slice.json +79 -0
  86. package/specs/quiver-v46-deep-project-analysis/slices/slice-04-validation-docs-release-readiness/CLOSURE_BRIEF.md +20 -0
  87. package/specs/quiver-v46-deep-project-analysis/slices/slice-04-validation-docs-release-readiness/EXECUTION_BRIEF.md +32 -0
  88. package/specs/quiver-v46-deep-project-analysis/slices/slice-04-validation-docs-release-readiness/slice.json +85 -0
  89. package/specs/quiver-v50-audit-trust-foundation/EVIDENCE_REPORT.md +151 -0
  90. package/specs/quiver-v50-audit-trust-foundation/EXECUTION_PLAN.md +34 -0
  91. package/specs/quiver-v50-audit-trust-foundation/SPEC.md +113 -0
  92. package/specs/quiver-v50-audit-trust-foundation/STATUS.md +26 -0
  93. package/specs/quiver-v50-audit-trust-foundation/pr.md +120 -0
  94. package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/CLOSURE_BRIEF.md +20 -0
  95. package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/EXECUTION_BRIEF.md +58 -0
  96. package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/slice.json +57 -0
  97. package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/CLOSURE_BRIEF.md +24 -0
  98. package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/EXECUTION_BRIEF.md +67 -0
  99. package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/slice.json +71 -0
  100. package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/CLOSURE_BRIEF.md +24 -0
  101. package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/EXECUTION_BRIEF.md +71 -0
  102. package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/slice.json +81 -0
  103. package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/CLOSURE_BRIEF.md +22 -0
  104. package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/EXECUTION_BRIEF.md +57 -0
  105. package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/slice.json +56 -0
  106. package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/CLOSURE_BRIEF.md +23 -0
  107. package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/EXECUTION_BRIEF.md +68 -0
  108. package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/slice.json +84 -0
  109. package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/CLOSURE_BRIEF.md +25 -0
  110. package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/EXECUTION_BRIEF.md +73 -0
  111. package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/slice.json +72 -0
  112. package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/CLOSURE_BRIEF.md +22 -0
  113. package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/EXECUTION_BRIEF.md +66 -0
  114. package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/slice.json +74 -0
  115. package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/CLOSURE_BRIEF.md +29 -0
  116. package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/EXECUTION_BRIEF.md +74 -0
  117. package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/slice.json +81 -0
  118. package/specs/quiver-v51-cli-ergonomics-automation-contracts/EVIDENCE_REPORT.md +145 -0
  119. package/specs/quiver-v51-cli-ergonomics-automation-contracts/EXECUTION_PLAN.md +32 -0
  120. package/specs/quiver-v51-cli-ergonomics-automation-contracts/SPEC.md +109 -0
  121. package/specs/quiver-v51-cli-ergonomics-automation-contracts/STATUS.md +25 -0
  122. package/specs/quiver-v51-cli-ergonomics-automation-contracts/pr.md +69 -0
  123. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/CLOSURE_BRIEF.md +20 -0
  124. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/EXECUTION_BRIEF.md +58 -0
  125. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/slice.json +56 -0
  126. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/CLOSURE_BRIEF.md +21 -0
  127. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/EXECUTION_BRIEF.md +61 -0
  128. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/slice.json +68 -0
  129. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/CLOSURE_BRIEF.md +25 -0
  130. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/EXECUTION_BRIEF.md +65 -0
  131. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/pr.md +134 -0
  132. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/slice.json +80 -0
  133. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/CLOSURE_BRIEF.md +31 -0
  134. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/EXECUTION_BRIEF.md +80 -0
  135. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/pr.md +159 -0
  136. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/slice.json +102 -0
  137. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/CLOSURE_BRIEF.md +25 -0
  138. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/EXECUTION_BRIEF.md +74 -0
  139. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/pr.md +147 -0
  140. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/slice.json +91 -0
  141. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/CLOSURE_BRIEF.md +28 -0
  142. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/EXECUTION_BRIEF.md +73 -0
  143. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/pr.md +146 -0
  144. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/slice.json +100 -0
  145. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/CLOSURE_BRIEF.md +36 -0
  146. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/EXECUTION_BRIEF.md +76 -0
  147. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/pr.md +155 -0
  148. package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/slice.json +111 -0
  149. package/specs/quiver-v52-schema-docs-release-hygiene/EVIDENCE_REPORT.md +95 -0
  150. package/specs/quiver-v52-schema-docs-release-hygiene/EXECUTION_PLAN.md +31 -0
  151. package/specs/quiver-v52-schema-docs-release-hygiene/SPEC.md +107 -0
  152. package/specs/quiver-v52-schema-docs-release-hygiene/STATUS.md +22 -0
  153. package/specs/quiver-v52-schema-docs-release-hygiene/pr.md +69 -0
  154. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/CLOSURE_BRIEF.md +21 -0
  155. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/EXECUTION_BRIEF.md +60 -0
  156. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/slice.json +62 -0
  157. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/CLOSURE_BRIEF.md +34 -0
  158. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/EXECUTION_BRIEF.md +71 -0
  159. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/pr.md +146 -0
  160. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/slice.json +106 -0
  161. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/CLOSURE_BRIEF.md +33 -0
  162. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/EXECUTION_BRIEF.md +67 -0
  163. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/pr.md +144 -0
  164. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/slice.json +86 -0
  165. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/CLOSURE_BRIEF.md +38 -0
  166. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/EXECUTION_BRIEF.md +75 -0
  167. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/pr.md +159 -0
  168. package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/slice.json +105 -0
  169. package/src/create-quiver/commands/ai.js +521 -0
  170. package/src/create-quiver/commands/changelog.js +93 -0
  171. package/src/create-quiver/commands/config.js +16 -5
  172. package/src/create-quiver/commands/evidence.js +33 -2
  173. package/src/create-quiver/commands/flow.js +1 -0
  174. package/src/create-quiver/commands/graph.js +8 -2
  175. package/src/create-quiver/commands/plan.js +6 -0
  176. package/src/create-quiver/commands/spec.js +28 -13
  177. package/src/create-quiver/index.js +408 -98
  178. package/src/create-quiver/lib/ai/analyze-project-discovery.js +387 -0
  179. package/src/create-quiver/lib/ai/analyze-project-docs.js +364 -0
  180. package/src/create-quiver/lib/ai/analyze-project-parser.js +277 -0
  181. package/src/create-quiver/lib/ai/analyze-project-prompts.js +214 -0
  182. package/src/create-quiver/lib/ai/analyze-project-review.js +99 -0
  183. package/src/create-quiver/lib/ai/analyze-project-sampling.js +402 -0
  184. package/src/create-quiver/lib/ai/analyze-project-schema.js +92 -0
  185. package/src/create-quiver/lib/ai/analyze-project-validation.js +309 -0
  186. package/src/create-quiver/lib/ai/artifacts.js +4 -1
  187. package/src/create-quiver/lib/ai/github.js +5 -2
  188. package/src/create-quiver/lib/ai/spec-templates.js +19 -0
  189. package/src/create-quiver/lib/cli/command-registry.js +72 -0
  190. package/src/create-quiver/lib/cli/parser.js +14 -0
  191. package/src/create-quiver/lib/evidence.js +161 -6
  192. package/src/create-quiver/lib/git.js +99 -0
  193. package/src/create-quiver/lib/i18n/messages/en.js +52 -7
  194. package/src/create-quiver/lib/i18n/messages/es.js +54 -9
  195. package/src/create-quiver/lib/init-docs.js +1 -1
  196. package/src/create-quiver/lib/init-layout.js +9 -8
  197. package/src/create-quiver/lib/lifecycle.js +24 -26
  198. package/src/create-quiver/lib/readiness.js +67 -56
  199. package/src/create-quiver/lib/spec-worktrees.js +16 -34
@@ -0,0 +1,92 @@
1
+ const { z } = require('zod');
2
+
3
+ const ANALYZE_PROJECT_SCHEMA_VERSION = 1;
4
+ const ANALYZE_PROJECT_KIND = 'quiver-project-analysis';
5
+ const MAX_ANALYZE_DOC_UPDATE_LENGTH = 400_000;
6
+ const CONFIDENCE_LEVELS = ['confirmed', 'inferred', 'unknown', 'conflict'];
7
+ const ALLOWED_ANALYZE_DOC_UPDATE_PATHS = [
8
+ 'docs/CONTEXTO.md',
9
+ 'docs/AI_CONTEXT.md',
10
+ 'docs/ARCHITECTURE.md',
11
+ 'docs/STATUS.md',
12
+ 'docs/DECISIONS.md',
13
+ 'docs/PROJECT_MAP.md',
14
+ ];
15
+
16
+ const confidenceSchema = z.enum(CONFIDENCE_LEVELS);
17
+ const evidencePathSchema = z.string().trim().min(1, 'evidence path is required');
18
+
19
+ const evidenceClaimSchema = z.object({
20
+ claim: z.string().trim().min(1, 'claim is required').max(4_000),
21
+ confidence: confidenceSchema,
22
+ evidence: z.array(evidencePathSchema).default([]),
23
+ notes: z.string().trim().max(2_000).default(''),
24
+ }).strict();
25
+
26
+ const namedFindingSchema = z.object({
27
+ name: z.string().trim().min(1, 'name is required').max(500),
28
+ summary: z.string().trim().max(4_000).default(''),
29
+ confidence: confidenceSchema.default('unknown'),
30
+ evidence: z.array(evidencePathSchema).default([]),
31
+ }).strict();
32
+
33
+ const productSchema = z.object({
34
+ name: namedFindingSchema.optional(),
35
+ type: namedFindingSchema.optional(),
36
+ summary: z.string().trim().max(4_000).default(''),
37
+ claims: z.array(evidenceClaimSchema).default([]),
38
+ }).strict().default({});
39
+
40
+ const domainSchema = z.object({
41
+ roles: z.array(namedFindingSchema).default([]),
42
+ entities: z.array(namedFindingSchema).default([]),
43
+ actions: z.array(namedFindingSchema).default([]),
44
+ flows: z.array(namedFindingSchema).default([]),
45
+ incomplete_or_suspicious: z.array(namedFindingSchema).default([]),
46
+ claims: z.array(evidenceClaimSchema).default([]),
47
+ }).strict().default({});
48
+
49
+ const architectureSchema = z.object({
50
+ frontend: z.array(namedFindingSchema).default([]),
51
+ backend: z.array(namedFindingSchema).default([]),
52
+ auth: z.array(namedFindingSchema).default([]),
53
+ persistence: z.array(namedFindingSchema).default([]),
54
+ integrations: z.array(namedFindingSchema).default([]),
55
+ state: z.array(namedFindingSchema).default([]),
56
+ api: z.array(namedFindingSchema).default([]),
57
+ testing: z.array(namedFindingSchema).default([]),
58
+ deploy: z.array(namedFindingSchema).default([]),
59
+ risks: z.array(namedFindingSchema).default([]),
60
+ claims: z.array(evidenceClaimSchema).default([]),
61
+ }).strict().default({});
62
+
63
+ const questionSchema = z.object({
64
+ question: z.string().trim().min(1, 'question is required').max(2_000),
65
+ reason: z.string().trim().max(2_000).default(''),
66
+ evidence: z.array(evidencePathSchema).default([]),
67
+ }).strict();
68
+
69
+ const analyzeProjectSchema = z.object({
70
+ schema_version: z.literal(ANALYZE_PROJECT_SCHEMA_VERSION).default(ANALYZE_PROJECT_SCHEMA_VERSION),
71
+ kind: z.literal(ANALYZE_PROJECT_KIND).default(ANALYZE_PROJECT_KIND),
72
+ product: productSchema,
73
+ domain: domainSchema,
74
+ architecture: architectureSchema,
75
+ features: z.array(namedFindingSchema).default([]),
76
+ risks: z.array(namedFindingSchema).default([]),
77
+ questions: z.array(questionSchema).default([]),
78
+ claims: z.array(evidenceClaimSchema).default([]),
79
+ doc_updates: z.record(z.string().trim().min(1), z.string().max(MAX_ANALYZE_DOC_UPDATE_LENGTH)).default({}),
80
+ }).strict();
81
+
82
+ module.exports = {
83
+ ALLOWED_ANALYZE_DOC_UPDATE_PATHS,
84
+ ANALYZE_PROJECT_KIND,
85
+ ANALYZE_PROJECT_SCHEMA_VERSION,
86
+ CONFIDENCE_LEVELS,
87
+ MAX_ANALYZE_DOC_UPDATE_LENGTH,
88
+ analyzeProjectSchema,
89
+ confidenceSchema,
90
+ evidenceClaimSchema,
91
+ namedFindingSchema,
92
+ };
@@ -0,0 +1,309 @@
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+
4
+ const {
5
+ ANALYZE_MANAGED_END,
6
+ ANALYZE_MANAGED_START,
7
+ normalizeAnalyzeProjectDocProposal,
8
+ } = require('./analyze-project-docs');
9
+ const { normalizeAnalyzeProjectAnalysis } = require('./analyze-project-parser');
10
+
11
+ const VALIDATION_KIND = 'quiver-analyze-project-post-write-validation';
12
+
13
+ const PLACEHOLDER_PATTERNS = [
14
+ { issue: 'placeholder-todo', pattern: /\bTODO\b/i },
15
+ { issue: 'placeholder-fixme', pattern: /\bFIXME\b/i },
16
+ { issue: 'placeholder-tbd', pattern: /\bTBD\b/i },
17
+ { issue: 'placeholder-template-token', pattern: /\{\{[^}\n]+\}\}/ },
18
+ { issue: 'placeholder-bracket-token', pattern: /\[(?:TODO|TBD|PLACEHOLDER|REPLACE|INSERT)[^\]\n]*\]/i },
19
+ { issue: 'placeholder-angle-token', pattern: /<(?:TODO|TBD|PLACEHOLDER|REPLACE|INSERT)[^>\n]*>/i },
20
+ { issue: 'placeholder-unfinished', pattern: /to be completed after implementation/i },
21
+ ];
22
+
23
+ const FACT_KEY_ALIASES = new Map([
24
+ ['app', 'product'],
25
+ ['application', 'product'],
26
+ ['auth', 'auth'],
27
+ ['authentication', 'auth'],
28
+ ['backend', 'backend'],
29
+ ['database', 'database'],
30
+ ['db', 'database'],
31
+ ['frontend', 'frontend'],
32
+ ['framework', 'framework'],
33
+ ['package manager', 'package_manager'],
34
+ ['package_manager', 'package_manager'],
35
+ ['persistence', 'database'],
36
+ ['product', 'product'],
37
+ ['stack', 'stack'],
38
+ ]);
39
+
40
+ function toPosix(filePath) {
41
+ return String(filePath || '').replace(/\\/g, '/');
42
+ }
43
+
44
+ function makeIssue(pathName, issue, message, extra = {}) {
45
+ return {
46
+ path: pathName || null,
47
+ issue,
48
+ message,
49
+ ...extra,
50
+ };
51
+ }
52
+
53
+ function extractManagedBlock(content) {
54
+ const text = String(content || '');
55
+ const start = text.indexOf(ANALYZE_MANAGED_START);
56
+ const end = text.indexOf(ANALYZE_MANAGED_END);
57
+ if (start < 0 || end <= start) {
58
+ return {
59
+ ok: false,
60
+ content: '',
61
+ issue: start < 0 && end < 0 ? 'managed-block-missing' : 'managed-block-unbalanced',
62
+ };
63
+ }
64
+ return {
65
+ ok: true,
66
+ content: text.slice(start + ANALYZE_MANAGED_START.length, end),
67
+ issue: '',
68
+ };
69
+ }
70
+
71
+ function readRelativeFile(repoRoot, relativePath) {
72
+ const normalized = toPosix(relativePath);
73
+ const absolute = path.resolve(repoRoot, normalized);
74
+ const repo = path.resolve(repoRoot);
75
+ const relative = path.relative(repo, absolute);
76
+ if (relative.startsWith('..') || path.isAbsolute(relative)) {
77
+ return {
78
+ ok: false,
79
+ path: normalized,
80
+ content: '',
81
+ issue: 'path-outside-repo',
82
+ message: `path is outside repository: ${normalized}`,
83
+ };
84
+ }
85
+ if (!fs.existsSync(absolute)) {
86
+ return {
87
+ ok: false,
88
+ path: normalized,
89
+ content: '',
90
+ issue: 'missing-written-doc',
91
+ message: `written doc is missing: ${normalized}`,
92
+ };
93
+ }
94
+ return {
95
+ ok: true,
96
+ path: normalized,
97
+ content: fs.readFileSync(absolute, 'utf8'),
98
+ };
99
+ }
100
+
101
+ function collectChangedDocPaths(report) {
102
+ const fromWritten = Array.isArray(report?.written_docs) ? report.written_docs : [];
103
+ const fromPlan = Array.isArray(report?.write_plan)
104
+ ? report.write_plan.filter((item) => item.action && item.action !== 'skip').map((item) => item.path)
105
+ : [];
106
+ return [...new Set([...fromWritten, ...fromPlan].map(toPosix).filter(Boolean))].sort();
107
+ }
108
+
109
+ function addSchemaValidation(report, errors) {
110
+ try {
111
+ normalizeAnalyzeProjectAnalysis(report.analysis, {
112
+ selectedFiles: report.selected_files || [],
113
+ promptFiles: report.prompt?.files || [],
114
+ });
115
+ } catch (error) {
116
+ for (const issue of error.issues || []) {
117
+ errors.push(makeIssue(issue.path, issue.issue || 'analysis-schema-invalid', issue.message || error.message));
118
+ }
119
+ }
120
+
121
+ try {
122
+ normalizeAnalyzeProjectDocProposal(report.doc_proposal);
123
+ } catch (error) {
124
+ for (const issue of error.issues || []) {
125
+ errors.push(makeIssue(issue.path || issue.pathName, issue.issue || 'doc-proposal-schema-invalid', issue.message || error.message));
126
+ }
127
+ }
128
+ }
129
+
130
+ function addManifestValidation(repoRoot, report, errors) {
131
+ if (!report?.snapshot?.manifestPath) {
132
+ errors.push(makeIssue('snapshot.manifestPath', 'snapshot-manifest-missing', 'snapshot manifest path is missing from write report.'));
133
+ return;
134
+ }
135
+
136
+ const manifest = readRelativeFile(repoRoot, report.snapshot.manifestPath);
137
+ if (!manifest.ok) {
138
+ errors.push(makeIssue(manifest.path, manifest.issue, manifest.message));
139
+ return;
140
+ }
141
+
142
+ try {
143
+ const parsed = JSON.parse(manifest.content);
144
+ const expectedPaths = collectChangedDocPaths(report);
145
+ const manifestPaths = new Set((parsed.entries || []).map((entry) => toPosix(entry.path)));
146
+ for (const expectedPath of expectedPaths) {
147
+ if (!manifestPaths.has(expectedPath)) {
148
+ errors.push(makeIssue(expectedPath, 'snapshot-manifest-entry-missing', `snapshot manifest does not contain an entry for ${expectedPath}.`));
149
+ }
150
+ }
151
+ } catch (error) {
152
+ errors.push(makeIssue(report.snapshot.manifestPath, 'snapshot-manifest-invalid-json', error.message));
153
+ }
154
+ }
155
+
156
+ function addPlaceholderValidation(docPath, managedContent, errors) {
157
+ for (const { issue, pattern } of PLACEHOLDER_PATTERNS) {
158
+ if (pattern.test(managedContent)) {
159
+ errors.push(makeIssue(docPath, issue, `critical placeholder remains in generated managed block: ${issue}`));
160
+ }
161
+ }
162
+ }
163
+
164
+ function normalizeFactValue(value) {
165
+ return String(value || '')
166
+ .replace(/[`*_]/g, '')
167
+ .replace(/\s+/g, ' ')
168
+ .trim()
169
+ .replace(/[.;,]+$/g, '')
170
+ .toLowerCase();
171
+ }
172
+
173
+ function isUnknownFactValue(value) {
174
+ const normalized = normalizeFactValue(value);
175
+ return !normalized
176
+ || normalized === 'unknown'
177
+ || normalized === 'none'
178
+ || normalized === 'n/a'
179
+ || normalized === 'needs confirmation'
180
+ || normalized === 'needs_confirmation'
181
+ || normalized === 'to confirm'
182
+ || normalized === 'not confirmed';
183
+ }
184
+
185
+ function extractFactEntries(docPath, managedContent) {
186
+ const facts = new Map();
187
+ const lines = String(managedContent || '').split(/\r?\n/);
188
+
189
+ for (const [index, rawLine] of lines.entries()) {
190
+ const line = rawLine
191
+ .replace(/^#+\s*/, '')
192
+ .replace(/^[-*]\s*/, '')
193
+ .trim();
194
+ const match = line.match(/^([A-Za-z _-]{2,32})\s*:\s*(.+)$/);
195
+ if (!match) {
196
+ continue;
197
+ }
198
+
199
+ const rawKey = match[1].trim().toLowerCase().replace(/[-\s]+/g, ' ');
200
+ const key = FACT_KEY_ALIASES.get(rawKey);
201
+ if (!key) {
202
+ continue;
203
+ }
204
+
205
+ const value = match[2].trim();
206
+ if (isUnknownFactValue(value)) {
207
+ continue;
208
+ }
209
+
210
+ if (!facts.has(key)) {
211
+ facts.set(key, []);
212
+ }
213
+ facts.get(key).push({
214
+ path: docPath,
215
+ line: index + 1,
216
+ value,
217
+ normalized: normalizeFactValue(value),
218
+ });
219
+ }
220
+
221
+ return facts;
222
+ }
223
+
224
+ function addFactConflicts(docsByPath, warnings, errors, options = {}) {
225
+ const projectMap = docsByPath.get('docs/PROJECT_MAP.md');
226
+ if (!projectMap?.managedBlock?.ok) {
227
+ return;
228
+ }
229
+
230
+ const projectFacts = extractFactEntries('docs/PROJECT_MAP.md', projectMap.managedBlock.content);
231
+ const contextPaths = ['docs/CONTEXTO.md', 'docs/AI_CONTEXT.md'];
232
+
233
+ for (const contextPath of contextPaths) {
234
+ const contextDoc = docsByPath.get(contextPath);
235
+ if (!contextDoc?.managedBlock?.ok) {
236
+ continue;
237
+ }
238
+ const contextFacts = extractFactEntries(contextPath, contextDoc.managedBlock.content);
239
+ for (const [key, entries] of contextFacts.entries()) {
240
+ const mapEntries = projectFacts.get(key) || [];
241
+ for (const contextEntry of entries) {
242
+ for (const mapEntry of mapEntries) {
243
+ if (contextEntry.normalized === mapEntry.normalized) {
244
+ continue;
245
+ }
246
+ const issue = makeIssue(contextPath, 'deterministic-doc-conflict', `${contextPath} says ${key}=${contextEntry.value}, but docs/PROJECT_MAP.md says ${key}=${mapEntry.value}.`, {
247
+ key,
248
+ project_map_value: mapEntry.value,
249
+ context_value: contextEntry.value,
250
+ });
251
+ if (options.strict === true) {
252
+ errors.push(issue);
253
+ } else {
254
+ warnings.push(issue);
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+ function validateAnalyzeProjectPostWrite(repoRoot, report, options = {}) {
263
+ const errors = [];
264
+ const warnings = [];
265
+ const checkedDocs = [];
266
+ const docsByPath = new Map();
267
+
268
+ addSchemaValidation(report || {}, errors);
269
+ addManifestValidation(repoRoot, report || {}, errors);
270
+
271
+ for (const docPath of collectChangedDocPaths(report || {})) {
272
+ const file = readRelativeFile(repoRoot, docPath);
273
+ checkedDocs.push(docPath);
274
+ if (!file.ok) {
275
+ errors.push(makeIssue(file.path, file.issue, file.message));
276
+ continue;
277
+ }
278
+
279
+ const managedBlock = extractManagedBlock(file.content);
280
+ docsByPath.set(docPath, {
281
+ content: file.content,
282
+ managedBlock,
283
+ });
284
+ if (!managedBlock.ok) {
285
+ errors.push(makeIssue(docPath, managedBlock.issue, `Quiver managed block is missing or unbalanced in ${docPath}.`));
286
+ continue;
287
+ }
288
+ addPlaceholderValidation(docPath, managedBlock.content, errors);
289
+ }
290
+
291
+ addFactConflicts(docsByPath, warnings, errors, { strict: options.strict === true });
292
+
293
+ return {
294
+ schema_version: 1,
295
+ kind: VALIDATION_KIND,
296
+ strict: options.strict === true,
297
+ ok: errors.length === 0,
298
+ checked_docs: checkedDocs,
299
+ errors,
300
+ warnings,
301
+ };
302
+ }
303
+
304
+ module.exports = {
305
+ VALIDATION_KIND,
306
+ extractFactEntries,
307
+ extractManagedBlock,
308
+ validateAnalyzeProjectPostWrite,
309
+ };
@@ -33,7 +33,10 @@ function escapeRegExp(value) {
33
33
  }
34
34
 
35
35
  function redactSensitiveLocalValues(text, options = {}) {
36
- let result = redactSecrets(text);
36
+ let result = redactSecrets(text)
37
+ .replace(/\bsk-[A-Za-z0-9_-]{16,}\b/g, '[REDACTED]')
38
+ .replace(/\bghp_[A-Za-z0-9_]{16,}\b/g, '[REDACTED]')
39
+ .replace(/\bgithub_pat_[A-Za-z0-9_]{16,}\b/g, '[REDACTED]');
37
40
  const replacements = [];
38
41
 
39
42
  if (options.projectRoot) {
@@ -3,7 +3,7 @@ const os = require('node:os');
3
3
  const path = require('node:path');
4
4
  const { spawnSync } = require('node:child_process');
5
5
 
6
- const { currentBranch, hasRemote, isCleanWorktree } = require('../git');
6
+ const { currentBranch, hasRemote, isCleanWorktree, resolveBaseBranchName } = require('../git');
7
7
  const { createTranslator } = require('../i18n/catalog');
8
8
  const { parseJsonWithComments } = require('../json');
9
9
  const { formatActionableError } = require('../actionable-error');
@@ -510,7 +510,10 @@ function buildPrCreateArgs(plan) {
510
510
  function buildPrCreatePlan(repoRoot, preflightReport, options = {}) {
511
511
  const prBody = readPrBody(repoRoot, options.prBodyPath || options.input);
512
512
  ensureNoOpenSlicesForPrBody(repoRoot, prBody.path);
513
- const baseBranch = String(options.baseBranch || 'main').trim() || 'main';
513
+ const baseBranch = resolveBaseBranchName(repoRoot, {
514
+ explicitBaseBranch: options.baseBranch,
515
+ remote: preflightReport.remote || DEFAULT_REMOTE,
516
+ });
514
517
  const title = String(options.title || '').trim() || extractPrTitle(prBody.body, preflightReport.branchName);
515
518
  const plan = {
516
519
  baseBranch,
@@ -289,6 +289,25 @@ function buildPrMarkdown(manifest) {
289
289
  '',
290
290
  'Generate the spec foundation, slice-00, implementation slices, execution plan, and PR body from the approved planning input.',
291
291
  '',
292
+ '## PR Policy',
293
+ '',
294
+ '- [ ] One slice only.',
295
+ '- [ ] Grouped PR exception: at most 2-3 slices, all docs-only, research-only, or low-risk mechanical cleanup.',
296
+ '- [ ] No behavior changes in a grouped PR.',
297
+ '- [ ] No mixed docs with UI, backend, refactor, or performance work.',
298
+ '- [ ] Separate evidence for each included slice.',
299
+ '- [ ] Whole PR is revertible without leaving partial state.',
300
+ '',
301
+ 'Individual PR required when the slice includes functional code, UI/UX, Supabase, Edge Functions, auth, storage, preview, performance/code-splitting, refactors, or tests/CI changes that affect gates.',
302
+ '',
303
+ '### Merge Policy',
304
+ '',
305
+ '- [ ] Human merge expected.',
306
+ '- [ ] Assisted auto-merge explicitly authorized for this PR or documented category.',
307
+ '- [ ] Assisted auto-merge conditions met: docs-only or chore-only, low risk, no runtime changes, no production configuration changes, green checks, and no pending comments.',
308
+ '',
309
+ 'Assisted auto-merge is prohibited for UI, Supabase, Edge Functions, auth, storage, preview, performance, refactors, and changes with doubtful rollback.',
310
+ '',
292
311
  '## Scope',
293
312
  '',
294
313
  '- `SPEC.md`',
@@ -0,0 +1,72 @@
1
+ const SUPPORTED_COMMAND_MODES = new Set([
2
+ 'init',
3
+ 'version',
4
+ 'changelog',
5
+ 'flow',
6
+ 'dashboard',
7
+ 'plan',
8
+ 'graph',
9
+ 'next',
10
+ 'doctor',
11
+ 'prepare',
12
+ 'analyze',
13
+ 'migrate',
14
+ 'slice',
15
+ 'handoff',
16
+ 'start-slice',
17
+ 'check-slice',
18
+ 'check-pr',
19
+ 'check-handoff',
20
+ 'new-handoff',
21
+ 'cleanup-slice',
22
+ 'check-scope',
23
+ 'config',
24
+ 'refresh-active-slices',
25
+ 'spec',
26
+ 'evidence',
27
+ 'demo',
28
+ 'ai',
29
+ ]);
30
+
31
+ const SUPPORTED_AI_COMMANDS = new Set([
32
+ 'active-slice',
33
+ 'agent',
34
+ 'analyze-project',
35
+ 'approve',
36
+ 'approval-status',
37
+ 'approvals',
38
+ 'doctor',
39
+ 'execute-plan',
40
+ 'execute-slice',
41
+ 'executor-prompt',
42
+ 'export',
43
+ 'inspect',
44
+ 'onboard',
45
+ 'plan',
46
+ 'prepare-context',
47
+ 'pr',
48
+ 'prompt-slice',
49
+ 'repair-plan',
50
+ 'review-plan',
51
+ 'revise',
52
+ 'resume',
53
+ 'run',
54
+ 'slices',
55
+ 'specs',
56
+ 'status',
57
+ 'trace',
58
+ ]);
59
+
60
+ const SUPPORTED_SPEC_COMMANDS = new Set(['close', 'create', 'start', 'status', 'validate']);
61
+ const SUPPORTED_DEMO_COMMANDS = new Set(['create']);
62
+ const SUPPORTED_CONFIG_SECTIONS = new Set(['language']);
63
+ const SUPPORTED_CONFIG_LANGUAGE_COMMANDS = new Set(['show', 'set']);
64
+
65
+ module.exports = {
66
+ SUPPORTED_AI_COMMANDS,
67
+ SUPPORTED_COMMAND_MODES,
68
+ SUPPORTED_CONFIG_LANGUAGE_COMMANDS,
69
+ SUPPORTED_CONFIG_SECTIONS,
70
+ SUPPORTED_DEMO_COMMANDS,
71
+ SUPPORTED_SPEC_COMMANDS,
72
+ };
@@ -0,0 +1,14 @@
1
+ function parseCliArgs(argv, options = {}) {
2
+ const legacyParseArgs = options.legacyParseArgs;
3
+ if (typeof legacyParseArgs !== 'function') {
4
+ throw new TypeError('parseCliArgs requires a legacyParseArgs adapter');
5
+ }
6
+
7
+ return legacyParseArgs(argv, {
8
+ language: options.language,
9
+ });
10
+ }
11
+
12
+ module.exports = {
13
+ parseCliArgs,
14
+ };