frappe-builder 1.1.0-dev.10
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/.fb/state.db +0 -0
- package/AGENTS.md +167 -0
- package/README.md +89 -0
- package/_bmad/_config/agent-manifest.csv +10 -0
- package/_bmad/_config/agents/bmm-analyst.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-architect.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-dev.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-pm.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-qa.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-quick-flow-solo-dev.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-sm.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-tech-writer.customize.yaml +41 -0
- package/_bmad/_config/agents/bmm-ux-designer.customize.yaml +41 -0
- package/_bmad/_config/bmad-help.csv +47 -0
- package/_bmad/_config/files-manifest.csv +369 -0
- package/_bmad/_config/ides/claude-code.yaml +5 -0
- package/_bmad/_config/manifest.yaml +28 -0
- package/_bmad/_config/skill-manifest.csv +41 -0
- package/_bmad/_config/task-manifest.csv +1 -0
- package/_bmad/_config/tool-manifest.csv +1 -0
- package/_bmad/_config/workflow-manifest.csv +1 -0
- package/_bmad/_memory/config.yaml +11 -0
- package/_bmad/_memory/tech-writer-sidecar/documentation-standards.md +224 -0
- package/_bmad/bmm/agents/analyst.md +69 -0
- package/_bmad/bmm/agents/architect.md +59 -0
- package/_bmad/bmm/agents/bmad-skill-manifest.yaml +39 -0
- package/_bmad/bmm/agents/dev.md +66 -0
- package/_bmad/bmm/agents/pm.md +63 -0
- package/_bmad/bmm/agents/qa.md +89 -0
- package/_bmad/bmm/agents/quick-flow-solo-dev.md +61 -0
- package/_bmad/bmm/agents/sm.md +67 -0
- package/_bmad/bmm/agents/tech-writer/bmad-skill-manifest.yaml +3 -0
- package/_bmad/bmm/agents/tech-writer/tech-writer.md +67 -0
- package/_bmad/bmm/agents/ux-designer.md +58 -0
- package/_bmad/bmm/config.yaml +16 -0
- package/_bmad/bmm/data/project-context-template.md +26 -0
- package/_bmad/bmm/module-help.csv +32 -0
- package/_bmad/bmm/teams/default-party.csv +20 -0
- package/_bmad/bmm/teams/team-fullstack.yaml +12 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/SKILL.md +6 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/product-brief.template.md +10 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-01-init.md +170 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-01b-continue.md +158 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-02-vision.md +193 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-03-users.md +196 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-04-metrics.md +199 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-05-scope.md +213 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/steps/step-06-complete.md +159 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-create-product-brief/workflow.md +55 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/SKILL.md +88 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/artifact-analyzer.md +60 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/opportunity-reviewer.md +44 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/skeptic-reviewer.md +44 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/agents/web-researcher.md +49 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/bmad-manifest.json +17 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/contextual-discovery.md +57 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/draft-and-review.md +86 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/finalize.md +75 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/prompts/guided-elicitation.md +70 -0
- package/_bmad/bmm/workflows/1-analysis/bmad-product-brief-preview/resources/brief-template.md +60 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/SKILL.md +6 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-01-init.md +137 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-02-domain-analysis.md +229 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-03-competitive-landscape.md +238 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-04-regulatory-focus.md +206 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-05-technical-trends.md +234 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/domain-steps/step-06-research-synthesis.md +444 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/research.template.md +29 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-domain-research/workflow.md +49 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/SKILL.md +6 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/research.template.md +29 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-01-init.md +184 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-02-customer-behavior.md +239 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-03-customer-pain-points.md +251 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-04-customer-decisions.md +261 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-05-competitive-analysis.md +173 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/steps/step-06-research-completion.md +478 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-market-research/workflow.md +49 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/SKILL.md +6 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/research.template.md +29 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-01-init.md +137 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-02-technical-overview.md +239 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-03-integration-patterns.md +248 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-04-architectural-patterns.md +202 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-05-implementation-research.md +233 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/technical-steps/step-06-research-synthesis.md +487 -0
- package/_bmad/bmm/workflows/1-analysis/research/bmad-technical-research/workflow.md +50 -0
- package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-01-init.md +182 -0
- package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +237 -0
- package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +249 -0
- package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +259 -0
- package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +177 -0
- package/_bmad/bmm/workflows/1-analysis/research/market-steps/step-06-research-completion.md +476 -0
- package/_bmad/bmm/workflows/1-analysis/research/research.template.md +29 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/SKILL.md +6 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-01-init.md +135 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-01b-continue.md +127 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-02-discovery.md +190 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-03-core-experience.md +217 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-04-emotional-response.md +220 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-05-inspiration.md +235 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-06-design-system.md +253 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-07-defining-experience.md +255 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-08-visual-foundation.md +225 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-09-design-directions.md +225 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-10-user-journeys.md +242 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-11-component-strategy.md +249 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-12-ux-patterns.md +238 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-13-responsive-accessibility.md +265 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/steps/step-14-complete.md +171 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/ux-design-template.md +13 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-create-ux-design/workflow.md +36 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/SKILL.md +6 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01-discovery.md +242 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01b-legacy-conversion.md +204 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-02-review.md +245 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-03-edit.md +250 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/steps-e/step-e-04-complete.md +165 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-edit-prd/workflow.md +63 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/SKILL.md +6 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/data/domain-complexity.csv +15 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/data/prd-purpose.md +197 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/data/project-types.csv +11 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-01-discovery.md +221 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-02-format-detection.md +188 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-02b-parity-check.md +206 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-03-density-validation.md +171 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-04-brief-coverage-validation.md +211 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-05-measurability-validation.md +225 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-06-traceability-validation.md +214 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-07-implementation-leakage-validation.md +202 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-08-domain-compliance-validation.md +240 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-09-project-type-validation.md +260 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-10-smart-validation.md +206 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-11-holistic-quality-validation.md +261 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-12-completeness-validation.md +239 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/steps-v/step-v-13-report-complete.md +229 -0
- package/_bmad/bmm/workflows/2-plan-workflows/bmad-validate-prd/workflow.md +62 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/domain-complexity.csv +15 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md +197 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/project-types.csv +11 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +224 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +191 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +209 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +174 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +214 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +228 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +217 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +205 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +243 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +263 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +209 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +264 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +242 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +232 -0
- package/_bmad/bmm/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +65 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/SKILL.md +6 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-01-document-discovery.md +179 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-02-prd-analysis.md +168 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-03-epic-coverage-validation.md +169 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-04-ux-alignment.md +129 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-05-epic-quality-review.md +241 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/steps/step-06-final-assessment.md +126 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/templates/readiness-report-template.md +4 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-check-implementation-readiness/workflow.md +49 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/SKILL.md +6 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/architecture-decision-template.md +12 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/data/domain-complexity.csv +13 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/data/project-types.csv +7 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-01-init.md +153 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-01b-continue.md +173 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-02-context.md +224 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-03-starter.md +329 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-04-decisions.md +318 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-05-patterns.md +359 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-06-structure.md +379 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-07-validation.md +359 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/steps/step-08-complete.md +76 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-architecture/workflow.md +38 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/SKILL.md +6 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-01-validate-prerequisites.md +255 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-02-design-epics.md +212 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-03-create-stories.md +255 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/steps/step-04-final-validation.md +131 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/templates/epics-template.md +61 -0
- package/_bmad/bmm/workflows/3-solutioning/bmad-create-epics-and-stories/workflow.md +53 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-code-review/SKILL.md +6 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-code-review/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-01-gather-context.md +61 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-02-review.md +41 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-03-triage.md +50 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-code-review/steps/step-04-present.md +38 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-code-review/workflow.md +54 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/SKILL.md +6 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/checklist.md +288 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-correct-course/workflow.md +267 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-create-story/SKILL.md +6 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-create-story/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-create-story/checklist.md +357 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-create-story/discover-inputs.md +88 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-create-story/template.md +49 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-create-story/workflow.md +380 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/SKILL.md +6 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/checklist.md +80 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-dev-story/workflow.md +450 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-retrospective/SKILL.md +6 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-retrospective/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-retrospective/workflow.md +1479 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/SKILL.md +6 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/checklist.md +33 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/sprint-status-template.yaml +56 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-planning/workflow.md +263 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-status/SKILL.md +6 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-status/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/4-implementation/bmad-sprint-status/workflow.md +261 -0
- package/_bmad/bmm/workflows/bmad-document-project/SKILL.md +6 -0
- package/_bmad/bmm/workflows/bmad-document-project/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/bmad-document-project/checklist.md +245 -0
- package/_bmad/bmm/workflows/bmad-document-project/documentation-requirements.csv +12 -0
- package/_bmad/bmm/workflows/bmad-document-project/instructions.md +128 -0
- package/_bmad/bmm/workflows/bmad-document-project/templates/deep-dive-template.md +345 -0
- package/_bmad/bmm/workflows/bmad-document-project/templates/index-template.md +169 -0
- package/_bmad/bmm/workflows/bmad-document-project/templates/project-overview-template.md +103 -0
- package/_bmad/bmm/workflows/bmad-document-project/templates/project-scan-report-schema.json +160 -0
- package/_bmad/bmm/workflows/bmad-document-project/templates/source-tree-template.md +135 -0
- package/_bmad/bmm/workflows/bmad-document-project/workflow.md +27 -0
- package/_bmad/bmm/workflows/bmad-document-project/workflows/deep-dive-instructions.md +299 -0
- package/_bmad/bmm/workflows/bmad-document-project/workflows/deep-dive-workflow.md +34 -0
- package/_bmad/bmm/workflows/bmad-document-project/workflows/full-scan-instructions.md +1107 -0
- package/_bmad/bmm/workflows/bmad-document-project/workflows/full-scan-workflow.md +34 -0
- package/_bmad/bmm/workflows/bmad-generate-project-context/SKILL.md +6 -0
- package/_bmad/bmm/workflows/bmad-generate-project-context/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/bmad-generate-project-context/project-context-template.md +21 -0
- package/_bmad/bmm/workflows/bmad-generate-project-context/steps/step-01-discover.md +186 -0
- package/_bmad/bmm/workflows/bmad-generate-project-context/steps/step-02-generate.md +321 -0
- package/_bmad/bmm/workflows/bmad-generate-project-context/steps/step-03-complete.md +278 -0
- package/_bmad/bmm/workflows/bmad-generate-project-context/workflow.md +43 -0
- package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/SKILL.md +6 -0
- package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/checklist.md +33 -0
- package/_bmad/bmm/workflows/bmad-qa-generate-e2e-tests/workflow.md +136 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/SKILL.md +6 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-01-mode-detection.md +169 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-02-context-gathering.md +114 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-03-execute.md +107 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-04-self-check.md +107 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-05-adversarial-review.md +94 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/steps/step-06-resolve-findings.md +144 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev/workflow.md +38 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/SKILL.md +6 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-01-clarify-and-route.md +51 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-02-plan.md +35 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-03-implement.md +33 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md +50 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-05-present.md +17 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/tech-spec-template.md +90 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md +79 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/SKILL.md +6 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/bmad-skill-manifest.yaml +1 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-01-understand.md +185 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-02-investigate.md +140 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-03-generate.md +123 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/steps/step-04-review.md +195 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/tech-spec-template.md +74 -0
- package/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-spec/workflow.md +73 -0
- package/_bmad/cis/config.yaml +12 -0
- package/_bmad/cis/module-help.csv +6 -0
- package/_bmad/cis/skills/bmad-cis-agent-brainstorming-coach/SKILL.md +51 -0
- package/_bmad/cis/skills/bmad-cis-agent-brainstorming-coach/bmad-skill-manifest.yaml +11 -0
- package/_bmad/cis/skills/bmad-cis-agent-creative-problem-solver/SKILL.md +51 -0
- package/_bmad/cis/skills/bmad-cis-agent-creative-problem-solver/bmad-skill-manifest.yaml +11 -0
- package/_bmad/cis/skills/bmad-cis-agent-design-thinking-coach/SKILL.md +52 -0
- package/_bmad/cis/skills/bmad-cis-agent-design-thinking-coach/bmad-skill-manifest.yaml +11 -0
- package/_bmad/cis/skills/bmad-cis-agent-innovation-strategist/SKILL.md +51 -0
- package/_bmad/cis/skills/bmad-cis-agent-innovation-strategist/bmad-skill-manifest.yaml +11 -0
- package/_bmad/cis/skills/bmad-cis-agent-presentation-master/SKILL.md +62 -0
- package/_bmad/cis/skills/bmad-cis-agent-presentation-master/bmad-skill-manifest.yaml +11 -0
- package/_bmad/cis/skills/bmad-cis-agent-storyteller/SKILL.md +56 -0
- package/_bmad/cis/skills/bmad-cis-agent-storyteller/bmad-skill-manifest.yaml +11 -0
- package/_bmad/cis/skills/bmad-cis-agent-storyteller/stories-told.md +7 -0
- package/_bmad/cis/skills/bmad-cis-agent-storyteller/story-preferences.md +7 -0
- package/_bmad/cis/skills/bmad-cis-design-thinking/SKILL.md +6 -0
- package/_bmad/cis/skills/bmad-cis-design-thinking/bmad-skill-manifest.yaml +1 -0
- package/_bmad/cis/skills/bmad-cis-design-thinking/design-methods.csv +31 -0
- package/_bmad/cis/skills/bmad-cis-design-thinking/template.md +111 -0
- package/_bmad/cis/skills/bmad-cis-design-thinking/workflow.md +242 -0
- package/_bmad/cis/skills/bmad-cis-innovation-strategy/SKILL.md +6 -0
- package/_bmad/cis/skills/bmad-cis-innovation-strategy/bmad-skill-manifest.yaml +1 -0
- package/_bmad/cis/skills/bmad-cis-innovation-strategy/innovation-frameworks.csv +31 -0
- package/_bmad/cis/skills/bmad-cis-innovation-strategy/template.md +189 -0
- package/_bmad/cis/skills/bmad-cis-innovation-strategy/workflow.md +315 -0
- package/_bmad/cis/skills/bmad-cis-problem-solving/SKILL.md +6 -0
- package/_bmad/cis/skills/bmad-cis-problem-solving/bmad-skill-manifest.yaml +1 -0
- package/_bmad/cis/skills/bmad-cis-problem-solving/solving-methods.csv +31 -0
- package/_bmad/cis/skills/bmad-cis-problem-solving/template.md +165 -0
- package/_bmad/cis/skills/bmad-cis-problem-solving/workflow.md +291 -0
- package/_bmad/cis/skills/bmad-cis-storytelling/SKILL.md +6 -0
- package/_bmad/cis/skills/bmad-cis-storytelling/bmad-skill-manifest.yaml +1 -0
- package/_bmad/cis/skills/bmad-cis-storytelling/story-types.csv +26 -0
- package/_bmad/cis/skills/bmad-cis-storytelling/template.md +113 -0
- package/_bmad/cis/skills/bmad-cis-storytelling/workflow.md +321 -0
- package/_bmad/core/config.yaml +9 -0
- package/_bmad/core/module-help.csv +11 -0
- package/_bmad/core/skills/bmad-advanced-elicitation/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-advanced-elicitation/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-advanced-elicitation/methods.csv +51 -0
- package/_bmad/core/skills/bmad-advanced-elicitation/workflow.md +135 -0
- package/_bmad/core/skills/bmad-brainstorming/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-brainstorming/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-brainstorming/brain-methods.csv +62 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-01-session-setup.md +214 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-01b-continue.md +124 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-02a-user-selected.md +229 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-02b-ai-recommended.md +239 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-02c-random-selection.md +211 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-02d-progressive-flow.md +266 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-03-technique-execution.md +401 -0
- package/_bmad/core/skills/bmad-brainstorming/steps/step-04-idea-organization.md +305 -0
- package/_bmad/core/skills/bmad-brainstorming/template.md +15 -0
- package/_bmad/core/skills/bmad-brainstorming/workflow.md +53 -0
- package/_bmad/core/skills/bmad-distillator/SKILL.md +178 -0
- package/_bmad/core/skills/bmad-distillator/agents/distillate-compressor.md +116 -0
- package/_bmad/core/skills/bmad-distillator/agents/round-trip-reconstructor.md +68 -0
- package/_bmad/core/skills/bmad-distillator/bmad-skill-manifest.yaml +15 -0
- package/_bmad/core/skills/bmad-distillator/resources/compression-rules.md +51 -0
- package/_bmad/core/skills/bmad-distillator/resources/distillate-format-reference.md +227 -0
- package/_bmad/core/skills/bmad-distillator/resources/splitting-strategy.md +78 -0
- package/_bmad/core/skills/bmad-editorial-review-prose/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-editorial-review-prose/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-editorial-review-prose/workflow.md +81 -0
- package/_bmad/core/skills/bmad-editorial-review-structure/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-editorial-review-structure/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-editorial-review-structure/workflow.md +174 -0
- package/_bmad/core/skills/bmad-help/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-help/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-help/workflow.md +88 -0
- package/_bmad/core/skills/bmad-index-docs/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-index-docs/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-index-docs/workflow.md +61 -0
- package/_bmad/core/skills/bmad-party-mode/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-party-mode/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-party-mode/steps/step-01-agent-loading.md +138 -0
- package/_bmad/core/skills/bmad-party-mode/steps/step-02-discussion-orchestration.md +187 -0
- package/_bmad/core/skills/bmad-party-mode/steps/step-03-graceful-exit.md +167 -0
- package/_bmad/core/skills/bmad-party-mode/workflow.md +190 -0
- package/_bmad/core/skills/bmad-review-adversarial-general/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-review-adversarial-general/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-review-adversarial-general/workflow.md +32 -0
- package/_bmad/core/skills/bmad-review-edge-case-hunter/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-review-edge-case-hunter/workflow.md +62 -0
- package/_bmad/core/skills/bmad-shard-doc/SKILL.md +6 -0
- package/_bmad/core/skills/bmad-shard-doc/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/skills/bmad-shard-doc/workflow.md +100 -0
- package/_bmad/core/tasks/bmad-create-prd/SKILL.md +6 -0
- package/_bmad/core/tasks/bmad-create-prd/bmad-skill-manifest.yaml +1 -0
- package/_bmad/core/tasks/bmad-create-prd/data/domain-complexity.csv +15 -0
- package/_bmad/core/tasks/bmad-create-prd/data/prd-purpose.md +197 -0
- package/_bmad/core/tasks/bmad-create-prd/data/project-types.csv +11 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-01-init.md +178 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-01b-continue.md +161 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-02-discovery.md +208 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-02b-vision.md +142 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-02c-executive-summary.md +158 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-03-success.md +214 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-04-journeys.md +201 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-05-domain.md +194 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-06-innovation.md +211 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-07-project-type.md +222 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-08-scoping.md +216 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-09-functional.md +219 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-10-nonfunctional.md +230 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-11-polish.md +221 -0
- package/_bmad/core/tasks/bmad-create-prd/steps-c/step-12-complete.md +115 -0
- package/_bmad/core/tasks/bmad-create-prd/templates/prd-template.md +10 -0
- package/_bmad/core/tasks/bmad-create-prd/workflow.md +62 -0
- package/config/allowed-commands.ts +39 -0
- package/config/defaults.ts +19 -0
- package/config/loader.ts +105 -0
- package/dist/cli.mjs +67 -0
- package/dist/init-BYJy3ztn.mjs +159 -0
- package/extensions/frappe-gates.ts +160 -0
- package/extensions/frappe-session.ts +324 -0
- package/extensions/frappe-state.ts +235 -0
- package/extensions/frappe-tools.ts +278 -0
- package/extensions/frappe-ui.ts +119 -0
- package/extensions/frappe-workflow.ts +85 -0
- package/gates/coverage-check.ts +37 -0
- package/gates/frappe-native-check.ts +65 -0
- package/gates/permission-check.ts +65 -0
- package/gates/query-check.ts +40 -0
- package/gates/server-side-check.ts +67 -0
- package/gates/style-check.ts +92 -0
- package/gates/types.ts +13 -0
- package/package.json +47 -0
- package/project-context.md +146 -0
- package/state/db.ts +85 -0
- package/state/fsm.ts +68 -0
- package/state/journal.ts +164 -0
- package/state/schema.ts +41 -0
- package/tools/agent-tools.ts +60 -0
- package/tools/bench-tools.ts +63 -0
- package/tools/context-sandbox.ts +31 -0
- package/tools/debug-tools.ts +12 -0
- package/tools/feature-tools.ts +126 -0
- package/tools/frappe-context7.ts +70 -0
- package/tools/frappe-query-tools.ts +47 -0
- package/tools/project-tools.ts +107 -0
- package/tsdown.config.ts +7 -0
package/state/db.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import type { Database as DatabaseType } from "better-sqlite3";
|
|
3
|
+
import { mkdirSync } from "node:fs";
|
|
4
|
+
import { initSchema } from "./schema.js";
|
|
5
|
+
import { appendEntry } from "./journal.js";
|
|
6
|
+
|
|
7
|
+
mkdirSync(".fb", { recursive: true });
|
|
8
|
+
|
|
9
|
+
/** Singleton SQLite connection — the only Database instance in the codebase. */
|
|
10
|
+
export let db: DatabaseType = new Database(".fb/state.db");
|
|
11
|
+
|
|
12
|
+
initSchema(db);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Replaces the db singleton — intended for test use only.
|
|
16
|
+
* Pass a real in-memory Database(":memory:") seeded with initSchema().
|
|
17
|
+
*/
|
|
18
|
+
export function setDb(instance: DatabaseType): void {
|
|
19
|
+
db = instance;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Switches the active project: closes the current session atomically and opens
|
|
24
|
+
* a new session for newProjectId, restoring its last known phase if a prior
|
|
25
|
+
* session exists. Writes a "state_transition" JSONL entry before the close.
|
|
26
|
+
*
|
|
27
|
+
* sitePath is optional so existing callers without a site path continue to work.
|
|
28
|
+
*/
|
|
29
|
+
export function switchProject(newProjectId: string, sitePath?: string): void {
|
|
30
|
+
db.transaction(() => {
|
|
31
|
+
// 1. Read current active session before closing
|
|
32
|
+
const current = db
|
|
33
|
+
.prepare(
|
|
34
|
+
"SELECT session_id, project_id, current_phase FROM sessions WHERE is_active = 1 LIMIT 1"
|
|
35
|
+
)
|
|
36
|
+
.get() as
|
|
37
|
+
| { session_id: string; project_id: string; current_phase: string }
|
|
38
|
+
| undefined;
|
|
39
|
+
|
|
40
|
+
const previousProjectId = current?.project_id ?? "unknown";
|
|
41
|
+
const previousSessionId = current?.session_id ?? crypto.randomUUID();
|
|
42
|
+
|
|
43
|
+
// 2. Write JSONL transition entry (appendFileSync — safe inside transaction)
|
|
44
|
+
appendEntry({
|
|
45
|
+
ts: new Date().toISOString(),
|
|
46
|
+
sessionId: previousSessionId,
|
|
47
|
+
type: "state_transition",
|
|
48
|
+
payload: { from: previousProjectId, to: newProjectId },
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// 3. Close current session
|
|
52
|
+
db.prepare(
|
|
53
|
+
"UPDATE sessions SET is_active = 0, ended_at = ? WHERE is_active = 1"
|
|
54
|
+
).run(new Date().toISOString());
|
|
55
|
+
|
|
56
|
+
// 4. Check for prior session on new project (for phase restoration)
|
|
57
|
+
const prior = db
|
|
58
|
+
.prepare(
|
|
59
|
+
"SELECT current_phase FROM sessions WHERE project_id = ? ORDER BY started_at DESC LIMIT 1"
|
|
60
|
+
)
|
|
61
|
+
.get(newProjectId) as { current_phase: string } | undefined;
|
|
62
|
+
|
|
63
|
+
// 5. Create new session, restoring prior phase if available; feature_id defaults to NULL
|
|
64
|
+
db.prepare(
|
|
65
|
+
"INSERT INTO sessions (session_id, project_id, current_phase, site_path, started_at, is_active) VALUES (?, ?, ?, ?, ?, 1)"
|
|
66
|
+
).run(
|
|
67
|
+
crypto.randomUUID(),
|
|
68
|
+
newProjectId,
|
|
69
|
+
prior?.current_phase ?? "idle",
|
|
70
|
+
sitePath ?? null,
|
|
71
|
+
new Date().toISOString()
|
|
72
|
+
);
|
|
73
|
+
})();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Returns the current FSM phase from the active session row.
|
|
78
|
+
* Returns "idle" if no active session exists.
|
|
79
|
+
*/
|
|
80
|
+
export function getCurrentPhase(): string {
|
|
81
|
+
const row = db
|
|
82
|
+
.prepare("SELECT current_phase FROM sessions WHERE is_active = 1 LIMIT 1")
|
|
83
|
+
.get() as { current_phase: string } | undefined;
|
|
84
|
+
return row?.current_phase ?? "idle";
|
|
85
|
+
}
|
package/state/fsm.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createMachine, state, transition } from "robot3";
|
|
2
|
+
|
|
3
|
+
export type Phase =
|
|
4
|
+
| "idle"
|
|
5
|
+
| "requirements"
|
|
6
|
+
| "architecture"
|
|
7
|
+
| "planning"
|
|
8
|
+
| "implementation"
|
|
9
|
+
| "testing"
|
|
10
|
+
| "documentation";
|
|
11
|
+
|
|
12
|
+
export const ALL_PHASES: Phase[] = [
|
|
13
|
+
"idle",
|
|
14
|
+
"requirements",
|
|
15
|
+
"architecture",
|
|
16
|
+
"planning",
|
|
17
|
+
"implementation",
|
|
18
|
+
"testing",
|
|
19
|
+
"documentation",
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
function buildMachineStates() {
|
|
23
|
+
return {
|
|
24
|
+
idle: state(
|
|
25
|
+
transition("start_full", "requirements"),
|
|
26
|
+
transition("start_quick", "implementation") as never // quick mode bypass (Story 3.3)
|
|
27
|
+
),
|
|
28
|
+
requirements: state(transition("approve", "architecture")),
|
|
29
|
+
architecture: state(transition("approve", "planning")),
|
|
30
|
+
planning: state(transition("approve", "implementation")),
|
|
31
|
+
implementation: state(transition("approve", "testing")),
|
|
32
|
+
testing: state(transition("approve", "documentation")),
|
|
33
|
+
documentation: state(transition("complete", "idle")),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Creates a Robot3 FSM starting at the given phase — fast-forward, no event replay. */
|
|
38
|
+
export function createFsmAtPhase(phase: Phase) {
|
|
39
|
+
return createMachine(phase, buildMachineStates());
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Maps each tool to its valid phase (or 'any').
|
|
44
|
+
* Tools not listed here are allowed in any phase — do not block unregistered tools.
|
|
45
|
+
*/
|
|
46
|
+
const TOOL_PHASE_MAP: Record<string, Phase | "any"> = {
|
|
47
|
+
set_active_project: "any",
|
|
48
|
+
start_feature: "idle",
|
|
49
|
+
complete_component: "implementation",
|
|
50
|
+
scaffold_doctype: "implementation",
|
|
51
|
+
run_tests: "testing",
|
|
52
|
+
get_project_status: "any",
|
|
53
|
+
frappe_query: "any",
|
|
54
|
+
bench_execute: "any", // allowed in all phases — includes testing (bench run-tests) and implementation (bench migrate)
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** Returns true if toolName is allowed to run in the given phase. Unknown tools are always allowed. */
|
|
58
|
+
export function isToolAllowedInPhase(toolName: string, phase: Phase): boolean {
|
|
59
|
+
const validPhase = TOOL_PHASE_MAP[toolName];
|
|
60
|
+
if (validPhase === undefined) return true; // unknown tool — do not block
|
|
61
|
+
if (validPhase === "any") return true;
|
|
62
|
+
return validPhase === phase;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Returns the phase where toolName is valid, or 'any' for unrestricted/unknown tools. */
|
|
66
|
+
export function getValidPhase(toolName: string): Phase | "any" {
|
|
67
|
+
return TOOL_PHASE_MAP[toolName] ?? "any";
|
|
68
|
+
}
|
package/state/journal.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
mkdirSync,
|
|
5
|
+
appendFileSync,
|
|
6
|
+
readFileSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
copyFileSync,
|
|
9
|
+
existsSync,
|
|
10
|
+
readdirSync,
|
|
11
|
+
} from "node:fs";
|
|
12
|
+
import { db, getCurrentPhase } from "./db.js";
|
|
13
|
+
|
|
14
|
+
/** Typed journal entry appended to the JSONL session log. */
|
|
15
|
+
export interface JournalEntry {
|
|
16
|
+
ts: string;
|
|
17
|
+
sessionId: string;
|
|
18
|
+
type: "tool_call" | "state_transition" | "quality_gate" | "checkpoint";
|
|
19
|
+
payload: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Module-level sessions directory — overridable in tests to avoid writing to ~/.frappe-builder/.
|
|
24
|
+
* Set this before calling appendEntry or compactIfNeeded in test code.
|
|
25
|
+
*/
|
|
26
|
+
let sessionsDir: string | null = null;
|
|
27
|
+
|
|
28
|
+
/** Returns the resolved sessions directory path. */
|
|
29
|
+
function getSessionsDir(): string {
|
|
30
|
+
return sessionsDir ?? join(homedir(), ".frappe-builder", "sessions");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Returns the JSONL journal path for a given session. */
|
|
34
|
+
function getJournalPath(sessionId: string): string {
|
|
35
|
+
return join(getSessionsDir(), `${sessionId}.jsonl`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Returns the archive path for a given session. */
|
|
39
|
+
function getArchivePath(sessionId: string): string {
|
|
40
|
+
return join(getSessionsDir(), `${sessionId}.jsonl.archive`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Overrides the sessions directory — intended for test use only.
|
|
45
|
+
* Pass null to reset to the default ~/.frappe-builder/sessions path.
|
|
46
|
+
*/
|
|
47
|
+
export function setSessionsDir(dir: string | null): void {
|
|
48
|
+
sessionsDir = dir;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Appends a JournalEntry to the session's JSONL log file.
|
|
53
|
+
* Synchronous write — required by NFR3 (writes complete before tool result returned).
|
|
54
|
+
*/
|
|
55
|
+
export function appendEntry(entry: JournalEntry): void {
|
|
56
|
+
const dir = getSessionsDir();
|
|
57
|
+
mkdirSync(dir, { recursive: true });
|
|
58
|
+
const line = JSON.stringify(entry) + "\n";
|
|
59
|
+
appendFileSync(getJournalPath(entry.sessionId), line, "utf-8");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Compacts the session journal if entries exceed 500 or the oldest is > 30 days old.
|
|
64
|
+
* Archives raw entries to .jsonl.archive, then overwrites .jsonl with a single checkpoint entry.
|
|
65
|
+
*/
|
|
66
|
+
export function compactIfNeeded(sessionId: string): void {
|
|
67
|
+
const journalPath = getJournalPath(sessionId);
|
|
68
|
+
const raw = readFileSync(journalPath, "utf-8");
|
|
69
|
+
const entries: JournalEntry[] = raw
|
|
70
|
+
.split("\n")
|
|
71
|
+
.filter(Boolean)
|
|
72
|
+
.map((line) => JSON.parse(line) as JournalEntry);
|
|
73
|
+
|
|
74
|
+
const now = Date.now();
|
|
75
|
+
const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;
|
|
76
|
+
const oldest = Math.min(...entries.map((e) => new Date(e.ts).getTime()));
|
|
77
|
+
const needsCompaction =
|
|
78
|
+
entries.length > 500 || now - oldest > thirtyDaysMs;
|
|
79
|
+
|
|
80
|
+
if (!needsCompaction) return;
|
|
81
|
+
|
|
82
|
+
copyFileSync(journalPath, getArchivePath(sessionId));
|
|
83
|
+
|
|
84
|
+
const checkpoint: JournalEntry = {
|
|
85
|
+
ts: new Date().toISOString(),
|
|
86
|
+
sessionId,
|
|
87
|
+
type: "checkpoint",
|
|
88
|
+
payload: {
|
|
89
|
+
state_snapshot: getCurrentPhase(),
|
|
90
|
+
features: db
|
|
91
|
+
.prepare("SELECT feature_id, name, current_phase FROM features")
|
|
92
|
+
.all(),
|
|
93
|
+
component_statuses: db
|
|
94
|
+
.prepare("SELECT component_id, feature_id, status FROM components")
|
|
95
|
+
.all(),
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
writeFileSync(journalPath, JSON.stringify(checkpoint) + "\n", "utf-8");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface AuditLogQuery {
|
|
103
|
+
sessionId?: string;
|
|
104
|
+
featureId?: string;
|
|
105
|
+
limit?: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Queries JSONL audit log files from the sessions directory.
|
|
110
|
+
* Includes both active (.jsonl) and archived (.jsonl.archive) files.
|
|
111
|
+
* Never throws — returns [] on any file error.
|
|
112
|
+
*/
|
|
113
|
+
export function getAuditLog(query: AuditLogQuery = {}): JournalEntry[] {
|
|
114
|
+
const { sessionId, featureId, limit } = query;
|
|
115
|
+
const dir = getSessionsDir();
|
|
116
|
+
|
|
117
|
+
const filePaths: string[] = [];
|
|
118
|
+
|
|
119
|
+
if (sessionId) {
|
|
120
|
+
const main = getJournalPath(sessionId);
|
|
121
|
+
const archive = getArchivePath(sessionId);
|
|
122
|
+
if (existsSync(main)) filePaths.push(main);
|
|
123
|
+
if (existsSync(archive)) filePaths.push(archive);
|
|
124
|
+
} else {
|
|
125
|
+
try {
|
|
126
|
+
const files = readdirSync(dir);
|
|
127
|
+
for (const f of files) {
|
|
128
|
+
if (f.endsWith(".jsonl") && !f.endsWith(".jsonl.archive")) {
|
|
129
|
+
filePaths.push(join(dir, f));
|
|
130
|
+
}
|
|
131
|
+
if (f.endsWith(".jsonl.archive")) {
|
|
132
|
+
filePaths.push(join(dir, f));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const entries: JournalEntry[] = [];
|
|
141
|
+
for (const filePath of filePaths) {
|
|
142
|
+
try {
|
|
143
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
144
|
+
for (const line of raw.split("\n")) {
|
|
145
|
+
if (!line.trim()) continue;
|
|
146
|
+
try {
|
|
147
|
+
entries.push(JSON.parse(line) as JournalEntry);
|
|
148
|
+
} catch {
|
|
149
|
+
// Skip malformed lines
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} catch {
|
|
153
|
+
// Skip unreadable files
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
entries.sort((a, b) => a.ts.localeCompare(b.ts));
|
|
158
|
+
|
|
159
|
+
const filtered = featureId
|
|
160
|
+
? entries.filter((e) => (e.payload as Record<string, unknown>).feature === featureId)
|
|
161
|
+
: entries;
|
|
162
|
+
|
|
163
|
+
return limit !== undefined ? filtered.slice(0, limit) : filtered;
|
|
164
|
+
}
|
package/state/schema.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Database } from "better-sqlite3";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Runs all CREATE TABLE IF NOT EXISTS statements against the provided database.
|
|
5
|
+
* Safe to call multiple times — idempotent by design.
|
|
6
|
+
*/
|
|
7
|
+
export function initSchema(db: Database): void {
|
|
8
|
+
db.exec(`
|
|
9
|
+
CREATE TABLE IF NOT EXISTS features (
|
|
10
|
+
feature_id TEXT PRIMARY KEY,
|
|
11
|
+
name TEXT NOT NULL,
|
|
12
|
+
mode TEXT NOT NULL DEFAULT 'full' CHECK (mode IN ('full', 'quick')),
|
|
13
|
+
current_phase TEXT NOT NULL DEFAULT 'idle',
|
|
14
|
+
created_at TEXT NOT NULL,
|
|
15
|
+
updated_at TEXT,
|
|
16
|
+
progress_done INTEGER DEFAULT 0,
|
|
17
|
+
progress_total INTEGER DEFAULT 0
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS components (
|
|
21
|
+
component_id TEXT NOT NULL,
|
|
22
|
+
feature_id TEXT NOT NULL,
|
|
23
|
+
status TEXT NOT NULL DEFAULT 'in-progress',
|
|
24
|
+
completed_at TEXT,
|
|
25
|
+
PRIMARY KEY (feature_id, component_id),
|
|
26
|
+
FOREIGN KEY (feature_id) REFERENCES features(feature_id)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
30
|
+
session_id TEXT PRIMARY KEY,
|
|
31
|
+
project_id TEXT NOT NULL,
|
|
32
|
+
current_phase TEXT NOT NULL DEFAULT 'idle',
|
|
33
|
+
site_path TEXT,
|
|
34
|
+
feature_id TEXT,
|
|
35
|
+
last_tool TEXT,
|
|
36
|
+
started_at TEXT NOT NULL,
|
|
37
|
+
ended_at TEXT,
|
|
38
|
+
is_active INTEGER NOT NULL DEFAULT 1
|
|
39
|
+
);
|
|
40
|
+
`);
|
|
41
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { loadConfig } from "../config/loader.js";
|
|
2
|
+
|
|
3
|
+
export interface SpawnAgentArgs {
|
|
4
|
+
skill: string;
|
|
5
|
+
trigger: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
approved?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SpawnAgentResult {
|
|
11
|
+
status: "requires_approval" | "rejected" | "disabled" | "spawned";
|
|
12
|
+
skill: string;
|
|
13
|
+
trigger: string;
|
|
14
|
+
prompt?: string;
|
|
15
|
+
error?: string;
|
|
16
|
+
result?: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Stub: no sub-agent spawn API found in @mariozechner/pi-agent-core at this version.
|
|
21
|
+
* Returns spawned status with null result — replace body with actual API when available.
|
|
22
|
+
*/
|
|
23
|
+
async function doSpawn(skill: string, trigger: string): Promise<SpawnAgentResult> {
|
|
24
|
+
return { status: "spawned", skill, trigger, result: null };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Handles the two-call permission flow for sub-agent spawning.
|
|
29
|
+
* Call 1 (no approved): returns requires_approval prompt if requirePermission === true.
|
|
30
|
+
* Call 2 (approved: true/false): spawns or rejects.
|
|
31
|
+
* Autonomous mode (requirePermission: false): spawns on first call.
|
|
32
|
+
* Does NOT write JSONL — that belongs in afterToolCall (frappe-state.ts).
|
|
33
|
+
*/
|
|
34
|
+
export async function spawnAgent(args: SpawnAgentArgs): Promise<SpawnAgentResult> {
|
|
35
|
+
const config = loadConfig();
|
|
36
|
+
|
|
37
|
+
if (!config.allowSubAgents) {
|
|
38
|
+
return {
|
|
39
|
+
status: "disabled",
|
|
40
|
+
skill: args.skill,
|
|
41
|
+
trigger: args.trigger,
|
|
42
|
+
error: "Sub-agent spawning is disabled in config",
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (config.requirePermission && args.approved === undefined) {
|
|
47
|
+
return {
|
|
48
|
+
status: "requires_approval",
|
|
49
|
+
skill: args.skill,
|
|
50
|
+
trigger: args.trigger,
|
|
51
|
+
prompt: `Agent wants to spawn ${args.skill} for ${args.reason}. Allow? [Y/n]`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (args.approved === false) {
|
|
56
|
+
return { status: "rejected", skill: args.skill, trigger: args.trigger };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return doSpawn(args.skill, args.trigger);
|
|
60
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { loadAllowedCommands } from "../config/allowed-commands.js";
|
|
3
|
+
import { routeThroughContextMode } from "./context-sandbox.js";
|
|
4
|
+
|
|
5
|
+
export interface BenchExecuteArgs {
|
|
6
|
+
command: string;
|
|
7
|
+
args?: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type BenchExecuteResult =
|
|
11
|
+
| { output: string; command: string; exit_code: number }
|
|
12
|
+
| { blocked: true; command: string; reason: string }
|
|
13
|
+
| { error: string; command: string; stderr: string };
|
|
14
|
+
|
|
15
|
+
function isAllowed(command: string, whitelist: string[]): boolean {
|
|
16
|
+
const normalised = command.trim().toLowerCase();
|
|
17
|
+
return whitelist.some((w) => w.trim().toLowerCase() === normalised);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Executes a whitelisted bench command via execa subprocess.
|
|
22
|
+
* Async (non-blocking) — bench commands can run for 30+ seconds (NFR16).
|
|
23
|
+
* Output routed through context-mode sandbox — raw stdout never returned directly.
|
|
24
|
+
* Returns structured error on failure, never throws.
|
|
25
|
+
*/
|
|
26
|
+
export async function benchExecute({
|
|
27
|
+
command,
|
|
28
|
+
args = [],
|
|
29
|
+
}: BenchExecuteArgs): Promise<BenchExecuteResult> {
|
|
30
|
+
const whitelist = loadAllowedCommands();
|
|
31
|
+
|
|
32
|
+
if (!isAllowed(command, whitelist)) {
|
|
33
|
+
return { blocked: true, command, reason: "not in whitelist" };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Split "bench migrate" → binary="bench", subParts=["migrate"]
|
|
37
|
+
const [binary, ...subParts] = command.trim().split(/\s+/);
|
|
38
|
+
const fullArgs = [...subParts, ...args];
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
// execa with args array — NO shell expansion (security: prevents injection)
|
|
42
|
+
const { stdout, exitCode } = await execa(binary, fullArgs);
|
|
43
|
+
const sandboxed = await routeThroughContextMode(stdout);
|
|
44
|
+
return { output: sandboxed, command, exit_code: exitCode ?? 0 };
|
|
45
|
+
} catch (err: unknown) {
|
|
46
|
+
const e = err as { message?: string; stderr?: string };
|
|
47
|
+
return {
|
|
48
|
+
error: e.message ?? String(err),
|
|
49
|
+
command,
|
|
50
|
+
stderr: e.stderr ?? "",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Stub — full implementation deferred (Story 4.2). */
|
|
56
|
+
export function scaffoldDoctype(_args: unknown): { error: string } {
|
|
57
|
+
return { error: "scaffold_doctype: not yet implemented — Story 4.2 (deferred)" };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Stub — full implementation Epic 6. */
|
|
61
|
+
export function runTests(_args: unknown): { error: string } {
|
|
62
|
+
return { error: "run_tests: not yet implemented — Epic 6" };
|
|
63
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context-mode sandbox routing for Frappe tool output.
|
|
3
|
+
*
|
|
4
|
+
* Context-mode MCP tools are accessible to the LLM session but not callable
|
|
5
|
+
* directly from extension code. Until an HTTP endpoint is discoverable,
|
|
6
|
+
* routeThroughContextMode applies the 8K truncation fallback.
|
|
7
|
+
*
|
|
8
|
+
* NFR17: truncation is NEVER silent — warning is always prepended.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const CHAR_LIMIT = 8192 * 4; // ~8K tokens at 4 chars/token
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Routes raw tool output through the context-mode sandbox.
|
|
15
|
+
* Falls back to 8K truncation with a visible warning if sandbox unavailable.
|
|
16
|
+
* Never throws.
|
|
17
|
+
*/
|
|
18
|
+
export async function routeThroughContextMode(raw: string): Promise<string> {
|
|
19
|
+
// TODO: wire to context-mode MCP HTTP endpoint when discoverable from extension code
|
|
20
|
+
return applyTruncationFallback(raw);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Truncates raw output at ~8K tokens and prepends a visible warning.
|
|
25
|
+
* Returns raw unchanged if under the limit.
|
|
26
|
+
* Exported for direct use and testing.
|
|
27
|
+
*/
|
|
28
|
+
export function applyTruncationFallback(raw: string): string {
|
|
29
|
+
if (raw.length <= CHAR_LIMIT) return raw;
|
|
30
|
+
return `[CONTEXT-MODE UNAVAILABLE: output truncated at 8K tokens]\n\n${raw.slice(0, CHAR_LIMIT)}`;
|
|
31
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug tool handlers — invoke_debugger and end_debug.
|
|
3
|
+
* These tools do NOT write state; all state/JSONL work happens in afterToolCall (frappe-state.ts).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export function invokeDebugger(): { tool: string; timestamp: string } {
|
|
7
|
+
return { tool: "invoke_debugger", timestamp: new Date().toISOString() };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function endDebug(): { tool: string; timestamp: string } {
|
|
11
|
+
return { tool: "end_debug", timestamp: new Date().toISOString() };
|
|
12
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { db } from "../state/db.js";
|
|
3
|
+
import { appendEntry } from "../state/journal.js";
|
|
4
|
+
import { loadConfig } from "../config/loader.js";
|
|
5
|
+
import { coverageCheck } from "../gates/coverage-check.js";
|
|
6
|
+
|
|
7
|
+
interface StartFeatureArgs {
|
|
8
|
+
name: string;
|
|
9
|
+
mode?: "full" | "quick";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function toFeatureId(name: string): string {
|
|
13
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new feature row in state.db and writes a state_transition JSONL entry.
|
|
18
|
+
* Returns the feature data directly — no wrapper object.
|
|
19
|
+
* mode defaults to "full" — feature row always stores an explicit mode value.
|
|
20
|
+
*/
|
|
21
|
+
export function startFeature({ name, mode = "full" }: StartFeatureArgs) {
|
|
22
|
+
const featureId = toFeatureId(name);
|
|
23
|
+
const createdAt = new Date().toISOString();
|
|
24
|
+
|
|
25
|
+
const session = db
|
|
26
|
+
.prepare("SELECT session_id FROM sessions WHERE is_active = 1 LIMIT 1")
|
|
27
|
+
.get() as { session_id: string } | undefined;
|
|
28
|
+
|
|
29
|
+
db.prepare(
|
|
30
|
+
"INSERT INTO features (feature_id, name, created_at, mode, current_phase) VALUES (?, ?, ?, ?, 'idle')"
|
|
31
|
+
).run(featureId, name, createdAt, mode);
|
|
32
|
+
|
|
33
|
+
appendEntry({
|
|
34
|
+
ts: createdAt,
|
|
35
|
+
sessionId: session?.session_id ?? "unknown",
|
|
36
|
+
type: "state_transition",
|
|
37
|
+
payload: { from: "idle", to: "feature_started", feature: name },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return { feature_id: featureId, name, mode, current_phase: "idle", created_at: createdAt };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface CompleteComponentArgs {
|
|
44
|
+
featureId: string;
|
|
45
|
+
componentId: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Marks a component as complete in state.db, writes a JSONL state_transition entry,
|
|
50
|
+
* and optionally creates a git checkpoint commit.
|
|
51
|
+
* Git checkpoint is best-effort — DB write is never rolled back on git failure.
|
|
52
|
+
*/
|
|
53
|
+
export async function completeComponent({ featureId, componentId }: CompleteComponentArgs) {
|
|
54
|
+
const completedAt = new Date().toISOString();
|
|
55
|
+
const config = loadConfig();
|
|
56
|
+
|
|
57
|
+
const session = db
|
|
58
|
+
.prepare("SELECT session_id, current_phase FROM sessions WHERE is_active = 1 LIMIT 1")
|
|
59
|
+
.get() as { session_id: string; current_phase: string } | undefined;
|
|
60
|
+
const sessionId = session?.session_id ?? "unknown";
|
|
61
|
+
const currentPhase = session?.current_phase ?? "idle";
|
|
62
|
+
|
|
63
|
+
// Determine if this is the final in-progress component for this feature
|
|
64
|
+
const pending = db
|
|
65
|
+
.prepare(
|
|
66
|
+
"SELECT COUNT(*) as cnt FROM components WHERE feature_id = ? AND status = 'in-progress' AND component_id != ?"
|
|
67
|
+
)
|
|
68
|
+
.get(featureId, componentId) as { cnt: number };
|
|
69
|
+
const isFinalComponent = pending.cnt === 0;
|
|
70
|
+
|
|
71
|
+
// Coverage gate: runs only when completing the final component in testing phase
|
|
72
|
+
if (isFinalComponent && currentPhase === "testing") {
|
|
73
|
+
const coverageResult = await coverageCheck({ file: `feature:${featureId}`, phase: currentPhase, sessionId });
|
|
74
|
+
|
|
75
|
+
// Log quality_gate JSONL regardless of pass/fail
|
|
76
|
+
appendEntry({
|
|
77
|
+
ts: new Date().toISOString(),
|
|
78
|
+
sessionId,
|
|
79
|
+
type: "quality_gate",
|
|
80
|
+
payload: {
|
|
81
|
+
gate: "coverage_check",
|
|
82
|
+
result: coverageResult.passed ? "pass" : "blocked",
|
|
83
|
+
coverage: coverageResult.coverage,
|
|
84
|
+
file: `feature:${featureId}`,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (!coverageResult.passed) {
|
|
89
|
+
return {
|
|
90
|
+
blocked: true,
|
|
91
|
+
tool: "complete_component",
|
|
92
|
+
gate: "coverage_check",
|
|
93
|
+
coverage: coverageResult.coverage,
|
|
94
|
+
required: coverageResult.required,
|
|
95
|
+
message: `Coverage gate blocked: ${coverageResult.coverage}% coverage < 70% required. Fix tests and retry.`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Gate passed (or not applicable) — update component status
|
|
101
|
+
db.prepare(`
|
|
102
|
+
INSERT INTO components (feature_id, component_id, status, completed_at)
|
|
103
|
+
VALUES (?, ?, 'complete', ?)
|
|
104
|
+
ON CONFLICT(feature_id, component_id)
|
|
105
|
+
DO UPDATE SET status = 'complete', completed_at = excluded.completed_at
|
|
106
|
+
`).run(featureId, componentId, completedAt);
|
|
107
|
+
|
|
108
|
+
appendEntry({
|
|
109
|
+
ts: completedAt,
|
|
110
|
+
sessionId,
|
|
111
|
+
type: "state_transition",
|
|
112
|
+
payload: { feature: featureId, component: componentId, status: "complete" },
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (config.autoGitCheckpoint !== false) {
|
|
116
|
+
const message = `feat(frappe-builder): ${featureId}/${componentId} completed [phase: ${currentPhase}]`;
|
|
117
|
+
try {
|
|
118
|
+
await execa("git", ["commit", "-am", message]);
|
|
119
|
+
return { feature_id: featureId, component_id: componentId, status: "complete", completed_at: completedAt, git_checkpoint: true };
|
|
120
|
+
} catch (err) {
|
|
121
|
+
return { feature_id: featureId, component_id: componentId, status: "complete", completed_at: completedAt, git_checkpoint: false, git_error: (err as Error).message };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { feature_id: featureId, component_id: componentId, status: "complete", completed_at: completedAt, git_checkpoint: false };
|
|
126
|
+
}
|