create-quiver 0.15.4 → 0.16.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.
- package/.github/pull_request_template.md +17 -0
- package/.github/workflows/ci.yml +76 -0
- package/.markdown-link-check.json +15 -0
- package/.markdownlint.json +11 -0
- package/.quiver/runs/run-2026-06-09t19-14-39z/approvals.json +5 -0
- package/.quiver/runs/run-2026-06-09t19-14-39z/decisions.md +2 -0
- package/.quiver/runs/run-2026-06-09t19-14-39z/requirement.md +0 -0
- package/.quiver/runs/run-2026-06-09t19-14-39z/snapshots/20260609T191439Z/docs/INDEX.md +97 -0
- package/.quiver/runs/run-2026-06-09t19-14-39z/snapshots/20260609T191439Z/manifest.json +61 -0
- package/.quiver/runs/run-2026-06-09t19-14-39z/state.json +28 -0
- package/ACTIVE_SLICES.md +43 -0
- package/ARCHITECTURE.md +133 -0
- package/CHANGELOG.md +12 -0
- package/CONTRIBUTING.md +174 -9
- package/README.md +10 -1
- package/ROADMAP.md +4 -0
- package/SECURITY.md +9 -2
- package/auditoria-ux-ui-performance-documentacion.md +705 -0
- package/copys-landing-page.md +244 -0
- package/docs/AI_CONTEXT.md.es.template +3 -1
- package/docs/AI_CONTEXT.md.template +3 -1
- package/docs/CLI_UX_GUIDE.md +9 -1
- package/docs/COMMANDS.md.template +20 -6
- package/docs/GITFLOW_PR_GUIDE.md +73 -11
- package/docs/GITFLOW_PR_GUIDE.md.es.template +61 -2
- package/docs/GITFLOW_PR_GUIDE.md.template +72 -10
- package/docs/INDEX.md +1 -0
- package/docs/QUICK.md.template +2 -1
- package/docs/STANDARD.md.template +2 -1
- package/docs/WORKFLOW.md.es.template +3 -1
- package/docs/WORKFLOW.md.template +6 -4
- package/docs/ai/ACTIVE_SLICE.md +61 -0
- package/docs/getting-started/installation.md +7 -0
- package/docs/reference/commands.md +104 -6
- package/docs/reference/slice-schema.md +37 -0
- package/docs/schema/slice.schema.json +221 -0
- package/docs/specs/01-spec/01-slice/01-slice.json +36 -0
- package/docs/specs/01-spec/01-slice/01-slice.md +106 -0
- package/docs/specs/01-spec/01-slice/CLOSURE_BRIEF.md +80 -0
- package/docs/specs/01-spec/01-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/02-slice/02-slice.json +36 -0
- package/docs/specs/01-spec/02-slice/02-slice.md +108 -0
- package/docs/specs/01-spec/02-slice/CLOSURE_BRIEF.md +88 -0
- package/docs/specs/01-spec/02-slice/EXECUTION_BRIEF.md +40 -0
- package/docs/specs/01-spec/03-slice/03-slice.json +36 -0
- package/docs/specs/01-spec/03-slice/03-slice.md +103 -0
- package/docs/specs/01-spec/03-slice/CLOSURE_BRIEF.md +54 -0
- package/docs/specs/01-spec/03-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/04-slice/04-slice.json +36 -0
- package/docs/specs/01-spec/04-slice/04-slice.md +107 -0
- package/docs/specs/01-spec/04-slice/CLOSURE_BRIEF.md +46 -0
- package/docs/specs/01-spec/04-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/05-slice/05-slice.json +36 -0
- package/docs/specs/01-spec/05-slice/05-slice.md +106 -0
- package/docs/specs/01-spec/05-slice/CLOSURE_BRIEF.md +84 -0
- package/docs/specs/01-spec/05-slice/EXECUTION_BRIEF.md +109 -0
- package/docs/specs/01-spec/06-slice/06-slice.json +36 -0
- package/docs/specs/01-spec/06-slice/06-slice.md +107 -0
- package/docs/specs/01-spec/06-slice/CLOSURE_BRIEF.md +67 -0
- package/docs/specs/01-spec/06-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/07-slice/07-slice.json +36 -0
- package/docs/specs/01-spec/07-slice/07-slice.md +105 -0
- package/docs/specs/01-spec/07-slice/CLOSURE_BRIEF.md +71 -0
- package/docs/specs/01-spec/07-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/08-slice/08-slice.json +36 -0
- package/docs/specs/01-spec/08-slice/08-slice.md +105 -0
- package/docs/specs/01-spec/08-slice/CLOSURE_BRIEF.md +114 -0
- package/docs/specs/01-spec/08-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/CLOSURE_BRIEF.md +87 -0
- package/docs/specs/01-spec/spec.md +197 -0
- package/docs/workflows/full-ai-spec-to-pr.md +46 -3
- package/i18n/es/docs/GITFLOW_PR_GUIDE.md.template +38 -1
- package/package.json +27 -1
- package/pr.md +154 -0
- package/scripts/package-quiver.sh +82 -2
- package/scripts/release-quiver.sh +14 -3
- package/specs/[project-name]/slices/pr.md.template +19 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/command-language-mode-matrix.json +91 -0
- package/specs/quiver-v50-audit-trust-foundation/EVIDENCE_REPORT.md +151 -0
- package/specs/quiver-v50-audit-trust-foundation/EXECUTION_PLAN.md +34 -0
- package/specs/quiver-v50-audit-trust-foundation/SPEC.md +113 -0
- package/specs/quiver-v50-audit-trust-foundation/STATUS.md +26 -0
- package/specs/quiver-v50-audit-trust-foundation/pr.md +120 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/CLOSURE_BRIEF.md +20 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/slice.json +57 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/CLOSURE_BRIEF.md +24 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/EXECUTION_BRIEF.md +67 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/slice.json +71 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/CLOSURE_BRIEF.md +24 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/EXECUTION_BRIEF.md +71 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/slice.json +81 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/CLOSURE_BRIEF.md +22 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/EXECUTION_BRIEF.md +57 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/slice.json +56 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/CLOSURE_BRIEF.md +23 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/EXECUTION_BRIEF.md +68 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/slice.json +84 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/CLOSURE_BRIEF.md +25 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/EXECUTION_BRIEF.md +73 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/slice.json +72 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/CLOSURE_BRIEF.md +22 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/EXECUTION_BRIEF.md +66 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/slice.json +74 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/CLOSURE_BRIEF.md +29 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/EXECUTION_BRIEF.md +74 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/slice.json +81 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/EVIDENCE_REPORT.md +145 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/EXECUTION_PLAN.md +32 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/SPEC.md +109 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/STATUS.md +25 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/pr.md +69 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/CLOSURE_BRIEF.md +20 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/slice.json +56 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/CLOSURE_BRIEF.md +21 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/EXECUTION_BRIEF.md +61 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/slice.json +68 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/CLOSURE_BRIEF.md +25 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/EXECUTION_BRIEF.md +65 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/pr.md +134 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/slice.json +80 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/CLOSURE_BRIEF.md +31 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/EXECUTION_BRIEF.md +80 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/pr.md +159 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/slice.json +102 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/CLOSURE_BRIEF.md +25 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/EXECUTION_BRIEF.md +74 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/pr.md +147 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/slice.json +91 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/CLOSURE_BRIEF.md +28 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/EXECUTION_BRIEF.md +73 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/pr.md +146 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/slice.json +100 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/CLOSURE_BRIEF.md +36 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/EXECUTION_BRIEF.md +76 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/pr.md +155 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/slice.json +111 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/EVIDENCE_REPORT.md +95 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/EXECUTION_PLAN.md +31 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/SPEC.md +107 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/STATUS.md +22 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/pr.md +69 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/CLOSURE_BRIEF.md +21 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/EXECUTION_BRIEF.md +60 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/slice.json +62 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/EXECUTION_BRIEF.md +71 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/pr.md +146 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/slice.json +106 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/EXECUTION_BRIEF.md +67 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/pr.md +144 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/slice.json +86 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/CLOSURE_BRIEF.md +38 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/EXECUTION_BRIEF.md +75 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/pr.md +159 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/slice.json +105 -0
- package/src/create-quiver/commands/changelog.js +93 -0
- package/src/create-quiver/commands/config.js +16 -5
- package/src/create-quiver/commands/evidence.js +33 -2
- package/src/create-quiver/commands/flow.js +1 -0
- package/src/create-quiver/commands/graph.js +8 -2
- package/src/create-quiver/commands/plan.js +6 -0
- package/src/create-quiver/commands/spec.js +28 -13
- package/src/create-quiver/index.js +294 -94
- package/src/create-quiver/lib/ai/github.js +5 -2
- package/src/create-quiver/lib/ai/spec-templates.js +19 -0
- package/src/create-quiver/lib/cli/command-registry.js +71 -0
- package/src/create-quiver/lib/cli/parser.js +14 -0
- package/src/create-quiver/lib/evidence.js +161 -6
- package/src/create-quiver/lib/git.js +99 -0
- package/src/create-quiver/lib/i18n/messages/en.js +52 -7
- package/src/create-quiver/lib/i18n/messages/es.js +54 -9
- package/src/create-quiver/lib/init-docs.js +1 -1
- package/src/create-quiver/lib/init-layout.js +9 -8
- package/src/create-quiver/lib/lifecycle.js +24 -26
- package/src/create-quiver/lib/readiness.js +67 -56
- package/src/create-quiver/lib/spec-worktrees.js +16 -34
|
@@ -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 =
|
|
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,71 @@
|
|
|
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
|
+
'approve',
|
|
35
|
+
'approval-status',
|
|
36
|
+
'approvals',
|
|
37
|
+
'doctor',
|
|
38
|
+
'execute-plan',
|
|
39
|
+
'execute-slice',
|
|
40
|
+
'executor-prompt',
|
|
41
|
+
'export',
|
|
42
|
+
'inspect',
|
|
43
|
+
'onboard',
|
|
44
|
+
'plan',
|
|
45
|
+
'prepare-context',
|
|
46
|
+
'pr',
|
|
47
|
+
'prompt-slice',
|
|
48
|
+
'repair-plan',
|
|
49
|
+
'review-plan',
|
|
50
|
+
'revise',
|
|
51
|
+
'resume',
|
|
52
|
+
'run',
|
|
53
|
+
'slices',
|
|
54
|
+
'specs',
|
|
55
|
+
'status',
|
|
56
|
+
'trace',
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
const SUPPORTED_SPEC_COMMANDS = new Set(['close', 'create', 'start', 'status', 'validate']);
|
|
60
|
+
const SUPPORTED_DEMO_COMMANDS = new Set(['create']);
|
|
61
|
+
const SUPPORTED_CONFIG_SECTIONS = new Set(['language']);
|
|
62
|
+
const SUPPORTED_CONFIG_LANGUAGE_COMMANDS = new Set(['show', 'set']);
|
|
63
|
+
|
|
64
|
+
module.exports = {
|
|
65
|
+
SUPPORTED_AI_COMMANDS,
|
|
66
|
+
SUPPORTED_COMMAND_MODES,
|
|
67
|
+
SUPPORTED_CONFIG_LANGUAGE_COMMANDS,
|
|
68
|
+
SUPPORTED_CONFIG_SECTIONS,
|
|
69
|
+
SUPPORTED_DEMO_COMMANDS,
|
|
70
|
+
SUPPORTED_SPEC_COMMANDS,
|
|
71
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -3,6 +3,23 @@ const path = require('path');
|
|
|
3
3
|
const { spawnSync } = require('node:child_process');
|
|
4
4
|
|
|
5
5
|
const DEFAULT_OUTPUT_LIMIT = 4000;
|
|
6
|
+
const SIGNAL_NUMBERS = {
|
|
7
|
+
SIGHUP: 1,
|
|
8
|
+
SIGINT: 2,
|
|
9
|
+
SIGQUIT: 3,
|
|
10
|
+
SIGILL: 4,
|
|
11
|
+
SIGTRAP: 5,
|
|
12
|
+
SIGABRT: 6,
|
|
13
|
+
SIGBUS: 7,
|
|
14
|
+
SIGFPE: 8,
|
|
15
|
+
SIGKILL: 9,
|
|
16
|
+
SIGUSR1: 10,
|
|
17
|
+
SIGSEGV: 11,
|
|
18
|
+
SIGUSR2: 12,
|
|
19
|
+
SIGPIPE: 13,
|
|
20
|
+
SIGALRM: 14,
|
|
21
|
+
SIGTERM: 15,
|
|
22
|
+
};
|
|
6
23
|
|
|
7
24
|
function redactSecrets(text) {
|
|
8
25
|
return String(text || '')
|
|
@@ -40,6 +57,83 @@ function defaultEvidencePath(repoRoot, startedAt = new Date()) {
|
|
|
40
57
|
return path.join(repoRoot, '.quiver', 'evidence', `evidence-${stamp}.md`);
|
|
41
58
|
}
|
|
42
59
|
|
|
60
|
+
function isPathInside(parentPath, childPath) {
|
|
61
|
+
const relative = path.relative(parentPath, childPath);
|
|
62
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function realpathExistingAncestor(targetPath) {
|
|
66
|
+
let current = targetPath;
|
|
67
|
+
while (!fs.existsSync(current)) {
|
|
68
|
+
const next = path.dirname(current);
|
|
69
|
+
if (next === current) {
|
|
70
|
+
return fs.realpathSync(current);
|
|
71
|
+
}
|
|
72
|
+
current = next;
|
|
73
|
+
}
|
|
74
|
+
return fs.realpathSync(current);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function assertSafeProjectPath(repoRoot, targetPath, label = 'evidence path') {
|
|
78
|
+
const rootPath = path.resolve(repoRoot);
|
|
79
|
+
const rootReal = fs.realpathSync(rootPath);
|
|
80
|
+
const resolved = path.resolve(rootPath, targetPath);
|
|
81
|
+
const ancestorReal = realpathExistingAncestor(resolved);
|
|
82
|
+
const pathLooksInsideRoot = isPathInside(rootPath, resolved) || isPathInside(rootReal, resolved);
|
|
83
|
+
|
|
84
|
+
if (!pathLooksInsideRoot || !isPathInside(rootReal, ancestorReal)) {
|
|
85
|
+
throw new Error(`create-quiver: ${label} must stay inside the project root.`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return resolved;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function resolveEvidenceOutputPath(repoRoot, outputPath, startedAtDate = new Date()) {
|
|
92
|
+
const resolved = outputPath
|
|
93
|
+
? assertSafeProjectPath(repoRoot, outputPath, 'evidence output path')
|
|
94
|
+
: defaultEvidencePath(repoRoot, startedAtDate);
|
|
95
|
+
const directory = path.dirname(resolved);
|
|
96
|
+
|
|
97
|
+
if (fs.existsSync(resolved) && fs.lstatSync(resolved).isSymbolicLink()) {
|
|
98
|
+
throw new Error('create-quiver: evidence output path cannot be a symlink.');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
102
|
+
const rootReal = fs.realpathSync(repoRoot);
|
|
103
|
+
const directoryReal = fs.realpathSync(directory);
|
|
104
|
+
if (!isPathInside(rootReal, directoryReal)) {
|
|
105
|
+
throw new Error('create-quiver: evidence output path must stay inside the project root.');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return resolved;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function resolveEvidenceReadPath(repoRoot, evidencePath) {
|
|
112
|
+
if (!evidencePath) {
|
|
113
|
+
throw new Error('create-quiver: evidence show requires an evidence file path.');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const resolved = assertSafeProjectPath(repoRoot, evidencePath, 'evidence read path');
|
|
117
|
+
if (!fs.existsSync(resolved)) {
|
|
118
|
+
throw new Error(`create-quiver: evidence file not found: ${evidencePath}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const rootReal = fs.realpathSync(repoRoot);
|
|
122
|
+
const fileReal = fs.realpathSync(resolved);
|
|
123
|
+
if (!isPathInside(rootReal, fileReal)) {
|
|
124
|
+
throw new Error('create-quiver: evidence read path must stay inside the project root.');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return resolved;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function signalExitCode(signal) {
|
|
131
|
+
if (!signal) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return 128 + (SIGNAL_NUMBERS[signal] || 0) || 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
43
137
|
function renderEvidenceMarkdown(record) {
|
|
44
138
|
return `# Quiver Evidence
|
|
45
139
|
|
|
@@ -48,6 +142,7 @@ function renderEvidenceMarkdown(record) {
|
|
|
48
142
|
- Duration ms: ${record.duration_ms}
|
|
49
143
|
- Started at: ${record.started_at}
|
|
50
144
|
- Finished at: ${record.finished_at}
|
|
145
|
+
- Signal: ${record.signal || '-'}
|
|
51
146
|
- Output truncated: ${record.output_truncated ? 'yes' : 'no'}
|
|
52
147
|
|
|
53
148
|
## Stdout
|
|
@@ -66,10 +161,11 @@ ${record.stderr || ''}
|
|
|
66
161
|
|
|
67
162
|
function runEvidenceCommand(repoRoot, commandArgs, options = {}) {
|
|
68
163
|
if (!Array.isArray(commandArgs) || commandArgs.length === 0) {
|
|
69
|
-
throw new Error('create-quiver: evidence run requires a command after --');
|
|
164
|
+
throw new Error(options.missingCommandMessage || 'create-quiver: evidence run requires a command after --');
|
|
70
165
|
}
|
|
71
166
|
|
|
72
167
|
const startedAtDate = new Date();
|
|
168
|
+
const outputPath = resolveEvidenceOutputPath(repoRoot, options.outputPath, startedAtDate);
|
|
73
169
|
const started = Date.now();
|
|
74
170
|
const result = (options.spawnSync || spawnSync)(commandArgs[0], commandArgs.slice(1), {
|
|
75
171
|
cwd: repoRoot,
|
|
@@ -78,7 +174,8 @@ function runEvidenceCommand(repoRoot, commandArgs, options = {}) {
|
|
|
78
174
|
});
|
|
79
175
|
const finishedAtDate = new Date();
|
|
80
176
|
const duration = Date.now() - started;
|
|
81
|
-
const
|
|
177
|
+
const signal = result.signal || '';
|
|
178
|
+
const exitCode = typeof result.status === 'number' ? result.status : (signalExitCode(signal) || 1);
|
|
82
179
|
const stdout = truncateText(redactSecrets(result.stdout || ''), options.maxOutput || DEFAULT_OUTPUT_LIMIT);
|
|
83
180
|
const stderr = truncateText(redactSecrets(result.stderr || result.error?.message || ''), options.maxOutput || DEFAULT_OUTPUT_LIMIT);
|
|
84
181
|
const record = {
|
|
@@ -87,15 +184,12 @@ function runEvidenceCommand(repoRoot, commandArgs, options = {}) {
|
|
|
87
184
|
exit_code: exitCode,
|
|
88
185
|
finished_at: finishedAtDate.toISOString(),
|
|
89
186
|
output_truncated: stdout.truncated || stderr.truncated,
|
|
187
|
+
signal,
|
|
90
188
|
stderr: stderr.text,
|
|
91
189
|
stdout: stdout.text,
|
|
92
190
|
started_at: startedAtDate.toISOString(),
|
|
93
191
|
};
|
|
94
|
-
const outputPath = options.outputPath
|
|
95
|
-
? path.resolve(repoRoot, options.outputPath)
|
|
96
|
-
: defaultEvidencePath(repoRoot, startedAtDate);
|
|
97
192
|
|
|
98
|
-
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
99
193
|
fs.writeFileSync(outputPath, renderEvidenceMarkdown(record));
|
|
100
194
|
|
|
101
195
|
return {
|
|
@@ -105,11 +199,72 @@ function runEvidenceCommand(repoRoot, commandArgs, options = {}) {
|
|
|
105
199
|
};
|
|
106
200
|
}
|
|
107
201
|
|
|
202
|
+
function parseEvidenceMarkdown(content) {
|
|
203
|
+
const text = String(content || '');
|
|
204
|
+
const field = (label) => {
|
|
205
|
+
const match = text.match(new RegExp(`^- ${label}: (.*)$`, 'm'));
|
|
206
|
+
return match ? match[1].trim() : '';
|
|
207
|
+
};
|
|
208
|
+
const rawExitCode = field('Exit code');
|
|
209
|
+
const rawDuration = field('Duration ms');
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
command: field('Command').replace(/^`|`$/g, ''),
|
|
213
|
+
duration_ms: Number.isFinite(Number(rawDuration)) ? Number(rawDuration) : null,
|
|
214
|
+
exit_code: Number.isFinite(Number(rawExitCode)) ? Number(rawExitCode) : null,
|
|
215
|
+
finished_at: field('Finished at'),
|
|
216
|
+
output_truncated: field('Output truncated') === 'yes',
|
|
217
|
+
signal: field('Signal') === '-' ? '' : field('Signal'),
|
|
218
|
+
started_at: field('Started at'),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function listEvidenceFiles(repoRoot) {
|
|
223
|
+
const evidenceDir = path.join(repoRoot, '.quiver', 'evidence');
|
|
224
|
+
if (!fs.existsSync(evidenceDir)) {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const rootReal = fs.realpathSync(repoRoot);
|
|
229
|
+
const dirReal = fs.realpathSync(evidenceDir);
|
|
230
|
+
if (!isPathInside(rootReal, dirReal)) {
|
|
231
|
+
throw new Error('create-quiver: evidence directory must stay inside the project root.');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return fs.readdirSync(evidenceDir)
|
|
235
|
+
.filter((entry) => entry.endsWith('.md'))
|
|
236
|
+
.sort()
|
|
237
|
+
.map((entry) => {
|
|
238
|
+
const filePath = path.join(evidenceDir, entry);
|
|
239
|
+
const content = fs.readFileSync(resolveEvidenceReadPath(repoRoot, filePath), 'utf8');
|
|
240
|
+
return {
|
|
241
|
+
path: path.relative(repoRoot, filePath).split(path.sep).join('/'),
|
|
242
|
+
...parseEvidenceMarkdown(content),
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function showEvidenceFile(repoRoot, evidencePath) {
|
|
248
|
+
const resolved = resolveEvidenceReadPath(repoRoot, evidencePath);
|
|
249
|
+
const content = fs.readFileSync(resolved, 'utf8');
|
|
250
|
+
return {
|
|
251
|
+
content,
|
|
252
|
+
path: path.relative(repoRoot, resolved).split(path.sep).join('/'),
|
|
253
|
+
record: parseEvidenceMarkdown(content),
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
108
257
|
module.exports = {
|
|
109
258
|
DEFAULT_OUTPUT_LIMIT,
|
|
110
259
|
defaultEvidencePath,
|
|
260
|
+
listEvidenceFiles,
|
|
261
|
+
parseEvidenceMarkdown,
|
|
111
262
|
redactSecrets,
|
|
112
263
|
renderEvidenceMarkdown,
|
|
264
|
+
resolveEvidenceOutputPath,
|
|
265
|
+
resolveEvidenceReadPath,
|
|
113
266
|
runEvidenceCommand,
|
|
267
|
+
showEvidenceFile,
|
|
268
|
+
signalExitCode,
|
|
114
269
|
truncateText,
|
|
115
270
|
};
|
|
@@ -2,6 +2,8 @@ const cp = require('child_process');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
|
|
5
|
+
const DEFAULT_BASE_BRANCH_CANDIDATES = ['main', 'master', 'develop'];
|
|
6
|
+
|
|
5
7
|
function runGit(args, cwd, options = {}) {
|
|
6
8
|
return cp.execFileSync('git', args, {
|
|
7
9
|
cwd,
|
|
@@ -123,6 +125,98 @@ function hasRemote(repoRoot, remoteName = 'origin') {
|
|
|
123
125
|
return remoteList(repoRoot).includes(remoteName);
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
function normalizeBranchName(value) {
|
|
129
|
+
return String(value || '').trim();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function remoteHeadBranch(repoRoot, remote = 'origin') {
|
|
133
|
+
const value = tryGit(['symbolic-ref', '--quiet', '--short', `refs/remotes/${remote}/HEAD`], repoRoot);
|
|
134
|
+
const prefix = `${remote}/`;
|
|
135
|
+
return value.startsWith(prefix) ? value.slice(prefix.length) : '';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function uniqueBaseCandidates(candidates) {
|
|
139
|
+
const seen = new Set();
|
|
140
|
+
return candidates.filter((candidate) => {
|
|
141
|
+
const branch = normalizeBranchName(candidate.branch);
|
|
142
|
+
if (!branch || seen.has(branch)) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
seen.add(branch);
|
|
146
|
+
candidate.branch = branch;
|
|
147
|
+
return true;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function buildBaseBranchCandidates(repoRoot, options = {}) {
|
|
152
|
+
const remote = options.remote || 'origin';
|
|
153
|
+
const explicitBaseBranch = normalizeBranchName(options.explicitBaseBranch);
|
|
154
|
+
const preferredBaseBranch = normalizeBranchName(options.preferredBaseBranch);
|
|
155
|
+
const defaults = Array.isArray(options.defaultBranches) && options.defaultBranches.length > 0
|
|
156
|
+
? options.defaultBranches
|
|
157
|
+
: DEFAULT_BASE_BRANCH_CANDIDATES;
|
|
158
|
+
|
|
159
|
+
if (explicitBaseBranch) {
|
|
160
|
+
return [{ branch: explicitBaseBranch, source: '--base', explicit: true }];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return uniqueBaseCandidates([
|
|
164
|
+
preferredBaseBranch ? { branch: preferredBaseBranch, source: options.preferredSource || 'slice.git.base_branch', explicit: false } : null,
|
|
165
|
+
{ branch: remoteHeadBranch(repoRoot, remote), source: 'remote HEAD', explicit: false },
|
|
166
|
+
...defaults.map((branch) => ({ branch, source: 'fallback', explicit: false })),
|
|
167
|
+
].filter(Boolean));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function resolveBaseRef(repoRoot, options = {}) {
|
|
171
|
+
const remote = options.remote || 'origin';
|
|
172
|
+
const candidates = buildBaseBranchCandidates(repoRoot, options);
|
|
173
|
+
|
|
174
|
+
for (const candidate of candidates) {
|
|
175
|
+
if (remote && hasRemoteBranch(repoRoot, candidate.branch, remote)) {
|
|
176
|
+
return {
|
|
177
|
+
baseBranch: candidate.branch,
|
|
178
|
+
baseRef: `${remote}/${candidate.branch}`,
|
|
179
|
+
candidates,
|
|
180
|
+
explicit: candidate.explicit,
|
|
181
|
+
remote,
|
|
182
|
+
source: candidate.source,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (hasLocalBranch(repoRoot, candidate.branch)) {
|
|
186
|
+
return {
|
|
187
|
+
baseBranch: candidate.branch,
|
|
188
|
+
baseRef: candidate.branch,
|
|
189
|
+
candidates,
|
|
190
|
+
explicit: candidate.explicit,
|
|
191
|
+
remote: '',
|
|
192
|
+
source: candidate.source,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (options.missingOk === true) {
|
|
198
|
+
const first = candidates[0] || { branch: '', source: 'fallback', explicit: false };
|
|
199
|
+
return {
|
|
200
|
+
baseBranch: first.branch,
|
|
201
|
+
baseRef: '',
|
|
202
|
+
candidates,
|
|
203
|
+
explicit: first.explicit,
|
|
204
|
+
remote: '',
|
|
205
|
+
source: first.source,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
throw new Error(`create-quiver: missing base branch. Tried: ${candidates.map((candidate) => candidate.branch).join(', ') || '(none)'}.`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function resolveBaseBranchName(repoRoot, options = {}) {
|
|
213
|
+
const resolution = resolveBaseRef(repoRoot, {
|
|
214
|
+
...options,
|
|
215
|
+
missingOk: true,
|
|
216
|
+
});
|
|
217
|
+
return resolution.baseBranch || DEFAULT_BASE_BRANCH_CANDIDATES[0];
|
|
218
|
+
}
|
|
219
|
+
|
|
126
220
|
function isCleanWorktree(repoRoot) {
|
|
127
221
|
return Boolean(repoRoot && fs.existsSync(repoRoot) && isGitWorktree(repoRoot) && statusPorcelain(repoRoot) === '');
|
|
128
222
|
}
|
|
@@ -195,8 +289,10 @@ function catFileExists(repoRoot, specRef) {
|
|
|
195
289
|
|
|
196
290
|
module.exports = {
|
|
197
291
|
branchDelete,
|
|
292
|
+
buildBaseBranchCandidates,
|
|
198
293
|
catFileExists,
|
|
199
294
|
currentBranch,
|
|
295
|
+
DEFAULT_BASE_BRANCH_CANDIDATES,
|
|
200
296
|
fetchBranch,
|
|
201
297
|
fetchRemote,
|
|
202
298
|
hasLocalBranch,
|
|
@@ -211,7 +307,10 @@ module.exports = {
|
|
|
211
307
|
isGitWorktree,
|
|
212
308
|
isLinkedWorktree,
|
|
213
309
|
revListCount,
|
|
310
|
+
remoteHeadBranch,
|
|
214
311
|
remoteList,
|
|
312
|
+
resolveBaseBranchName,
|
|
313
|
+
resolveBaseRef,
|
|
215
314
|
runGit,
|
|
216
315
|
statusPorcelain,
|
|
217
316
|
tryGit,
|
|
@@ -13,7 +13,9 @@ module.exports = {
|
|
|
13
13
|
},
|
|
14
14
|
groupTitles: {},
|
|
15
15
|
commandDescriptions: {},
|
|
16
|
-
optionDescriptions: {
|
|
16
|
+
optionDescriptions: {
|
|
17
|
+
'Show one human dashboard section': 'Show one human dashboard section (overview, specs, slices, blockers, warnings, agents, approvals, runs, active-slice, next-steps)',
|
|
18
|
+
},
|
|
17
19
|
},
|
|
18
20
|
'common.command.help': 'Run: npx create-quiver --help',
|
|
19
21
|
'common.language.current': 'Language: {language}',
|
|
@@ -28,6 +30,9 @@ module.exports = {
|
|
|
28
30
|
'common.unknown': 'unknown',
|
|
29
31
|
'common.warning': 'Warning: {message}',
|
|
30
32
|
'common.yes': 'yes',
|
|
33
|
+
'config.error.unsupported_language': 'unsupported language: {language}. Supported languages: {supported}. Run: npx create-quiver config language set {fallback}',
|
|
34
|
+
'config.error.unsupported_language_command': 'unsupported config language command: {command}. Supported commands: show, set',
|
|
35
|
+
'config.error.unsupported_section': 'unsupported config section: {section}. Supported sections: language',
|
|
31
36
|
'ai_task.command': 'Command: {command}',
|
|
32
37
|
'ai_task.context_pack': 'Context pack: {context}',
|
|
33
38
|
'ai_task.documentation_debt': 'Documentation debt: {count}',
|
|
@@ -320,6 +325,14 @@ module.exports = {
|
|
|
320
325
|
'analyze.detected_package_manager': 'Detected package manager: {manager}',
|
|
321
326
|
'analyze.detected_primary_stack': 'Detected primary stack: {stack}',
|
|
322
327
|
'analyze.dry_run_for': 'Project analysis dry-run for {path}',
|
|
328
|
+
'analyze.progress.artifacts_written': 'Analysis artifacts written',
|
|
329
|
+
'analyze.progress.context_refreshed': 'AI context refreshed',
|
|
330
|
+
'analyze.progress.refreshing_context': 'Refreshing AI context...',
|
|
331
|
+
'analyze.progress.scanned': 'Project scan completed',
|
|
332
|
+
'analyze.progress.scanning': 'Scanning project...',
|
|
333
|
+
'analyze.progress.state_updated': 'Analysis state updated',
|
|
334
|
+
'analyze.progress.updating_state': 'Updating Quiver state...',
|
|
335
|
+
'analyze.progress.writing_artifacts': 'Writing analysis artifacts...',
|
|
323
336
|
'analyze.would_refresh': 'Would refresh {path}',
|
|
324
337
|
'analyze.would_write': 'Would write {path}',
|
|
325
338
|
'analyze.writes_none': 'Writes: none',
|
|
@@ -352,7 +365,11 @@ module.exports = {
|
|
|
352
365
|
'demo.title.created': 'Quiver demo created',
|
|
353
366
|
'demo.title.dry_run': 'Quiver demo dry-run',
|
|
354
367
|
'evidence.command': 'Command: {command}',
|
|
368
|
+
'evidence.error.missing_command': 'evidence run requires a command after --',
|
|
369
|
+
'evidence.error.missing_subcommand': 'missing evidence subcommand. Use: npx create-quiver evidence <run|list|show>',
|
|
355
370
|
'evidence.exit_code': 'Exit code: {code}',
|
|
371
|
+
'evidence.list.empty': 'No evidence files found.',
|
|
372
|
+
'evidence.list.title': 'Quiver evidence files',
|
|
356
373
|
'evidence.output': 'Output: {path}',
|
|
357
374
|
'evidence.recorded': 'Quiver evidence recorded',
|
|
358
375
|
'init.agent_guidance.show.hint': 'Does not store credentials or execute providers',
|
|
@@ -379,6 +396,14 @@ module.exports = {
|
|
|
379
396
|
'init.next_steps.review_agents': 'Review AGENTS.md, then {path}',
|
|
380
397
|
'init.next_steps.review_workflow': 'Review {path}',
|
|
381
398
|
'init.next_steps.title': 'Next steps:',
|
|
399
|
+
'init.progress.docs_written': 'Init docs written',
|
|
400
|
+
'init.progress.exporting_templates': 'Exporting compatibility templates...',
|
|
401
|
+
'init.progress.install_checked': 'Package install checked',
|
|
402
|
+
'init.progress.installing_package': 'Checking create-quiver package install...',
|
|
403
|
+
'init.progress.preparing_templates': 'Preparing packaged templates...',
|
|
404
|
+
'init.progress.templates_exported': 'Compatibility templates exported',
|
|
405
|
+
'init.progress.templates_ready': 'Packaged templates ready',
|
|
406
|
+
'init.progress.writing_docs': 'Writing init docs...',
|
|
382
407
|
'init.profile.default.hint': 'Recommended AI-first contract',
|
|
383
408
|
'init.profile.full.hint': 'Includes historical compatibility and visible templates',
|
|
384
409
|
'init.profile.minimal.hint': 'Only essential documents',
|
|
@@ -396,6 +421,9 @@ module.exports = {
|
|
|
396
421
|
'init.summary.project': 'Project',
|
|
397
422
|
'init.summary.title': 'Selected configuration',
|
|
398
423
|
'migrate.completed_for': 'Quiver migration completed for {path}',
|
|
424
|
+
'migrate.confirm.declined': 'migrate canceled. No files were written.',
|
|
425
|
+
'migrate.confirm.prompt': 'This command will modify project files under {path}. Run `npx create-quiver migrate --dry-run` to preview. Continue?',
|
|
426
|
+
'migrate.confirm.required': 'migrate writes require confirmation before modifying project files. Run `npx create-quiver migrate --dry-run` to preview, or pass `--yes` to continue in automation.',
|
|
399
427
|
'migrate.dry_run_title': 'Quiver migration dry-run',
|
|
400
428
|
'migrate.legacy_preserved': 'Legacy layout detected and preserved: {paths}',
|
|
401
429
|
'migrate.next_command': 'Next command: {command}',
|
|
@@ -462,7 +490,9 @@ module.exports = {
|
|
|
462
490
|
'flow.stage.technical-plan-stale': 'technical plan needs revision',
|
|
463
491
|
'flow.suggested_sequence': 'Suggested sequence',
|
|
464
492
|
'flow.title': 'Quiver guided flow',
|
|
493
|
+
'graph.empty.level': 'No slices found for graph level {level}.',
|
|
465
494
|
'graph.empty.pending': 'No pending slices found.',
|
|
495
|
+
'graph.error.unsupported_format': 'unsupported graph format: {format}',
|
|
466
496
|
'graph.level': 'Level {level}',
|
|
467
497
|
'graph.lots_count': {
|
|
468
498
|
one: '{count} lot',
|
|
@@ -494,6 +524,10 @@ module.exports = {
|
|
|
494
524
|
'plan.header.status': 'STATUS',
|
|
495
525
|
'plan.header.ticket': 'TICKET',
|
|
496
526
|
'plan.header.title': 'TITLE',
|
|
527
|
+
'plan.missing_estimates_note': {
|
|
528
|
+
one: 'Note: {count} slice has no positive estimated_hours and is counted as 0h.',
|
|
529
|
+
other: 'Note: {count} slices have no positive estimated_hours and are counted as 0h.',
|
|
530
|
+
},
|
|
497
531
|
'plan.title': 'Quiver plan',
|
|
498
532
|
'plan.title.including_completed': 'Quiver plan (including completed)',
|
|
499
533
|
'plan.title.ready': 'Ready slices',
|
|
@@ -665,11 +699,11 @@ module.exports = {
|
|
|
665
699
|
'lifecycle.cleanup.dry_run.branch': 'DRY RUN: git branch {flag} {branch}',
|
|
666
700
|
'lifecycle.cleanup.dry_run.slice': 'DRY RUN: slice={slice} branch={branch}',
|
|
667
701
|
'lifecycle.cleanup.dry_run.worktree': 'DRY RUN: git worktree remove {force}{path}',
|
|
668
|
-
'lifecycle.cleanup.error.branch': 'normal cleanup must run from
|
|
669
|
-
'lifecycle.cleanup.error.
|
|
702
|
+
'lifecycle.cleanup.error.branch': 'normal cleanup must run from {base}. Current branch: {branch}',
|
|
703
|
+
'lifecycle.cleanup.error.base_stale': 'local {base} is not up to date with {ref}. Run git pull --ff-only before cleanup.',
|
|
670
704
|
'lifecycle.cleanup.error.dirty': 'the current checkout is not clean. Clean it before cleanup.',
|
|
671
705
|
'lifecycle.cleanup.error.missing': "no worktree or local branch exists for '{slice}'.",
|
|
672
|
-
'lifecycle.cleanup.error.unmerged': "branch '{branch}' is not merged into
|
|
706
|
+
'lifecycle.cleanup.error.unmerged': "branch '{branch}' is not merged into {ref}. Use --discard if the slice is intentionally discarded.",
|
|
673
707
|
'lifecycle.cleanup.finished': "PASS: Cleanup completed for '{slice}'.",
|
|
674
708
|
'lifecycle.cleanup.removed_active_slice': 'PASS: ACTIVE_SLICE.md removed',
|
|
675
709
|
'lifecycle.cleanup.removed_branch': 'PASS: Local branch removed: {branch}',
|
|
@@ -724,15 +758,15 @@ module.exports = {
|
|
|
724
758
|
'readiness.pr.branch.pass': 'PASS: Current branch matches the slice branch declaration.',
|
|
725
759
|
'readiness.pr.case.pass': 'PASS: At least one documented use case.',
|
|
726
760
|
'readiness.pr.clean.pass': 'PASS: Worktree is clean.',
|
|
727
|
-
'readiness.pr.commits.pass': 'PASS: Branch has own commits against
|
|
728
|
-
'readiness.pr.error.absorbed': 'The branch was already absorbed by
|
|
761
|
+
'readiness.pr.commits.pass': 'PASS: Branch has own commits against {ref}.',
|
|
762
|
+
'readiness.pr.error.absorbed': 'The branch was already absorbed by {ref}. This gate applies before merge.',
|
|
729
763
|
'readiness.pr.error.dirty': 'The worktree is not clean. Close the implementation before opening the PR.',
|
|
730
764
|
'readiness.pr.error.missing_branch': 'Missing git.branch_name in the slice.',
|
|
731
765
|
'readiness.pr.error.missing_pr': 'Missing pr.md next to the slice.',
|
|
732
766
|
'readiness.pr.error.missing_section': "Missing required section '{heading}' in pr.md.",
|
|
733
767
|
'readiness.pr.error.missing_subsection': "Missing subsection '{subheading}' inside How to Test.",
|
|
734
768
|
'readiness.pr.error.no_case': 'How to Test must include at least one documented use case (#### Case 1: ...).',
|
|
735
|
-
'readiness.pr.error.no_commits': 'The branch has no own commits against
|
|
769
|
+
'readiness.pr.error.no_commits': 'The branch has no own commits against {ref}.',
|
|
736
770
|
'readiness.pr.error.rollback': 'Rollback must include at least one git revert command.',
|
|
737
771
|
'readiness.pr.error.wrong_branch': 'Run this check from the slice branch. Current: {actual} Expected: {expected}',
|
|
738
772
|
'readiness.pr.how_to_test.pass': 'PASS: How to Test includes environment, worktree access, startup, use cases, and technical verification.',
|
|
@@ -750,6 +784,11 @@ module.exports = {
|
|
|
750
784
|
'readiness.spec_docs.pass': 'PASS: Local spec has SPEC.md, STATUS.md, and EVIDENCE_REPORT.md.',
|
|
751
785
|
'readiness.warn': 'WARN: {message}',
|
|
752
786
|
'spec_create.confirm_create': 'Create spec "{slug}"?',
|
|
787
|
+
'spec_create.error.approval_declined': 'spec create interactive approval declined. No files were written.',
|
|
788
|
+
'spec_create.error.interactive_tty_required': 'spec create --interactive requires an interactive TTY. Use --input, --spec, --review, and --dry-run for non-interactive automation.',
|
|
789
|
+
'spec_create.error.review_canceled': '{reason}\nReview artifact: {path}',
|
|
790
|
+
'spec_create.error.review_canceled.default_reason': 'spec create review was canceled.',
|
|
791
|
+
'spec_create.error.review_tty_required': 'spec create --review requires an interactive terminal or an injected editor runner.\nReview artifact: {path}',
|
|
753
792
|
'spec_create.input.approved_plan_hint': 'Reviewed and approved technical plan',
|
|
754
793
|
'spec_create.label.files_written': 'Files written: {count}',
|
|
755
794
|
'spec_create.label.input_file': 'Input file: {path}',
|
|
@@ -817,6 +856,12 @@ module.exports = {
|
|
|
817
856
|
'spec_validate.strict': 'Strict: {value}',
|
|
818
857
|
'spec_validate.title': 'Quiver spec validation',
|
|
819
858
|
'spec_validate.warnings': 'Warnings:',
|
|
859
|
+
'spec.error.directory_not_found': 'spec directory not found: {path}',
|
|
860
|
+
'spec.error.directory_already_exists': 'spec directory already exists: {path}',
|
|
861
|
+
'spec.error.missing_approved_plan_input': 'missing reviewed and approved plan input: {path}',
|
|
862
|
+
'spec.error.missing_directory_command': 'missing spec directory. Use: npx create-quiver spec <start|status|validate|close> <spec-dir>',
|
|
863
|
+
'spec.error.missing_directory_validate': 'missing spec directory. Use: npx create-quiver spec validate specs/<spec-slug>',
|
|
864
|
+
'spec.error.validate_failed': 'spec validate failed for {path}',
|
|
820
865
|
'status.blocked': 'blocked',
|
|
821
866
|
'status.cancelled': 'cancelled',
|
|
822
867
|
'status.active': 'active',
|