create-quiver 0.15.3 → 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 +79 -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/AGENTS.md.es.template +37 -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 +37 -0
- package/docs/AI_CONTEXT.md.template +3 -1
- package/docs/AI_ONBOARDING_PROMPT.md.es.template +22 -0
- package/docs/CLI_UX_GUIDE.md +55 -1
- package/docs/COMMANDS.md.es.template +28 -0
- package/docs/COMMANDS.md.template +20 -6
- package/docs/CONTEXTO.md.es.template +33 -0
- package/docs/DECISIONS.md.es.template +17 -0
- package/docs/GITFLOW_PR_GUIDE.md +73 -11
- package/docs/GITFLOW_PR_GUIDE.md.es.template +84 -0
- package/docs/GITFLOW_PR_GUIDE.md.template +72 -10
- package/docs/INDEX.md +11 -1
- package/docs/INDEX.md.es.template +36 -0
- package/docs/QUICK.md.template +2 -1
- package/docs/STANDARD.md.template +2 -1
- package/docs/STATUS.md.es.template +28 -0
- package/docs/SUPPORT_MATRIX.md.es.template +22 -0
- package/docs/TESTING_GUIDE_FOR_AI.md.es.template +19 -0
- package/docs/TROUBLESHOOTING.md.es.template +35 -0
- package/docs/WORKFLOW.md.es.template +31 -0
- package/docs/WORKFLOW.md.template +6 -4
- package/docs/ai/ACTIVE_SLICE.md +61 -0
- package/docs/ai/LESSONS.md.es.template +24 -0
- package/docs/getting-started/installation.md +26 -0
- package/docs/reference/commands.md +159 -7
- 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-v37-cli-i18n-foundation/EVIDENCE_REPORT.md +73 -0
- package/specs/quiver-v37-cli-i18n-foundation/EXECUTION_PLAN.md +34 -0
- package/specs/quiver-v37-cli-i18n-foundation/SPEC.md +91 -0
- package/specs/quiver-v37-cli-i18n-foundation/STATUS.md +29 -0
- package/specs/quiver-v37-cli-i18n-foundation/pr.md +97 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-00-foundation-and-program-roadmap/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-00-foundation-and-program-roadmap/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-00-foundation-and-program-roadmap/slice.json +54 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-01-language-resolution-contract/CLOSURE_BRIEF.md +30 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-01-language-resolution-contract/EXECUTION_BRIEF.md +27 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-01-language-resolution-contract/slice.json +66 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-02-message-catalog-interpolation/CLOSURE_BRIEF.md +27 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-02-message-catalog-interpolation/EXECUTION_BRIEF.md +26 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-02-message-catalog-interpolation/slice.json +62 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-03-config-language-command/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-03-config-language-command/EXECUTION_BRIEF.md +25 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-03-config-language-command/slice.json +66 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-04-parser-help-error-foundation/CLOSURE_BRIEF.md +30 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-04-parser-help-error-foundation/EXECUTION_BRIEF.md +24 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-04-parser-help-error-foundation/slice.json +65 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-05-foundation-docs-tests-package-readiness/CLOSURE_BRIEF.md +27 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-05-foundation-docs-tests-package-readiness/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v37-cli-i18n-foundation/slices/slice-05-foundation-docs-tests-package-readiness/slice.json +67 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/EVIDENCE_REPORT.md +69 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/EXECUTION_PLAN.md +25 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/SPEC.md +52 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/STATUS.md +24 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/pr.md +119 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-00-read-only-foundation/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-00-read-only-foundation/EXECUTION_BRIEF.md +21 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-00-read-only-foundation/slice.json +53 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-01-version-dashboard-help/CLOSURE_BRIEF.md +17 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-01-version-dashboard-help/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-01-version-dashboard-help/slice.json +69 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-02-flow-doctor-next-graph/CLOSURE_BRIEF.md +13 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-02-flow-doctor-next-graph/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-02-flow-doctor-next-graph/slice.json +77 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-03-ai-inspection-and-export/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-03-ai-inspection-and-export/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-03-ai-inspection-and-export/slice.json +66 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-04-read-only-tests-smokes/CLOSURE_BRIEF.md +13 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-04-read-only-tests-smokes/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v38-cli-i18n-read-only-commands/slices/slice-04-read-only-tests-smokes/slice.json +61 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/EVIDENCE_REPORT.md +71 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/EXECUTION_PLAN.md +25 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/SPEC.md +53 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/STATUS.md +24 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/pr.md +104 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-00-setup-foundation/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-00-setup-foundation/EXECUTION_BRIEF.md +21 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-00-setup-foundation/slice.json +53 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-01-init-interactive-language/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-01-init-interactive-language/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-01-init-interactive-language/slice.json +68 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-02-analyze-migrate-prepare/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-02-analyze-migrate-prepare/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-02-analyze-migrate-prepare/slice.json +62 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-03-demo-evidence-onboarding/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-03-demo-evidence-onboarding/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-03-demo-evidence-onboarding/slice.json +72 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-04-setup-tests-smokes/CLOSURE_BRIEF.md +15 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-04-setup-tests-smokes/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v39-cli-i18n-setup-onboarding/slices/slice-04-setup-tests-smokes/slice.json +61 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/EVIDENCE_REPORT.md +50 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/EXECUTION_PLAN.md +25 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/SPEC.md +52 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/STATUS.md +24 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/pr.md +94 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-00-spec-slice-foundation/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-00-spec-slice-foundation/EXECUTION_BRIEF.md +21 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-00-spec-slice-foundation/slice.json +53 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-01-spec-create-start-status/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-01-spec-create-start-status/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-01-spec-create-start-status/slice.json +63 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-02-spec-validate-close/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-02-spec-validate-close/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-02-spec-validate-close/slice.json +63 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-03-slice-lifecycle-handoffs/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-03-slice-lifecycle-handoffs/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-03-slice-lifecycle-handoffs/slice.json +72 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-04-spec-slice-tests-smokes/CLOSURE_BRIEF.md +15 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-04-spec-slice-tests-smokes/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v40-cli-i18n-spec-slice-workflows/slices/slice-04-spec-slice-tests-smokes/slice.json +69 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/EVIDENCE_REPORT.md +90 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/EXECUTION_PLAN.md +33 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/SPEC.md +57 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/STATUS.md +26 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/pr.md +103 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-00-ai-i18n-foundation/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-00-ai-i18n-foundation/EXECUTION_BRIEF.md +21 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-00-ai-i18n-foundation/slice.json +53 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-01-ai-run-status-resume/CLOSURE_BRIEF.md +13 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-01-ai-run-status-resume/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-01-ai-run-status-resume/slice.json +68 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-02-ai-agent-models/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-02-ai-agent-models/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-02-ai-agent-models/slice.json +66 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-03-ai-planner-approval-review/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-03-ai-planner-approval-review/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-03-ai-planner-approval-review/slice.json +68 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-04-ai-execution-pr/CLOSURE_BRIEF.md +13 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-04-ai-execution-pr/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-04-ai-execution-pr/slice.json +72 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-05-ai-tests-smokes/CLOSURE_BRIEF.md +15 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-05-ai-tests-smokes/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-05-ai-tests-smokes/slice.json +66 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-06-ai-prepare-context-progress-i18n-fix/CLOSURE_BRIEF.md +11 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-06-ai-prepare-context-progress-i18n-fix/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v41-cli-i18n-ai-lifecycle/slices/slice-06-ai-prepare-context-progress-i18n-fix/slice.json +70 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/EVIDENCE_REPORT.md +64 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/EXECUTION_PLAN.md +26 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/SPEC.md +52 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/STATUS.md +24 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/pr.md +125 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-00-generated-docs-foundation/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-00-generated-docs-foundation/EXECUTION_BRIEF.md +21 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-00-generated-docs-foundation/slice.json +53 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-01-template-language-routing/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-01-template-language-routing/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-01-template-language-routing/slice.json +62 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-02-init-docs-and-i18n-assets/CLOSURE_BRIEF.md +11 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-02-init-docs-and-i18n-assets/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-02-init-docs-and-i18n-assets/slice.json +72 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-03-docs-reference-guides/CLOSURE_BRIEF.md +12 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-03-docs-reference-guides/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-03-docs-reference-guides/slice.json +60 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-04-generated-docs-tests-smokes/CLOSURE_BRIEF.md +16 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-04-generated-docs-tests-smokes/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v42-cli-i18n-generated-docs/slices/slice-04-generated-docs-tests-smokes/slice.json +62 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/EVIDENCE_REPORT.md +203 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/EXECUTION_PLAN.md +27 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/SPEC.md +54 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/STATUS.md +24 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/command-language-mode-matrix.json +636 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/cross-platform-smoke-matrix.md +35 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/pr.md +155 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-00-audit-foundation/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-00-audit-foundation/EXECUTION_BRIEF.md +21 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-00-audit-foundation/slice.json +53 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-01-command-language-mode-matrix/CLOSURE_BRIEF.md +13 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-01-command-language-mode-matrix/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-01-command-language-mode-matrix/slice.json +62 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-02-public-string-audit/CLOSURE_BRIEF.md +18 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-02-public-string-audit/EXECUTION_BRIEF.md +22 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-02-public-string-audit/slice.json +59 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-03-cross-platform-smokes/CLOSURE_BRIEF.md +15 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-03-cross-platform-smokes/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-03-cross-platform-smokes/slice.json +62 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-04-package-release-readiness/CLOSURE_BRIEF.md +17 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-04-package-release-readiness/EXECUTION_BRIEF.md +24 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/slices/slice-04-package-release-readiness/slice.json +66 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/EVIDENCE_REPORT.md +18 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/EXECUTION_PLAN.md +31 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/SPEC.md +118 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/STATUS.md +25 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/pr.md +92 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-00-tui-lite-contract-foundation/CLOSURE_BRIEF.md +11 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-00-tui-lite-contract-foundation/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-00-tui-lite-contract-foundation/slice.json +64 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-01-provider-stream-hooks/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-01-provider-stream-hooks/EXECUTION_BRIEF.md +24 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-01-provider-stream-hooks/slice.json +65 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-02-live-output-renderer/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-02-live-output-renderer/EXECUTION_BRIEF.md +24 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-02-live-output-renderer/slice.json +70 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-03-prepare-context-integration/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-03-prepare-context-integration/EXECUTION_BRIEF.md +25 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-03-prepare-context-integration/slice.json +70 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-04-planner-command-audit-adoption/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-04-planner-command-audit-adoption/EXECUTION_BRIEF.md +26 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-04-planner-command-audit-adoption/slice.json +72 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-05-docs-tests-readiness/CLOSURE_BRIEF.md +15 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-05-docs-tests-readiness/EXECUTION_BRIEF.md +26 -0
- package/specs/quiver-v44-provider-live-output-tui-lite/slices/slice-05-docs-tests-readiness/slice.json +75 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/EVIDENCE_REPORT.md +30 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/EXECUTION_PLAN.md +22 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/SPEC.md +49 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/STATUS.md +21 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/pr.md +67 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/slices/slice-00-ci-actions-foundation/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/slices/slice-00-ci-actions-foundation/EXECUTION_BRIEF.md +21 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/slices/slice-00-ci-actions-foundation/slice.json +48 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/slices/slice-01-actions-node24-readiness/CLOSURE_BRIEF.md +14 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/slices/slice-01-actions-node24-readiness/EXECUTION_BRIEF.md +23 -0
- package/specs/quiver-v45-ci-actions-node24-readiness/slices/slice-01-actions-node24-readiness/slice.json +65 -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/ai.js +485 -307
- package/src/create-quiver/commands/changelog.js +93 -0
- package/src/create-quiver/commands/config.js +135 -0
- package/src/create-quiver/commands/demo.js +2 -2
- package/src/create-quiver/commands/evidence.js +39 -6
- package/src/create-quiver/commands/flow.js +109 -16
- package/src/create-quiver/commands/graph.js +9 -2
- package/src/create-quiver/commands/next.js +21 -18
- package/src/create-quiver/commands/plan.js +29 -6
- package/src/create-quiver/commands/spec.js +94 -70
- package/src/create-quiver/index.js +798 -223
- package/src/create-quiver/lib/ai/execution-plan.js +23 -20
- package/src/create-quiver/lib/ai/executor.js +60 -44
- package/src/create-quiver/lib/ai/export-state.js +75 -64
- package/src/create-quiver/lib/ai/github.js +29 -23
- package/src/create-quiver/lib/ai/run-state.js +28 -25
- 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/dashboard.js +154 -111
- package/src/create-quiver/lib/demo.js +14 -12
- package/src/create-quiver/lib/evidence.js +161 -6
- package/src/create-quiver/lib/git.js +99 -0
- package/src/create-quiver/lib/handoff.js +16 -7
- package/src/create-quiver/lib/i18n/catalog.js +152 -0
- package/src/create-quiver/lib/i18n/language.js +279 -0
- package/src/create-quiver/lib/i18n/messages/en.js +898 -0
- package/src/create-quiver/lib/i18n/messages/es.js +1013 -0
- package/src/create-quiver/lib/i18n/read-only-format.js +26 -0
- package/src/create-quiver/lib/i18n/templates.js +172 -0
- package/src/create-quiver/lib/init-docs.js +19 -5
- package/src/create-quiver/lib/init-layout.js +15 -8
- package/src/create-quiver/lib/lifecycle.js +72 -67
- package/src/create-quiver/lib/readiness.js +131 -110
- package/src/create-quiver/lib/renderers/tree.js +9 -6
- package/src/create-quiver/lib/spec-worktrees.js +50 -64
- package/src/create-quiver/lib/version.js +11 -9
|
@@ -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,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const { createTranslator } = require('./i18n/catalog');
|
|
3
4
|
|
|
4
5
|
const REQUIRED_HEADINGS = [
|
|
5
6
|
'## Background',
|
|
@@ -141,23 +142,31 @@ function formatMinimalTemplate(kind) {
|
|
|
141
142
|
return lines.join('\n').trimEnd();
|
|
142
143
|
}
|
|
143
144
|
|
|
144
|
-
function formatMissingSectionsError(resolved, missingSections) {
|
|
145
|
+
function formatMissingSectionsError(resolved, missingSections, options = {}) {
|
|
146
|
+
const translator = createTranslator(options.language);
|
|
145
147
|
return [
|
|
146
|
-
`create-quiver: ${
|
|
148
|
+
`create-quiver: ${translator.t('handoff.error.missing_sections', {
|
|
149
|
+
sections: missingSections.join(', '),
|
|
150
|
+
subject: translator.t(`handoff.subject.${resolved.kind}`),
|
|
151
|
+
})}`,
|
|
147
152
|
'',
|
|
148
|
-
'
|
|
153
|
+
translator.t('handoff.accepted_headings'),
|
|
149
154
|
formatAliasGuidance(resolved.kind),
|
|
150
155
|
'',
|
|
151
|
-
'
|
|
156
|
+
translator.t('handoff.minimal_template'),
|
|
152
157
|
formatMinimalTemplate(resolved.kind),
|
|
153
158
|
].join('\n');
|
|
154
159
|
}
|
|
155
160
|
|
|
156
|
-
function checkHandoff(handoffInput, repoRoot = process.cwd()) {
|
|
161
|
+
function checkHandoff(handoffInput, repoRoot = process.cwd(), options = {}) {
|
|
157
162
|
const resolved = resolveHandoffPath(repoRoot, handoffInput);
|
|
163
|
+
const translator = createTranslator(options.language);
|
|
158
164
|
|
|
159
165
|
if (!fs.existsSync(resolved.absolutePath)) {
|
|
160
|
-
throw new Error(`create-quiver:
|
|
166
|
+
throw new Error(`create-quiver: ${translator.t('handoff.error.missing_file', {
|
|
167
|
+
path: resolved.relativePath,
|
|
168
|
+
subject: translator.t(`handoff.subject.${resolved.kind}`),
|
|
169
|
+
})}`);
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
const text = fs.readFileSync(resolved.absolutePath, 'utf8');
|
|
@@ -165,7 +174,7 @@ function checkHandoff(handoffInput, repoRoot = process.cwd()) {
|
|
|
165
174
|
? validateHandoffSections(text)
|
|
166
175
|
: validateBriefSections(text, resolved.kind);
|
|
167
176
|
if (missingSections.length > 0) {
|
|
168
|
-
throw new Error(formatMissingSectionsError(resolved, missingSections));
|
|
177
|
+
throw new Error(formatMissingSectionsError(resolved, missingSections, options));
|
|
169
178
|
}
|
|
170
179
|
|
|
171
180
|
return resolved;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
const { DEFAULT_LANGUAGE, SUPPORTED_LANGUAGES, normalizeLanguage } = require('./language');
|
|
2
|
+
const en = require('./messages/en');
|
|
3
|
+
const es = require('./messages/es');
|
|
4
|
+
|
|
5
|
+
const CATALOGS = Object.freeze({
|
|
6
|
+
en,
|
|
7
|
+
es,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
function getCatalog(language = DEFAULT_LANGUAGE) {
|
|
11
|
+
const normalized = normalizeLanguage(language) || DEFAULT_LANGUAGE;
|
|
12
|
+
return CATALOGS[normalized] || CATALOGS[DEFAULT_LANGUAGE];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function listMessageKeys(catalog) {
|
|
16
|
+
return Object.keys(catalog?.messages || {}).sort();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function validateCatalogCompleteness(catalogs = CATALOGS) {
|
|
20
|
+
const baseKeys = listMessageKeys(catalogs[DEFAULT_LANGUAGE]);
|
|
21
|
+
const missing = [];
|
|
22
|
+
const extra = [];
|
|
23
|
+
|
|
24
|
+
for (const language of SUPPORTED_LANGUAGES) {
|
|
25
|
+
const keys = listMessageKeys(catalogs[language]);
|
|
26
|
+
for (const key of baseKeys) {
|
|
27
|
+
if (!keys.includes(key)) {
|
|
28
|
+
missing.push(`${language}:${key}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const key of keys) {
|
|
32
|
+
if (!baseKeys.includes(key)) {
|
|
33
|
+
extra.push(`${language}:${key}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
ok: missing.length === 0 && extra.length === 0,
|
|
40
|
+
missing,
|
|
41
|
+
extra,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function assertCatalogCompleteness(catalogs = CATALOGS) {
|
|
46
|
+
const report = validateCatalogCompleteness(catalogs);
|
|
47
|
+
if (!report.ok) {
|
|
48
|
+
throw new Error([
|
|
49
|
+
'i18n catalog completeness failed',
|
|
50
|
+
...report.missing.map((item) => `missing ${item}`),
|
|
51
|
+
...report.extra.map((item) => `extra ${item}`),
|
|
52
|
+
].join('\n'));
|
|
53
|
+
}
|
|
54
|
+
return report;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function sanitizeInterpolationValue(value) {
|
|
58
|
+
if (value === null || typeof value === 'undefined') {
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return String(value)
|
|
63
|
+
.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, '')
|
|
64
|
+
.replace(/\r/g, '\\r')
|
|
65
|
+
.replace(/\n/g, '\\n')
|
|
66
|
+
.replace(/\t/g, '\\t')
|
|
67
|
+
.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, '');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function interpolate(template, params = {}) {
|
|
71
|
+
return String(template).replace(/\{([a-zA-Z0-9_.-]+)\}/g, (match, name) => {
|
|
72
|
+
if (!Object.prototype.hasOwnProperty.call(params, name)) {
|
|
73
|
+
return `[missing:${name}]`;
|
|
74
|
+
}
|
|
75
|
+
return sanitizeInterpolationValue(params[name]);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function selectPluralTemplate(message, params = {}) {
|
|
80
|
+
if (!message || typeof message !== 'object' || Array.isArray(message)) {
|
|
81
|
+
return message;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const count = Number(params.count);
|
|
85
|
+
if (count === 1 && typeof message.one === 'string') {
|
|
86
|
+
return message.one;
|
|
87
|
+
}
|
|
88
|
+
if (typeof message.other === 'string') {
|
|
89
|
+
return message.other;
|
|
90
|
+
}
|
|
91
|
+
if (typeof message.one === 'string') {
|
|
92
|
+
return message.one;
|
|
93
|
+
}
|
|
94
|
+
return '';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function resolveMessage(language, key) {
|
|
98
|
+
const catalog = getCatalog(language);
|
|
99
|
+
const message = catalog.messages[key];
|
|
100
|
+
if (typeof message !== 'undefined') {
|
|
101
|
+
return {
|
|
102
|
+
message,
|
|
103
|
+
language: catalog.metadata.language,
|
|
104
|
+
fallback: false,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const fallbackCatalog = getCatalog(DEFAULT_LANGUAGE);
|
|
109
|
+
const fallbackMessage = fallbackCatalog.messages[key];
|
|
110
|
+
if (typeof fallbackMessage !== 'undefined') {
|
|
111
|
+
return {
|
|
112
|
+
message: fallbackMessage,
|
|
113
|
+
language: DEFAULT_LANGUAGE,
|
|
114
|
+
fallback: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
message: `[missing:${key}]`,
|
|
120
|
+
language: DEFAULT_LANGUAGE,
|
|
121
|
+
fallback: true,
|
|
122
|
+
missing: true,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function translate(language, key, params = {}) {
|
|
127
|
+
const resolved = resolveMessage(language, key);
|
|
128
|
+
const template = selectPluralTemplate(resolved.message, params);
|
|
129
|
+
return interpolate(template, params);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function createTranslator(language = DEFAULT_LANGUAGE) {
|
|
133
|
+
return {
|
|
134
|
+
language: getCatalog(language).metadata.language,
|
|
135
|
+
t(key, params = {}) {
|
|
136
|
+
return translate(language, key, params);
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports = {
|
|
142
|
+
CATALOGS,
|
|
143
|
+
assertCatalogCompleteness,
|
|
144
|
+
createTranslator,
|
|
145
|
+
getCatalog,
|
|
146
|
+
interpolate,
|
|
147
|
+
listMessageKeys,
|
|
148
|
+
resolveMessage,
|
|
149
|
+
sanitizeInterpolationValue,
|
|
150
|
+
translate,
|
|
151
|
+
validateCatalogCompleteness,
|
|
152
|
+
};
|