@williambeto/ai-workflow 1.19.1 → 2.2.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/CHANGELOG.md +56 -838
- package/PUBLISH_MANIFEST.json +34 -0
- package/README.md +78 -148
- package/{packages/ai-workflow/bin → bin}/ai-workflow.js +0 -0
- package/dist-assets/AGENTS.md +27 -0
- package/dist-assets/agents/astra.md +63 -0
- package/dist-assets/agents/atlas.md +169 -0
- package/dist-assets/agents/nexus.md +42 -0
- package/dist-assets/agents/orion.md +44 -0
- package/dist-assets/agents/phoenix.md +42 -0
- package/dist-assets/agents/sage.md +54 -0
- package/dist-assets/commands/README.md +14 -0
- package/dist-assets/commands/atlas.md +12 -0
- package/dist-assets/commands/audit.md +10 -0
- package/dist-assets/commands/deploy.md +12 -0
- package/dist-assets/commands/discover.md +10 -0
- package/dist-assets/commands/implement.md +28 -0
- package/dist-assets/commands/optimize-tokens.md +10 -0
- package/dist-assets/commands/plan.md +10 -0
- package/dist-assets/commands/release.md +12 -0
- package/dist-assets/commands/run.md +26 -0
- package/dist-assets/commands/spec-create.md +10 -0
- package/dist-assets/commands/spec-implement.md +10 -0
- package/dist-assets/commands/spec-review.md +10 -0
- package/dist-assets/commands/update-memory.md +10 -0
- package/dist-assets/commands/validate.md +12 -0
- package/dist-assets/docs/INDEX.md +21 -0
- package/dist-assets/docs/QUICKSTART.md +23 -0
- package/dist-assets/docs/adr/ADR-0000.md +19 -0
- package/dist-assets/docs/adr/ADR-0001.md +45 -0
- package/dist-assets/docs/adr/ADR-0002.md +62 -0
- package/dist-assets/docs/adr/ADR-0003.md +60 -0
- package/dist-assets/docs/adr/ADR-0004.md +71 -0
- package/dist-assets/docs/adr/ADR-0005.md +22 -0
- package/dist-assets/docs/adr/ADR-0006.md +82 -0
- package/dist-assets/docs/adr/ADR-0007.md +78 -0
- package/dist-assets/docs/api-engine-reference.md +7 -0
- package/{docs → dist-assets/docs}/architecture-policy.md +1 -1
- package/dist-assets/docs/cli-reference.md +27 -0
- package/dist-assets/docs/compatibility/provider-usage.md +38 -0
- package/dist-assets/docs/compatibility/runtime-matrix.md +30 -0
- package/dist-assets/docs/consumer-onboarding.md +17 -0
- package/dist-assets/docs/contributing-guide.md +11 -0
- package/{docs → dist-assets/docs}/design-patterns-policy.md +2 -2
- package/dist-assets/docs/full-documentation.md +113 -0
- package/{docs → dist-assets/docs}/npm-consumer-quickstart.md +18 -46
- package/dist-assets/docs/opencode-readme.md +8 -0
- package/dist-assets/docs/policies/01-BRANCH_GATE.md +63 -0
- package/dist-assets/docs/policies/02-SDD_METHODOLOGY.md +95 -0
- package/dist-assets/docs/policies/03-QUALITY_GATE.md +22 -0
- package/dist-assets/docs/policies/05-AGENT_CONTRACT.md +7 -0
- package/dist-assets/docs/policies/06-FINAL_EVIDENCE_CONTRACT.md +31 -0
- package/dist-assets/docs/policies/07-RELEASE_GATE.md +47 -0
- package/dist-assets/docs/policies/08-PRODUCT_TRUTHFULNESS_AND_PROJECT_DOCS.md +18 -0
- package/dist-assets/docs/policies/09-SPEC_VISIBILITY_AND_PUBLICATION.md +28 -0
- package/dist-assets/docs/policies/10-BEHAVIORAL_CONTRACT_HARDENING.md +9 -0
- package/dist-assets/docs/policies/11-EXECUTABLE_DELEGATION_AND_TRUTHFULNESS.md +7 -0
- package/dist-assets/docs/policies/ORCHESTRATION_PROTOCOL.md +15 -0
- package/dist-assets/docs/policies/PROCEDURE_DELIVERY_ARTIFACTS.md +21 -0
- package/dist-assets/docs/policies/PROCEDURE_DOCUMENTATION_CHECKLIST.md +24 -0
- package/dist-assets/docs/policies/PROCEDURE_UI_CHECKLIST.md +54 -0
- package/dist-assets/docs/profiles/README.md +19 -0
- package/dist-assets/docs/profiles/backend-api.md +5 -0
- package/dist-assets/docs/profiles/documentation.md +3 -0
- package/dist-assets/docs/profiles/frontend-product.md +19 -0
- package/dist-assets/docs/profiles/frontend-utility.md +19 -0
- package/dist-assets/docs/profiles/refactor.md +3 -0
- package/dist-assets/docs/profiles/security-review.md +3 -0
- package/dist-assets/docs/references/frontend-quality/landing-page-quality-checklist.md +11 -0
- package/dist-assets/docs/references/frontend-quality/product-copy-truthfulness.md +7 -0
- package/dist-assets/docs/references/frontend-quality/quality-failure-examples.md +20 -0
- package/dist-assets/docs/references/frontend-quality/visual-composition-patterns.md +10 -0
- package/dist-assets/docs/specs/runtime-operational-contract.md +39 -0
- package/dist-assets/docs/troubleshooting-guide.md +21 -0
- package/dist-assets/docs/visual-validation-guide.md +76 -0
- package/dist-assets/examples/README.md +10 -0
- package/dist-assets/examples/autopilot-cycle/00-CONTEXT.md +3 -0
- package/dist-assets/examples/autopilot-cycle/01-requirement.md +16 -0
- package/dist-assets/examples/autopilot-cycle/02-gate-a-check.md +23 -0
- package/dist-assets/examples/autopilot-cycle/03-orion-planning.md +20 -0
- package/dist-assets/examples/autopilot-cycle/04-astra-implementation.md +17 -0
- package/dist-assets/examples/autopilot-cycle/05-sage-validation.md +15 -0
- package/dist-assets/examples/autopilot-cycle/06-phoenix-healing.md +12 -0
- package/dist-assets/examples/autopilot-cycle/07-orchestration-report.md +18 -0
- package/dist-assets/examples/backend-api/00-CONTEXT.md +12 -0
- package/dist-assets/examples/backend-api/01-requirement.md +19 -0
- package/dist-assets/examples/backend-api/02-functional-spec.md +20 -0
- package/dist-assets/examples/backend-api/03-technical-plan.md +15 -0
- package/dist-assets/examples/backend-api/04-pr-breakdown.md +10 -0
- package/dist-assets/examples/backend-api/05-execution-handoff.md +13 -0
- package/dist-assets/examples/backend-api/06-validation-report.md +11 -0
- package/dist-assets/examples/backend-api/07-orchestration-report.md +7 -0
- package/dist-assets/examples/blocked-scenarios/00-CONTEXT.md +9 -0
- package/dist-assets/examples/blocked-scenarios/01-branch-gate-block.md +12 -0
- package/dist-assets/examples/blocked-scenarios/02-quality-gate-block.md +13 -0
- package/dist-assets/examples/blocked-scenarios/03-scope-creep-block.md +13 -0
- package/dist-assets/examples/blocked-scenarios/04-unblock-resolution.md +9 -0
- package/dist-assets/examples/blocked-scenarios/05-orchestration-decision-log.md +11 -0
- package/dist-assets/examples/bugfix-critical/00-CONTEXT.md +12 -0
- package/dist-assets/examples/bugfix-critical/01-bug-report.md +11 -0
- package/dist-assets/examples/bugfix-critical/02-diagnosis-hypothesis.md +11 -0
- package/dist-assets/examples/bugfix-critical/03-technical-plan.md +12 -0
- package/dist-assets/examples/bugfix-critical/04-implementation-handoff.md +8 -0
- package/dist-assets/examples/bugfix-critical/05-validation-report.md +10 -0
- package/dist-assets/examples/bugfix-critical/06-orchestration-report.md +7 -0
- package/dist-assets/examples/cli-package/00-CONTEXT.md +9 -0
- package/dist-assets/examples/cli-package/01-requirement.md +14 -0
- package/dist-assets/examples/cli-package/02-technical-spec.md +16 -0
- package/dist-assets/examples/cli-package/03-technical-plan.md +12 -0
- package/dist-assets/examples/cli-package/04-pr-breakdown.md +9 -0
- package/dist-assets/examples/cli-package/05-release-report.md +15 -0
- package/dist-assets/examples/docs-only-repo/01-requirement.md +31 -0
- package/dist-assets/examples/docs-only-repo/02-functional-spec.md +25 -0
- package/dist-assets/examples/docs-only-repo/03-technical-plan.md +21 -0
- package/dist-assets/examples/docs-only-repo/04-pr-breakdown.md +13 -0
- package/dist-assets/examples/docs-only-repo/05-execution-handoff.md +17 -0
- package/dist-assets/examples/docs-only-repo/06-validation-report.md +16 -0
- package/dist-assets/examples/docs-only-repo/README.md +26 -0
- package/dist-assets/examples/full-stack-checkout/00-CONTEXT.md +9 -0
- package/dist-assets/examples/full-stack-checkout/01-requirement.md +12 -0
- package/dist-assets/examples/full-stack-checkout/02-functional-spec.md +15 -0
- package/dist-assets/examples/full-stack-checkout/03-technical-plan.md +15 -0
- package/dist-assets/examples/full-stack-checkout/04-pr-breakdown.md +8 -0
- package/dist-assets/examples/full-stack-checkout/05-execution-handoff.md +14 -0
- package/dist-assets/examples/full-stack-checkout/06-validation-report.md +12 -0
- package/dist-assets/examples/healing-cycle/00-CONTEXT.md +15 -0
- package/dist-assets/examples/healing-cycle/01-broken-implementation.md +10 -0
- package/dist-assets/examples/healing-cycle/02-sage-fails.md +14 -0
- package/dist-assets/examples/healing-cycle/03-phoenix-diagnosis.md +17 -0
- package/dist-assets/examples/healing-cycle/04-phoenix-fix.md +18 -0
- package/dist-assets/examples/healing-cycle/05-sage-revalidation.md +12 -0
- package/dist-assets/examples/healing-cycle/06-orchestration-log.md +14 -0
- package/dist-assets/examples/infra-deploy/00-CONTEXT.md +9 -0
- package/dist-assets/examples/infra-deploy/01-operational-goal.md +12 -0
- package/dist-assets/examples/infra-deploy/02-architecture-specs.md +15 -0
- package/dist-assets/examples/infra-deploy/03-implementation-plan.md +14 -0
- package/dist-assets/examples/infra-deploy/04-step-breakdown.md +9 -0
- package/dist-assets/examples/infra-deploy/05-execution-handoff.md +13 -0
- package/dist-assets/examples/infra-deploy/06-operational-report.md +11 -0
- package/dist-assets/examples/multi-pr-release/00-CONTEXT.md +9 -0
- package/dist-assets/examples/multi-pr-release/01-requirement.md +13 -0
- package/dist-assets/examples/multi-pr-release/02-strategic-plan.md +13 -0
- package/dist-assets/examples/multi-pr-release/03-pr-breakdown.md +14 -0
- package/dist-assets/examples/multi-pr-release/04-release-plan.md +12 -0
- package/dist-assets/examples/multi-pr-release/05-orchestration-report.md +7 -0
- package/dist-assets/examples/nuxt-dashboard/01-requirement.md +81 -0
- package/dist-assets/examples/nuxt-dashboard/02-functional-spec.md +88 -0
- package/dist-assets/examples/nuxt-dashboard/03-technical-plan.md +76 -0
- package/dist-assets/examples/nuxt-dashboard/04-pr-breakdown.md +219 -0
- package/dist-assets/examples/nuxt-dashboard/05-execution-handoff.md +88 -0
- package/dist-assets/examples/nuxt-dashboard/06-validation-report.md +56 -0
- package/dist-assets/examples/nuxt-dashboard/07-orchestration-report.md +79 -0
- package/dist-assets/examples/nuxt-dashboard/README.md +52 -0
- package/dist-assets/examples/react-dashboard/01-requirement.md +84 -0
- package/dist-assets/examples/react-dashboard/02-functional-spec.md +88 -0
- package/dist-assets/examples/react-dashboard/03-technical-plan.md +76 -0
- package/dist-assets/examples/react-dashboard/04-pr-breakdown.md +218 -0
- package/dist-assets/examples/react-dashboard/05-execution-handoff.md +13 -0
- package/dist-assets/examples/react-dashboard/06-validation-report.md +12 -0
- package/dist-assets/examples/react-dashboard/07-orchestration-report.md +7 -0
- package/dist-assets/examples/react-dashboard/README.md +70 -0
- package/dist-assets/examples/refactoring-service/00-CONTEXT.md +9 -0
- package/dist-assets/examples/refactoring-service/01-debt-report.md +12 -0
- package/dist-assets/examples/refactoring-service/02-behavior-spec.md +11 -0
- package/dist-assets/examples/refactoring-service/03-technical-plan.md +13 -0
- package/dist-assets/examples/refactoring-service/04-pr-breakdown.md +9 -0
- package/dist-assets/examples/refactoring-service/05-execution-handoff.md +14 -0
- package/dist-assets/examples/refactoring-service/06-stability-report.md +12 -0
- package/dist-assets/examples/sdd-cycle/00-CONTEXT.md +12 -0
- package/dist-assets/examples/sdd-cycle/01-raw-request.md +13 -0
- package/dist-assets/examples/sdd-cycle/02-spec-creation.md +18 -0
- package/dist-assets/examples/sdd-cycle/03-spec-review.md +12 -0
- package/dist-assets/examples/sdd-cycle/04-technical-plan.md +16 -0
- package/dist-assets/examples/sdd-cycle/05-pr-breakdown.md +9 -0
- package/dist-assets/examples/sdd-cycle/06-spec-implement.md +13 -0
- package/dist-assets/examples/sdd-cycle/07-validation-against-spec.md +13 -0
- package/dist-assets/examples/wordpress-theme/01-requirement.md +29 -0
- package/dist-assets/examples/wordpress-theme/02-functional-spec.md +22 -0
- package/dist-assets/examples/wordpress-theme/03-technical-plan.md +22 -0
- package/dist-assets/examples/wordpress-theme/04-pr-breakdown.md +14 -0
- package/dist-assets/examples/wordpress-theme/05-execution-handoff.md +17 -0
- package/dist-assets/examples/wordpress-theme/06-validation-report.md +16 -0
- package/dist-assets/examples/wordpress-theme/README.md +32 -0
- package/{harness → dist-assets/harness}/handoffs/HANDOFF.template.md +2 -2
- package/{harness → dist-assets/harness}/workflows/agent-evaluation-checklist.md +5 -5
- package/{harness → dist-assets/harness}/workflows/implement-review-validate.md +24 -0
- package/{harness → dist-assets/harness}/workflows/multi-agent-handoff.md +4 -4
- package/{harness → dist-assets/harness}/workflows/planner-executor-workflow.md +5 -5
- package/{harness → dist-assets/harness}/workflows/requirement-to-pr.md +1 -1
- package/dist-assets/runbooks/agent-delegation-workflow.md +50 -0
- package/dist-assets/runbooks/apply-starter-to-real-project.md +45 -0
- package/dist-assets/runbooks/commands-cheatsheet.md +44 -0
- package/dist-assets/runbooks/how-to-use-skills.md +44 -0
- package/dist-assets/runbooks/private-spec-publication-safety.md +35 -0
- package/{runbooks → dist-assets/runbooks}/spec-driven-development.md +3 -6
- package/dist-assets/runbooks/tutorial-walkthroughs.md +23 -0
- package/dist-assets/runbooks/use-linear-for-operational-planning.md +45 -0
- package/dist-assets/runbooks/use-napkin-project-memory.md +33 -0
- package/dist-assets/skills/architecture/SKILL.md +166 -0
- package/dist-assets/skills/backend-development/SKILL.md +166 -0
- package/dist-assets/skills/deployment/SKILL.md +166 -0
- package/dist-assets/skills/design-principles/SKILL.md +166 -0
- package/dist-assets/skills/documentation/SKILL.md +171 -0
- package/dist-assets/skills/frontend-development/SKILL.md +225 -0
- package/dist-assets/skills/full-stack-development/SKILL.md +166 -0
- package/dist-assets/skills/optimize-tokens/SKILL.md +166 -0
- package/dist-assets/skills/pr-workflow/SKILL.md +166 -0
- package/dist-assets/skills/product-discovery/SKILL.md +166 -0
- package/dist-assets/skills/product-planning/SKILL.md +166 -0
- package/dist-assets/skills/project-memory/SKILL.md +166 -0
- package/dist-assets/skills/prompt-engineer/SKILL.md +166 -0
- package/dist-assets/skills/qa-workflow/SKILL.md +186 -0
- package/dist-assets/skills/refactoring/SKILL.md +166 -0
- package/dist-assets/skills/release-workflow/SKILL.md +166 -0
- package/dist-assets/skills/spec-driven-development/SKILL.md +166 -0
- package/dist-assets/skills/technical-leadership/SKILL.md +166 -0
- package/dist-assets/skills/ui-ux-design/SKILL.md +202 -0
- package/dist-assets/templates/.geminiignore.template +8 -0
- package/dist-assets/templates/CLAUDE.md.template +20 -0
- package/dist-assets/templates/CODEX.md.template +20 -0
- package/dist-assets/templates/GEMINI.md.template +20 -0
- package/dist-assets/templates/HANDOFF.template.md +45 -0
- package/dist-assets/templates/SPEC.template.md +38 -0
- package/dist-assets/templates/change-proposal.template.md +14 -0
- package/dist-assets/templates/owner-evidence/astra-implementation.json +10 -0
- package/dist-assets/templates/owner-evidence/phoenix-remediation.json +8 -0
- package/dist-assets/templates/owner-evidence/sage-revalidation.json +8 -0
- package/dist-assets/templates/owner-evidence/sage-validation.json +8 -0
- package/dist-assets/templates/specs/deep.md +48 -0
- package/dist-assets/templates/specs/standard.md +38 -0
- package/dist-assets/templates/specs/tiny.md +19 -0
- package/package.json +43 -47
- package/src/adapters/index.js +3 -0
- package/src/adapters/platforms/claude.js +126 -0
- package/src/adapters/platforms/codex.js +100 -0
- package/src/adapters/platforms/gemini.js +232 -0
- package/src/cli.js +114 -0
- package/src/commands/collect-evidence.js +61 -0
- package/src/commands/doctor.js +186 -0
- package/src/commands/execute.js +172 -0
- package/{packages/ai-workflow/src → src}/commands/init.js +119 -20
- package/src/commands/run.js +112 -0
- package/src/core/completion-contract.js +35 -0
- package/src/core/execution-planner.js +59 -0
- package/src/core/gates/branch-gate.js +146 -0
- package/src/core/handoff/handoff-engine.js +104 -0
- package/src/core/healing/cli-remediation-executor.js +151 -0
- package/src/core/healing/healer-engine.js +179 -0
- package/src/core/identity.js +43 -0
- package/{packages/ai-workflow/src → src}/core/install-plan.js +3 -3
- package/src/core/opencode-merge.js +149 -0
- package/{packages/ai-workflow/src → src}/core/package-assets.js +29 -10
- package/src/core/request-classifier.js +58 -0
- package/src/core/runtime/opencode-adapter.js +94 -0
- package/src/core/sdd/validator.js +67 -0
- package/src/core/statuses.js +29 -0
- package/src/core/symlink-layout.js +93 -0
- package/src/core/templates.js +221 -0
- package/src/core/validation/canonical-finalization.js +43 -0
- package/src/core/validation/evidence-collector.js +109 -0
- package/src/core/validation/quality-guard.js +243 -0
- package/src/core/workflow-profiles.js +107 -0
- package/src/core/workflow-state-machine.js +46 -0
- package/.agents/napkin.md +0 -89
- package/.agents/skills/backend-implementer/SKILL.md +0 -490
- package/.agents/skills/build-and-validate/SKILL.md +0 -442
- package/.agents/skills/deploy-engineer/SKILL.md +0 -541
- package/.agents/skills/docs-writer/SKILL.md +0 -430
- package/.agents/skills/frontend-implementer/SKILL.md +0 -488
- package/.agents/skills/interface-design/SKILL.md +0 -428
- package/.agents/skills/interface-design/references/critique.md +0 -67
- package/.agents/skills/interface-design/references/example.md +0 -86
- package/.agents/skills/interface-design/references/principles.md +0 -235
- package/.agents/skills/interface-design/references/validation.md +0 -48
- package/.agents/skills/minimal-context/SKILL.md +0 -177
- package/.agents/skills/napkin/SKILL.md +0 -84
- package/.agents/skills/opencode-agent-design/SKILL.md +0 -77
- package/.agents/skills/playwright-cli/SKILL.md +0 -62
- package/.agents/skills/pr-orchestrator/SKILL.md +0 -366
- package/.agents/skills/product-manager/SKILL.md +0 -519
- package/.agents/skills/seo-audit/SKILL.md +0 -176
- package/.agents/skills/stack-variant-creator/SKILL.md +0 -265
- package/.agents/skills/tech-lead/SKILL.md +0 -453
- package/.agents/skills/tester/SKILL.md +0 -399
- package/.agents/skills/token-economy/SKILL.md +0 -137
- package/.agents/skills/vue-nuxt/SKILL.md +0 -102
- package/.agents/skills/wordpress-engineer/SKILL.md +0 -75
- package/.codex/prompts/README.md +0 -44
- package/.codex/prompts/autopilot.md +0 -50
- package/.codex/prompts/deploy.md +0 -33
- package/.codex/prompts/execute-selected-pr.md +0 -35
- package/.codex/prompts/fix-issue.md +0 -34
- package/.codex/prompts/minimal-context-mode.md +0 -55
- package/.codex/prompts/orchestrate-next.md +0 -33
- package/.codex/prompts/plan-from-requirement.md +0 -37
- package/.codex/prompts/review-implementation.md +0 -33
- package/.codex/prompts/roadmap-audit.md +0 -22
- package/.codex/prompts/specs/create-spec-from-requirement.md +0 -26
- package/.codex/prompts/specs/review-spec.md +0 -29
- package/.codex/prompts/specs/spec-to-pr-breakdown.md +0 -23
- package/.codex/prompts/specs/spec-to-technical-plan.md +0 -28
- package/.codex/prompts/start-project.md +0 -29
- package/.codex/prompts/token-economy-mode.md +0 -48
- package/.codex/prompts/validate-work.md +0 -28
- package/checklists/change-spec-readiness-checklist.md +0 -34
- package/docs/full-documentation.md +0 -661
- package/docs/setup-codex-opencode.md +0 -313
- package/harness/README.md +0 -106
- package/opencode/README.md +0 -84
- package/opencode/agents/README.md +0 -113
- package/opencode/agents/atlas.md +0 -127
- package/opencode/agents/discovery.md +0 -61
- package/opencode/agents/fixer.md +0 -51
- package/opencode/agents/implementer.md +0 -61
- package/opencode/agents/orchestrator.md +0 -145
- package/opencode/agents/planner.md +0 -60
- package/opencode/agents/prompt-engineer.md +0 -50
- package/opencode/agents/release-manager.md +0 -50
- package/opencode/agents/reviewer.md +0 -51
- package/opencode/agents/spec-engineer.md +0 -85
- package/opencode/agents/validator.md +0 -50
- package/opencode/agents/wordpress-engineer.md +0 -49
- package/opencode/commands/README.md +0 -48
- package/opencode/commands/autopilot.md +0 -50
- package/opencode/commands/deploy.md +0 -35
- package/opencode/commands/execute.md +0 -47
- package/opencode/commands/orchestrate.md +0 -37
- package/opencode/commands/plan.md +0 -39
- package/opencode/commands/review.md +0 -33
- package/opencode/commands/roadmap-audit.md +0 -30
- package/opencode/commands/ship.md +0 -48
- package/opencode/commands/specs/create-spec-from-request.md +0 -27
- package/opencode/commands/specs/create-spec-from-requirement.md +0 -25
- package/opencode/commands/specs/review-spec.md +0 -26
- package/opencode/commands/specs/spec-to-pr-breakdown.md +0 -19
- package/opencode/commands/specs/spec-to-tasks.md +0 -26
- package/opencode/commands/specs/spec-to-technical-plan.md +0 -27
- package/opencode/commands/start.md +0 -45
- package/opencode/commands/token-economy.md +0 -29
- package/opencode/commands/validate.md +0 -33
- package/opencode.jsonc +0 -235
- package/packages/ai-workflow/README.md +0 -82
- package/packages/ai-workflow/src/cli.js +0 -70
- package/packages/ai-workflow/src/commands/codex.js +0 -37
- package/packages/ai-workflow/src/commands/doctor.js +0 -168
- package/packages/ai-workflow/src/commands/guide.js +0 -194
- package/packages/ai-workflow/src/core/opencode-merge.js +0 -172
- package/packages/ai-workflow/src/core/symlink-layout.js +0 -54
- package/packages/ai-workflow/src/core/templates.js +0 -276
- package/runbooks/agent-delegation-workflow.md +0 -111
- package/runbooks/apply-starter-to-real-project.md +0 -445
- package/runbooks/commands-cheatsheet.md +0 -71
- package/runbooks/how-to-use-skills.md +0 -713
- package/runbooks/quick-start-guide.md +0 -213
- package/runbooks/tutorial-walkthroughs.md +0 -416
- package/runbooks/use-linear-for-operational-planning.md +0 -185
- package/runbooks/use-napkin-project-memory.md +0 -77
- package/templates/AGENTS.template.md +0 -397
- package/templates/DESIGN.template.md +0 -484
- package/templates/PR-PLAN.template.md +0 -172
- package/templates/README.template.md +0 -293
- package/templates/REQUIREMENT.template.md +0 -165
- package/templates/SPEC.template.md +0 -397
- package/templates/TECH-PLAN.template.md +0 -244
- package/templates/change-proposal.template.md +0 -97
- /package/{checklists/spec-readiness-checklist.md → dist-assets/docs/policies/SPEC_READINESS.md} +0 -0
- /package/{prompts → dist-assets/prompts}/00-bootstrap-project.md +0 -0
- /package/{prompts → dist-assets/prompts}/01-create-requirement.md +0 -0
- /package/{prompts → dist-assets/prompts}/02-create-spec.md +0 -0
- /package/{prompts → dist-assets/prompts}/03-create-tech-plan.md +0 -0
- /package/{prompts → dist-assets/prompts}/04-breakdown-prs.md +0 -0
- /package/{prompts → dist-assets/prompts}/05-implement-pr.md +0 -0
- /package/{prompts → dist-assets/prompts}/06-review-and-fix.md +0 -0
- /package/{prompts → dist-assets/prompts}/07-apply-design.md +0 -0
- /package/{prompts → dist-assets/prompts}/08-validate.md +0 -0
- /package/{prompts → dist-assets/prompts}/09-deploy.md +0 -0
- /package/{prompts → dist-assets/prompts}/commands/implement.md +0 -0
- /package/{prompts → dist-assets/prompts}/commands/requirement.md +0 -0
- /package/{prompts → dist-assets/prompts}/commands/spec.md +0 -0
- /package/{prompts → dist-assets/prompts}/commands/tech-plan.md +0 -0
- /package/{prompts → dist-assets/prompts}/commands/validate.md +0 -0
- /package/{runbooks → dist-assets/runbooks}/branch-cleanup.md +0 -0
- /package/{runbooks → dist-assets/runbooks}/deploy-checklist.md +0 -0
- /package/{runbooks → dist-assets/runbooks}/publication-readiness-checklist.md +0 -0
- /package/{runbooks → dist-assets/runbooks}/publish-package-checklist.md +0 -0
- /package/{runbooks → dist-assets/runbooks}/team-governance-pr-readiness.md +0 -0
- /package/{runbooks → dist-assets/runbooks}/validate-starter-in-real-project.md +0 -0
- /package/{runbooks → dist-assets/runbooks}/validation-checklist.md +0 -0
- /package/{schemas → dist-assets/schemas}/README.md +0 -0
- /package/{schemas → dist-assets/schemas}/functional-spec.schema.json +0 -0
- /package/{schemas → dist-assets/schemas}/handoff.schema.json +0 -0
- /package/{schemas → dist-assets/schemas}/pr-breakdown.schema.json +0 -0
- /package/{schemas → dist-assets/schemas}/requirement.schema.json +0 -0
- /package/{schemas → dist-assets/schemas}/technical-plan.schema.json +0 -0
- /package/{schemas → dist-assets/schemas}/validation-report.schema.json +0 -0
- /package/{packages/ai-workflow/src → src}/core/backup.js +0 -0
- /package/{packages/ai-workflow/src → src}/core/filesystem.js +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { RequestClassifier } from "../core/request-classifier.js";
|
|
2
|
+
import { ExecutionPlanner } from "../core/execution-planner.js";
|
|
3
|
+
import { WorkflowStateMachine } from "../core/workflow-state-machine.js";
|
|
4
|
+
import { BranchGate } from "../core/gates/branch-gate.js";
|
|
5
|
+
import { OpenCodeAdapter } from "../core/runtime/opencode-adapter.js";
|
|
6
|
+
import { runCollectEvidence } from "./collect-evidence.js";
|
|
7
|
+
import { QualityGuard } from "../core/validation/quality-guard.js";
|
|
8
|
+
import { HandoffEngine } from "../core/handoff/handoff-engine.js";
|
|
9
|
+
import { HealerEngine } from "../core/healing/healer-engine.js";
|
|
10
|
+
import { createCliRemediationExecutor } from "../core/healing/cli-remediation-executor.js";
|
|
11
|
+
import { isRecoverableGateFailure, isTerminalFailure } from "../core/statuses.js";
|
|
12
|
+
import fs from "node:fs/promises";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
|
|
15
|
+
function slugify(text) {
|
|
16
|
+
return text
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
19
|
+
.replace(/^-+|-+$/g, "")
|
|
20
|
+
.slice(0, 32) || "task";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function combineValidation(evidence, quality) {
|
|
24
|
+
const statuses = [evidence.internalStatus, quality.overallStatus];
|
|
25
|
+
let overallStatus = "PASS";
|
|
26
|
+
if (statuses.includes("BLOCKED")) overallStatus = "BLOCKED";
|
|
27
|
+
else if (statuses.includes("FAIL")) overallStatus = "FAIL";
|
|
28
|
+
else if (statuses.includes("FAIL_DELEGATION_GATE")) overallStatus = "FAIL_DELEGATION_GATE";
|
|
29
|
+
else if (statuses.includes("FAIL_QUALITY_GATE")) overallStatus = "FAIL_QUALITY_GATE";
|
|
30
|
+
else if (statuses.includes("PASS_WITH_NOTES")) overallStatus = "PASS_WITH_NOTES";
|
|
31
|
+
return { overallStatus, evidence, quality };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* runExecute - Coordinators natural request execution.
|
|
36
|
+
*/
|
|
37
|
+
export async function runExecute({ cwd, naturalRequest, override, taskSlug: taskSlugOverride }) {
|
|
38
|
+
if (!naturalRequest || !naturalRequest.trim()) {
|
|
39
|
+
throw new Error("Missing request. Please provide a natural request string via positional arguments or --request flag.");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const taskSlug = taskSlugOverride || slugify(naturalRequest);
|
|
43
|
+
console.log(`\n[AI WORKFLOW] Executing natural request intake [slug: ${taskSlug}]...\n`);
|
|
44
|
+
|
|
45
|
+
const stateMachine = new WorkflowStateMachine();
|
|
46
|
+
|
|
47
|
+
// 1. Classification
|
|
48
|
+
const classifier = new RequestClassifier();
|
|
49
|
+
const classification = classifier.classify(naturalRequest);
|
|
50
|
+
console.log(`[CLASSIFIED] Intent: ${classification.intent}, Mode: ${classification.mode}, Profile: ${classification.profile}`);
|
|
51
|
+
stateMachine.transitionTo("CLASSIFIED");
|
|
52
|
+
|
|
53
|
+
// 2. Planning
|
|
54
|
+
const planner = new ExecutionPlanner({ cwd });
|
|
55
|
+
const plan = planner.plan(classification, taskSlug);
|
|
56
|
+
console.log(`[PLANNED] Owner: ${plan.owner}, Remediation limit: ${plan.remediationLimit}`);
|
|
57
|
+
stateMachine.transitionTo("PLANNED");
|
|
58
|
+
|
|
59
|
+
// 3. Branch Gate
|
|
60
|
+
const branchGate = new BranchGate({ memoryDir: path.join(cwd, ".ai-workflow"), cwd });
|
|
61
|
+
const gateResult = branchGate.check(override, {
|
|
62
|
+
autoRecover: true,
|
|
63
|
+
taskSlug,
|
|
64
|
+
readOnly: !plan.branchNeeded
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (gateResult.blocked) {
|
|
68
|
+
stateMachine.transitionTo("BLOCKED");
|
|
69
|
+
throw new Error(`[GATE BLOCKED] ${gateResult.reason}`);
|
|
70
|
+
}
|
|
71
|
+
console.log(`[PASS] Branch Gate: ${gateResult.recovered ? `${gateResult.branchBefore} -> ${gateResult.branch}` : `${gateResult.branch} is authorized`}.`);
|
|
72
|
+
stateMachine.transitionTo("BRANCH_READY");
|
|
73
|
+
|
|
74
|
+
// 4. Spec template creation (for full/deep mode)
|
|
75
|
+
if (plan.specPath) {
|
|
76
|
+
const fullSpecPath = path.join(cwd, plan.specPath);
|
|
77
|
+
const specExists = await fs.access(fullSpecPath).then(() => true).catch(() => false);
|
|
78
|
+
if (!specExists) {
|
|
79
|
+
await fs.mkdir(path.dirname(fullSpecPath), { recursive: true });
|
|
80
|
+
const specTemplatePath = path.join(cwd, ".ai-workflow/templates/specs/standard.md");
|
|
81
|
+
const templateContent = await fs.readFile(specTemplatePath, "utf8").catch(() => {
|
|
82
|
+
return `# [STANDARD] Specification: ${classification.request}\n\n## Metadata\n\n- ID: SPEC-${taskSlug}\n- Author: Spec-Engineer\n- Status: DRAFT\n- Date: ${new Date().toISOString().split("T")[0]}\n\n## Functional Requirements\n\n- ${classification.request}\n\n## Technical Implementation Plan\n\n### Files to Create/Modify\n\n- \`src/index.js\`\n\n## Acceptance Criteria\n\n- [ ] Implemented successfully\n\n## Testing Strategy\n\n- [ ] Behavior tests pass`;
|
|
83
|
+
});
|
|
84
|
+
await fs.writeFile(fullSpecPath, templateContent);
|
|
85
|
+
console.log(`[EXECUTE] Created DRAFT specification template at: ${plan.specPath}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 5. Delegation
|
|
90
|
+
stateMachine.transitionTo("DELEGATED");
|
|
91
|
+
stateMachine.transitionTo("IMPLEMENTING");
|
|
92
|
+
|
|
93
|
+
const adapter = new OpenCodeAdapter({ cwd });
|
|
94
|
+
let promptMsg = classification.request;
|
|
95
|
+
if (plan.specPath) {
|
|
96
|
+
promptMsg = `Please review and fill in the specification file at: ${plan.specPath}. Make sure to change the Status field to 'APPROVED' in the Metadata section, and then implement the behavior described.`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const runResult = await adapter.execute(promptMsg, {
|
|
100
|
+
agent: plan.owner,
|
|
101
|
+
dangerouslySkipPermissions: true
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (!runResult.success) {
|
|
105
|
+
console.error(`[EXECUTE] OpenCode adapter execution reported failure.`);
|
|
106
|
+
}
|
|
107
|
+
stateMachine.transitionTo("IMPLEMENTED");
|
|
108
|
+
|
|
109
|
+
// 6. Validation
|
|
110
|
+
stateMachine.transitionTo("VALIDATING");
|
|
111
|
+
const validateWorkflow = async () => {
|
|
112
|
+
const evidence = await runCollectEvidence({
|
|
113
|
+
cwd,
|
|
114
|
+
exitOnError: false,
|
|
115
|
+
taskSlug,
|
|
116
|
+
mode: plan.mode,
|
|
117
|
+
profile: plan.profile,
|
|
118
|
+
branchRecovery: gateResult.recovered ? `${gateResult.branchBefore} -> ${gateResult.branch}` : "NOT_REQUIRED"
|
|
119
|
+
});
|
|
120
|
+
const quality = await new QualityGuard({ cwd, taskSlug, mode: plan.mode }).verify();
|
|
121
|
+
return combineValidation(evidence, quality);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
let result = await validateWorkflow();
|
|
125
|
+
|
|
126
|
+
// 7. Bounded Remediation
|
|
127
|
+
if (isRecoverableGateFailure(result.overallStatus)) {
|
|
128
|
+
stateMachine.transitionTo("REMEDIATING");
|
|
129
|
+
console.log(`\n[REMEDIATION REQUIRED] ${result.overallStatus}. Starting bounded ${plan.mode} remediation.`);
|
|
130
|
+
const executor = createCliRemediationExecutor(cwd);
|
|
131
|
+
const healer = new HealerEngine({ cwd, mode: plan.mode, taskSlug });
|
|
132
|
+
|
|
133
|
+
result = await healer.run({
|
|
134
|
+
initialResult: result,
|
|
135
|
+
validate: async () => {
|
|
136
|
+
stateMachine.transitionTo("REVALIDATING");
|
|
137
|
+
const res = await validateWorkflow();
|
|
138
|
+
return res;
|
|
139
|
+
},
|
|
140
|
+
remediate: executor
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (isTerminalFailure(result.overallStatus)) {
|
|
145
|
+
stateMachine.transitionTo("BLOCKED");
|
|
146
|
+
throw new Error(`[WORKFLOW BLOCKED] ${result.overallStatus}: Validation could not be resolved safely.`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 8. Finalizer
|
|
150
|
+
const finalState = result.overallStatus === "PASS"
|
|
151
|
+
? "COMPLETED"
|
|
152
|
+
: result.overallStatus === "PASS_WITH_NOTES"
|
|
153
|
+
? "COMPLETED_WITH_NOTES"
|
|
154
|
+
: "BLOCKED";
|
|
155
|
+
|
|
156
|
+
stateMachine.transitionTo(finalState);
|
|
157
|
+
|
|
158
|
+
console.log("\n--- Final Handoff ---");
|
|
159
|
+
const handoffEngine = new HandoffEngine({ cwd });
|
|
160
|
+
const handoffPath = await handoffEngine.generate({
|
|
161
|
+
taskId: taskSlug,
|
|
162
|
+
status: finalState,
|
|
163
|
+
specPaths: plan.specPath ? [plan.specPath] : [],
|
|
164
|
+
evidence: result.evidence,
|
|
165
|
+
nextActions: `Profile ${plan.profile}. Observed execution completed with status ${finalState}.`
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
console.log(`\n[AI WORKFLOW COMPLETE] ${finalState}`);
|
|
169
|
+
console.log(`Handoff Packet: ${path.relative(cwd, handoffPath)}\n`);
|
|
170
|
+
|
|
171
|
+
return { ...result, stateHistory: stateMachine.getHistory() };
|
|
172
|
+
}
|
|
@@ -2,10 +2,11 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { createInstallPlan } from "../core/install-plan.js";
|
|
4
4
|
import { buildAiWorkflowConfig, getTemplateFiles, isValidProfile } from "../core/templates.js";
|
|
5
|
-
import { exists, writeFileSafe } from "../core/filesystem.js";
|
|
5
|
+
import { exists, writeFileSafe, readJson } from "../core/filesystem.js";
|
|
6
6
|
import { createManagedBackup, createManagedPathBackup } from "../core/backup.js";
|
|
7
7
|
import { mergeOpencodeConfig } from "../core/opencode-merge.js";
|
|
8
|
-
import { buildSymlinkEntries, isSymlinkTo } from "../core/symlink-layout.js";
|
|
8
|
+
import { buildSymlinkEntries, isSymlinkTo, setupInternalSymlinks } from "../core/symlink-layout.js";
|
|
9
|
+
import { GeminiAdapter, ClaudeAdapter, CodexAdapter } from "../adapters/index.js";
|
|
9
10
|
|
|
10
11
|
function summarize(actions) {
|
|
11
12
|
const createCount = actions.filter((a) => a.type === "create").length;
|
|
@@ -79,16 +80,63 @@ async function upsertGitignoreBlock(cwd, entries) {
|
|
|
79
80
|
return "updated";
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
83
|
+
async function injectScripts(cwd) {
|
|
84
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
85
|
+
if (!(await exists(pkgPath))) return;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const pkg = await readJson(pkgPath);
|
|
89
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
90
|
+
|
|
91
|
+
if (!pkg.scripts.validate) {
|
|
92
|
+
pkg.scripts.validate = "ai-workflow collect-evidence";
|
|
93
|
+
await writeFileSafe(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
} catch {
|
|
97
|
+
// Ignore invalid package.json
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function runInit({
|
|
103
|
+
cwd, yes, force, dryRun, noInstall, noOverwrite, gemini, claude, codex, "dev-mode": devMode, profile }) {
|
|
104
|
+
// Self-execution guard
|
|
105
|
+
if (!devMode) {
|
|
106
|
+
try {
|
|
107
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
108
|
+
if (await exists(pkgPath)) {
|
|
109
|
+
const pkg = await readJson(pkgPath);
|
|
110
|
+
if (pkg.name === "@williambeto/ai-workflow") {
|
|
111
|
+
console.error("\nFATAL: Cannot run 'ai-workflow init' inside its own development repository.");
|
|
112
|
+
console.error("This would corrupt the development environment. Aborting.");
|
|
113
|
+
console.error("Use the --dev-mode flag if you are developing the kit itself and need to test the init command.\n");
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
// Ignore if package.json is unreadable. The guard is a safety net.
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const selectedProfile = profile || "standard";
|
|
85
123
|
|
|
86
124
|
if (!isValidProfile(selectedProfile)) {
|
|
87
|
-
|
|
125
|
+
console.error(`Invalid profile: "${selectedProfile}". Valid profiles: standard, full`);
|
|
126
|
+
process.exit(1);
|
|
88
127
|
}
|
|
128
|
+
const installRoot = ".ai-workflow";
|
|
129
|
+
|
|
130
|
+
const platforms = [];
|
|
131
|
+
if (gemini) platforms.push("gemini");
|
|
132
|
+
if (claude) platforms.push("claude");
|
|
133
|
+
if (codex) platforms.push("codex");
|
|
89
134
|
|
|
90
135
|
console.log(`ai-workflow: initializing in ${cwd}`);
|
|
91
136
|
console.log(`Profile: ${selectedProfile}`);
|
|
137
|
+
if (platforms.length > 0) {
|
|
138
|
+
console.log(`Platforms: ${platforms.join(", ")}`);
|
|
139
|
+
}
|
|
92
140
|
|
|
93
141
|
const actions = await createInstallPlan({ cwd, exists, profile: selectedProfile });
|
|
94
142
|
const linkEntries = buildSymlinkEntries({ templateFiles: getTemplateFiles(selectedProfile), installRoot });
|
|
@@ -105,6 +153,9 @@ export async function runInit({ cwd, yes, force, dryRun, noInstall, noOverwrite,
|
|
|
105
153
|
|
|
106
154
|
if (dryRun) {
|
|
107
155
|
console.log("Dry-run enabled. No files were written.");
|
|
156
|
+
if (platforms.length > 0) {
|
|
157
|
+
console.log("ai-workflow: (dry-run) platform migration would be executed after file writing.");
|
|
158
|
+
}
|
|
108
159
|
return;
|
|
109
160
|
}
|
|
110
161
|
|
|
@@ -128,17 +179,10 @@ export async function runInit({ cwd, yes, force, dryRun, noInstall, noOverwrite,
|
|
|
128
179
|
}
|
|
129
180
|
|
|
130
181
|
const content =
|
|
131
|
-
action.relativePath === ".ai-workflow.json"
|
|
182
|
+
action.relativePath === ".ai-workflow/config.json"
|
|
132
183
|
? `${JSON.stringify(
|
|
133
184
|
buildAiWorkflowConfig({
|
|
134
|
-
profile: selectedProfile
|
|
135
|
-
managedFiles: Array.from(
|
|
136
|
-
new Set([
|
|
137
|
-
...Object.keys(getTemplateFiles(selectedProfile)).map((p) => path.join(installRoot, p)),
|
|
138
|
-
".ai-workflow.json"
|
|
139
|
-
])
|
|
140
|
-
),
|
|
141
|
-
managedLinks: linkEntries.map((entry) => entry.linkPath)
|
|
185
|
+
profile: selectedProfile
|
|
142
186
|
}),
|
|
143
187
|
null,
|
|
144
188
|
2
|
|
@@ -175,6 +219,8 @@ export async function runInit({ cwd, yes, force, dryRun, noInstall, noOverwrite,
|
|
|
175
219
|
maxPerFile: 20
|
|
176
220
|
});
|
|
177
221
|
linkBackups.push(backupPath);
|
|
222
|
+
// Ensure we remove the old path before symlinking if it's not already handled by backup
|
|
223
|
+
await fs.rm(absoluteLinkPath, { recursive: true, force: true });
|
|
178
224
|
}
|
|
179
225
|
|
|
180
226
|
const stat = await fs.lstat(absoluteTargetPath);
|
|
@@ -182,6 +228,7 @@ export async function runInit({ cwd, yes, force, dryRun, noInstall, noOverwrite,
|
|
|
182
228
|
const linkTarget = process.platform === "win32" ? absoluteTargetPath : path.relative(path.dirname(absoluteLinkPath), absoluteTargetPath);
|
|
183
229
|
|
|
184
230
|
try {
|
|
231
|
+
await fs.mkdir(path.dirname(absoluteLinkPath), { recursive: true });
|
|
185
232
|
await fs.symlink(linkTarget, absoluteLinkPath, type);
|
|
186
233
|
} catch (error) {
|
|
187
234
|
throw new Error(
|
|
@@ -193,25 +240,77 @@ export async function runInit({ cwd, yes, force, dryRun, noInstall, noOverwrite,
|
|
|
193
240
|
linkCreated.push(linkPath);
|
|
194
241
|
}
|
|
195
242
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
: await mergeOpencodeConfig(cwd, { force, backupRoot, profile: selectedProfile });
|
|
243
|
+
await setupInternalSymlinks(cwd, installRoot);
|
|
244
|
+
|
|
245
|
+
const opencodeResult = await mergeOpencodeConfig(cwd, { force, backupRoot });
|
|
200
246
|
|
|
201
247
|
const generatedIgnoreEntries = [
|
|
202
248
|
".ai-workflow/",
|
|
203
|
-
".ai-workflow.json",
|
|
204
249
|
".ai-workflow-backups/",
|
|
250
|
+
"opencode.jsonc.backup.*",
|
|
205
251
|
...linkEntries.flatMap((entry) => toIgnoreEntries(entry.linkPath))
|
|
206
252
|
];
|
|
207
253
|
|
|
254
|
+
if (gemini) {
|
|
255
|
+
generatedIgnoreEntries.push(".gemini/");
|
|
256
|
+
}
|
|
257
|
+
if (codex) {
|
|
258
|
+
generatedIgnoreEntries.push(".agents/", ".codex/");
|
|
259
|
+
}
|
|
260
|
+
if (claude) {
|
|
261
|
+
generatedIgnoreEntries.push(".claude/");
|
|
262
|
+
}
|
|
263
|
+
|
|
208
264
|
const gitignoreResult = await upsertGitignoreBlock(cwd, generatedIgnoreEntries);
|
|
265
|
+
const scriptInjected = await injectScripts(cwd);
|
|
266
|
+
|
|
267
|
+
if (platforms.length > 0) {
|
|
268
|
+
console.log("ai-workflow: migrating to native platforms...");
|
|
269
|
+
const agentsDir = path.join(cwd, installRoot, "opencode/agents");
|
|
270
|
+
const skillsDir = path.join(cwd, installRoot, "opencode/skills");
|
|
271
|
+
|
|
272
|
+
const agentFiles = (await fs.readdir(agentsDir).catch(() => []))
|
|
273
|
+
.filter((f) => f.endsWith(".md"))
|
|
274
|
+
.map((f) => path.join(agentsDir, f));
|
|
275
|
+
|
|
276
|
+
if (gemini) {
|
|
277
|
+
const adapter = new GeminiAdapter({ cwd });
|
|
278
|
+
|
|
279
|
+
// Collect specialized skills from the new opencode/skills path
|
|
280
|
+
const skillFolders = await fs.readdir(skillsDir).catch(() => []);
|
|
281
|
+
const skillFiles = [];
|
|
282
|
+
for (const folder of skillFolders) {
|
|
283
|
+
const skillPath = path.join(skillsDir, folder, "SKILL.md");
|
|
284
|
+
if (await exists(skillPath)) {
|
|
285
|
+
skillFiles.push(skillPath);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const allFiles = [...agentFiles, ...skillFiles];
|
|
290
|
+
const transformed = await Promise.all(allFiles.map((f) => adapter.transform(f)));
|
|
291
|
+
await adapter.deploy(transformed, installRoot);
|
|
292
|
+
console.log(`- gemini: deployed AI Workflow Kit agents to .gemini/ (native discovery enabled)`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (claude) {
|
|
296
|
+
const adapter = new ClaudeAdapter({ cwd });
|
|
297
|
+
await adapter.deploy(installRoot);
|
|
298
|
+
console.log("- claude: deployed AI Workflow Kit agents to CLAUDE.md and .claude/rules/ (native discovery enabled)");
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (codex) {
|
|
302
|
+
const adapter = new CodexAdapter({ cwd });
|
|
303
|
+
await adapter.deploy(installRoot);
|
|
304
|
+
console.log("- codex: deployed AI Workflow Kit agents to .agents/, .codex/, and .github/ (native discovery enabled)");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
209
307
|
|
|
210
308
|
console.log("Installation complete.");
|
|
211
309
|
console.log(`- profile: ${selectedProfile}`);
|
|
212
310
|
|
|
213
311
|
console.log(`- opencode.jsonc: ${opencodeResult.reason}`);
|
|
214
312
|
console.log(`- .gitignore: ${gitignoreResult}`);
|
|
313
|
+
console.log(`- scripts: ${scriptInjected ? "injected 'validate'" : "already-up-to-date"}`);
|
|
215
314
|
console.log(`- symlink layout: ${linkCreated.length > 0 ? `created ${linkCreated.length}` : "already-up-to-date"}`);
|
|
216
315
|
if (backups.length > 0) {
|
|
217
316
|
console.log(`- backups created: ${backups.length}`);
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { BranchGate } from "../core/gates/branch-gate.js";
|
|
2
|
+
import { SpecValidator } from "../core/sdd/validator.js";
|
|
3
|
+
import { HandoffEngine } from "../core/handoff/handoff-engine.js";
|
|
4
|
+
import { runCollectEvidence } from "./collect-evidence.js";
|
|
5
|
+
import { QualityGuard } from "../core/validation/quality-guard.js";
|
|
6
|
+
import { HealerEngine } from "../core/healing/healer-engine.js";
|
|
7
|
+
import { createCliRemediationExecutor } from "../core/healing/cli-remediation-executor.js";
|
|
8
|
+
import { isRecoverableGateFailure, isTerminalFailure } from "../core/statuses.js";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import fs from "node:fs/promises";
|
|
11
|
+
import { getWorkflowProfile, resolveWorkflowProfile } from "../core/workflow-profiles.js";
|
|
12
|
+
|
|
13
|
+
function normalizeTaskSlugFromSpec(specPath) {
|
|
14
|
+
const normalized = String(specPath).replaceAll("\\", "/");
|
|
15
|
+
const marker = "/docs/workflows/";
|
|
16
|
+
const index = normalized.includes(marker)
|
|
17
|
+
? normalized.indexOf(marker) + marker.length
|
|
18
|
+
: normalized.startsWith("docs/workflows/") ? "docs/workflows/".length : -1;
|
|
19
|
+
if (index >= 0) {
|
|
20
|
+
const slug = normalized.slice(index).split("/")[0];
|
|
21
|
+
if (slug) return slug;
|
|
22
|
+
}
|
|
23
|
+
return path.basename(specPath, path.extname(specPath));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function combineValidation(evidence, quality) {
|
|
27
|
+
const statuses = [evidence.internalStatus, quality.overallStatus];
|
|
28
|
+
let overallStatus = "PASS";
|
|
29
|
+
if (statuses.includes("BLOCKED")) overallStatus = "BLOCKED";
|
|
30
|
+
else if (statuses.includes("FAIL")) overallStatus = "FAIL";
|
|
31
|
+
else if (statuses.includes("FAIL_DELEGATION_GATE")) overallStatus = "FAIL_DELEGATION_GATE";
|
|
32
|
+
else if (statuses.includes("FAIL_QUALITY_GATE")) overallStatus = "FAIL_QUALITY_GATE";
|
|
33
|
+
else if (statuses.includes("PASS_WITH_NOTES")) overallStatus = "PASS_WITH_NOTES";
|
|
34
|
+
return { overallStatus, evidence, quality };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Coordinates branch safety, specification validation, observed validation, bounded remediation, and handoff.
|
|
39
|
+
* Failed required validation can never be promoted to success.
|
|
40
|
+
*/
|
|
41
|
+
export async function runMasterOrchestrator({ cwd, specPath, override, remediationExecutor = null }) {
|
|
42
|
+
console.log("\n[AI WORKFLOW] Starting evidence-backed orchestration...\n");
|
|
43
|
+
|
|
44
|
+
const branchGate = new BranchGate({ memoryDir: path.join(cwd, ".ai-workflow"), cwd });
|
|
45
|
+
const taskSlug = specPath ? normalizeTaskSlugFromSpec(specPath) : "implementation";
|
|
46
|
+
const gateResult = branchGate.check(override, { autoRecover: true, taskSlug });
|
|
47
|
+
if (gateResult.blocked) throw new Error(`[GATE BLOCKED] ${gateResult.reason}`);
|
|
48
|
+
console.log(`[PASS] Branch Gate: ${gateResult.recovered ? `${gateResult.branchBefore} -> ${gateResult.branch}` : `${gateResult.branch} is authorized`}.`);
|
|
49
|
+
|
|
50
|
+
if (!specPath) throw new Error("[SDD BLOCKED] Missing --spec-path. An approved specification is required.");
|
|
51
|
+
|
|
52
|
+
const validator = new SpecValidator();
|
|
53
|
+
const absoluteSpecPath = path.isAbsolute(specPath) ? specPath : path.join(cwd, specPath);
|
|
54
|
+
const validation = await validator.validate(absoluteSpecPath);
|
|
55
|
+
if (!validation.valid) throw new Error(`[SDD BLOCKED] Specification is not ready: ${validation.reason}`);
|
|
56
|
+
|
|
57
|
+
const executionMode = validation.tier === "deep" ? "full" : validation.tier === "tiny" ? "quick" : "standard";
|
|
58
|
+
const specContent = await fs.readFile(absoluteSpecPath, "utf8");
|
|
59
|
+
const workflowProfile = resolveWorkflowProfile({ request: specContent });
|
|
60
|
+
const profileDefinition = getWorkflowProfile(workflowProfile);
|
|
61
|
+
console.log(`[PASS] Specification: ${validation.tier.toUpperCase()} spec is APPROVED.`);
|
|
62
|
+
console.log(`[PROFILE] ${workflowProfile} -> ${profileDefinition.owner}; skills: ${profileDefinition.skills.join(", ") || "none"}.`);
|
|
63
|
+
|
|
64
|
+
const validateWorkflow = async () => {
|
|
65
|
+
const evidence = await runCollectEvidence({
|
|
66
|
+
cwd,
|
|
67
|
+
exitOnError: false,
|
|
68
|
+
taskSlug,
|
|
69
|
+
mode: executionMode,
|
|
70
|
+
profile: workflowProfile,
|
|
71
|
+
branchRecovery: gateResult.recovered ? `${gateResult.branchBefore} -> ${gateResult.branch}` : "NOT_REQUIRED"
|
|
72
|
+
});
|
|
73
|
+
const quality = await new QualityGuard({ cwd, taskSlug, mode: executionMode }).verify();
|
|
74
|
+
return combineValidation(evidence, quality);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
let result = await validateWorkflow();
|
|
78
|
+
if (isRecoverableGateFailure(result.overallStatus)) {
|
|
79
|
+
console.log(`\n[REMEDIATION REQUIRED] ${result.overallStatus}. Starting bounded ${executionMode} remediation.`);
|
|
80
|
+
// Use the provided executor (programmatic API) or fall back to the default CLI executor.
|
|
81
|
+
// The CLI executor re-runs failed npm scripts; it does not modify source code.
|
|
82
|
+
const executor = typeof remediationExecutor === "function"
|
|
83
|
+
? remediationExecutor
|
|
84
|
+
: createCliRemediationExecutor(cwd);
|
|
85
|
+
const healer = new HealerEngine({ cwd, mode: executionMode, taskSlug });
|
|
86
|
+
result = await healer.run({ initialResult: result, validate: validateWorkflow, remediate: executor });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (isTerminalFailure(result.overallStatus)) {
|
|
90
|
+
throw new Error(`[WORKFLOW BLOCKED] ${result.overallStatus}: ${result.reason || "Validation could not be resolved safely."}`);
|
|
91
|
+
}
|
|
92
|
+
if (isRecoverableGateFailure(result.overallStatus)) {
|
|
93
|
+
throw new Error(`[WORKFLOW BLOCKED] Unresolved gate status after remediation: ${result.overallStatus}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log("\n--- Final Handoff ---");
|
|
97
|
+
const handoffEngine = new HandoffEngine({ cwd });
|
|
98
|
+
const handoffPath = await handoffEngine.generate({
|
|
99
|
+
taskId: path.basename(specPath, ".md"),
|
|
100
|
+
status: result.overallStatus,
|
|
101
|
+
specPaths: [specPath],
|
|
102
|
+
evidence: result.evidence,
|
|
103
|
+
nextActions: `Profile ${workflowProfile}. Observed validation completed. Ready for review or explicitly approved release actions.`
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
console.log(`\n[AI WORKFLOW COMPLETE] ${result.overallStatus}`);
|
|
107
|
+
if (result.remediation?.attempts) console.log(`Remediation attempts: ${result.remediation.attempts}`);
|
|
108
|
+
console.log(`Handoff Packet: ${path.relative(cwd, handoffPath)}\n`);
|
|
109
|
+
return { ...result, workflowProfile };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { combineValidation };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluates objective owner-output completeness. It does not judge visual taste.
|
|
3
|
+
* A caller may resume the same owner once; a second incomplete result must block.
|
|
4
|
+
*/
|
|
5
|
+
export function evaluateOwnerCompletion({
|
|
6
|
+
expectedFiles = [],
|
|
7
|
+
existingFiles = [],
|
|
8
|
+
validation = {},
|
|
9
|
+
ownerReportComplete = false,
|
|
10
|
+
resumeCount = 0
|
|
11
|
+
} = {}) {
|
|
12
|
+
const existing = new Set(existingFiles);
|
|
13
|
+
const missingFiles = expectedFiles.filter((file) => !existing.has(file));
|
|
14
|
+
const missingValidation = Object.entries(validation)
|
|
15
|
+
.filter(([, value]) => value === "REQUIRED" || value === false)
|
|
16
|
+
.map(([key]) => key);
|
|
17
|
+
const missing = [
|
|
18
|
+
...missingFiles.map((file) => `file:${file}`),
|
|
19
|
+
...missingValidation.map((check) => `validation:${check}`),
|
|
20
|
+
...(!ownerReportComplete ? ["owner-report"] : [])
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
if (missing.length === 0) {
|
|
24
|
+
return { status: "PASS", action: "continue", missing: [] };
|
|
25
|
+
}
|
|
26
|
+
if (resumeCount < 1) {
|
|
27
|
+
return { status: "INCOMPLETE", action: "resume-same-owner", missing };
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
status: "BLOCKED",
|
|
31
|
+
action: "stop",
|
|
32
|
+
reason: "Owner output remained incomplete after one resume",
|
|
33
|
+
missing
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ExecutionPlanner - Formulates a minimum operational plan based on classification.
|
|
5
|
+
*/
|
|
6
|
+
export class ExecutionPlanner {
|
|
7
|
+
constructor({ cwd = process.cwd() } = {}) {
|
|
8
|
+
this.cwd = cwd;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates an execution plan.
|
|
13
|
+
* @param {Object} classification - The output of RequestClassifier.
|
|
14
|
+
* @param {string} taskSlug - Descriptive slug for the task.
|
|
15
|
+
* @returns {Object} Operational plan contract.
|
|
16
|
+
*/
|
|
17
|
+
plan(classification, taskSlug = "task") {
|
|
18
|
+
const remediationLimit = classification.mode === "full" ? 3 : classification.mode === "quick" ? 1 : 2;
|
|
19
|
+
const branchNeeded = classification.intent === "write";
|
|
20
|
+
const specPath = classification.specNeeded
|
|
21
|
+
? path.join("docs/workflows", taskSlug, "spec.md")
|
|
22
|
+
: null;
|
|
23
|
+
|
|
24
|
+
// Build default expected validations based on the resolved profile
|
|
25
|
+
const validationsExpected = [];
|
|
26
|
+
if (classification.validationNeeded) {
|
|
27
|
+
validationsExpected.push("test");
|
|
28
|
+
if (classification.profile.startsWith("frontend")) {
|
|
29
|
+
validationsExpected.push("lint", "build");
|
|
30
|
+
} else if (classification.profile === "backend-api") {
|
|
31
|
+
validationsExpected.push("lint");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const restrictions = [
|
|
36
|
+
"Never commit or push directly to main/master.",
|
|
37
|
+
"Always execute behavior tests for new or modified behavior."
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
if (classification.risk === "high") {
|
|
41
|
+
restrictions.push("Require independent validation review.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
objective: classification.request,
|
|
46
|
+
scope: classification.intent === "read-only" ? "Analysis and verification" : "Implementation of requested behavior",
|
|
47
|
+
restrictions,
|
|
48
|
+
owner: classification.owner,
|
|
49
|
+
skills: [...classification.skills],
|
|
50
|
+
branchNeeded,
|
|
51
|
+
branchName: branchNeeded ? `feat/${taskSlug}` : null,
|
|
52
|
+
validationsExpected,
|
|
53
|
+
remediationLimit,
|
|
54
|
+
specPath,
|
|
55
|
+
mode: classification.mode,
|
|
56
|
+
profile: classification.profile
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|