@khoavu882/doflow 0.0.0-stage → 2.0.0-beta.4
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/LICENSE +21 -0
- package/README.md +132 -2
- package/bin/doflow.js +44 -0
- package/core/.antigravity-plugin/hooks.json +39 -0
- package/core/.antigravity-plugin/mcp_config.json +18 -0
- package/core/.antigravity-plugin/plugin.json +31 -0
- package/core/.claude-plugin/marketplace.json +20 -0
- package/core/.claude-plugin/plugin.json +21 -0
- package/core/.codex-plugin/marketplace.json +20 -0
- package/core/.codex-plugin/plugin.json +35 -0
- package/core/.plugin/plugin.json +19 -0
- package/core/harnesses/antigravity/hooks/pre-implementation-gate.sh +9 -0
- package/core/harnesses/antigravity/hooks/stop-check.sh +10 -0
- package/core/harnesses/claude/hooks/lib.sh +304 -0
- package/core/harnesses/claude/hooks/mcp-tool-guard.sh +20 -0
- package/core/harnesses/claude/hooks/permission-audit.sh +47 -0
- package/core/harnesses/claude/hooks/post-compact.sh +74 -0
- package/core/harnesses/claude/hooks/post-edit-lint.sh +36 -0
- package/core/harnesses/claude/hooks/post-tool-failure.sh +47 -0
- package/core/harnesses/claude/hooks/pre-bash-guard.sh +20 -0
- package/core/harnesses/claude/hooks/pre-compact.sh +43 -0
- package/core/harnesses/claude/hooks/pre-implement-gate.sh +21 -0
- package/core/harnesses/claude/hooks/session-end.sh +89 -0
- package/core/harnesses/claude/hooks/session-start.sh +5 -0
- package/core/harnesses/claude/hooks/skill-config-audit.sh +39 -0
- package/core/harnesses/claude/hooks/stop-check.sh +5 -0
- package/core/harnesses/claude/hooks/subagent-audit.sh +7 -0
- package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -0
- package/core/harnesses/claude/settings/keybindings.json +20 -0
- package/core/harnesses/claude/settings/settings.json +201 -0
- package/core/harnesses/claude/statusline/doflow-statusline.sh +49 -0
- package/core/harnesses/codex/agents/core-implementer.toml +7 -0
- package/core/harnesses/codex/agents/quality-guardian.toml +8 -0
- package/core/harnesses/codex/agents/research-writer.toml +8 -0
- package/core/harnesses/codex/agents/spec-analyst.toml +8 -0
- package/core/harnesses/codex/agents/system-architect.toml +9 -0
- package/core/harnesses/codex/config/config.toml +10 -0
- package/core/harnesses/codex/hooks/hooks.json +122 -0
- package/core/harnesses/codex/hooks/lib.sh +335 -0
- package/core/harnesses/codex/hooks/mcp-tool-guard.sh +18 -0
- package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +52 -0
- package/core/harnesses/codex/hooks/post-edit-lint.sh +6 -0
- package/core/harnesses/codex/hooks/pre-bash-guard.sh +18 -0
- package/core/harnesses/codex/hooks/pre-compact.impl.sh +46 -0
- package/core/harnesses/codex/hooks/pre-compact.sh +9 -0
- package/core/harnesses/codex/hooks/pre-implement-gate.sh +19 -0
- package/core/harnesses/codex/hooks/session-end.impl.sh +92 -0
- package/core/harnesses/codex/hooks/session-end.sh +5 -0
- package/core/harnesses/codex/hooks/session-start.sh +5 -0
- package/core/harnesses/codex/hooks/stop-check.sh +8 -0
- package/core/harnesses/codex/hooks/subagent-audit.sh +8 -0
- package/core/harnesses/codex/hooks/user-prompt-submit.sh +6 -0
- package/core/harnesses/gemini/hooks/hooks.json +77 -0
- package/core/harnesses/gemini/hooks/lib.sh +302 -0
- package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +21 -0
- package/core/harnesses/gemini/hooks/post-edit-lint.sh +39 -0
- package/core/harnesses/gemini/hooks/pre-bash-guard.sh +21 -0
- package/core/harnesses/gemini/hooks/pre-compact.sh +38 -0
- package/core/harnesses/gemini/hooks/pre-implement-gate.sh +22 -0
- package/core/harnesses/gemini/hooks/session-end.impl.sh +89 -0
- package/core/harnesses/gemini/hooks/session-end.sh +5 -0
- package/core/harnesses/gemini/hooks/session-start.sh +5 -0
- package/core/harnesses/gemini/settings/adapter-defaults.json +4 -0
- package/core/harnesses/kiro/agents/doflow.json +58 -0
- package/core/harnesses/kiro/hooks/doflow.json +53 -0
- package/core/harnesses/kiro/hooks/lib.sh +324 -0
- package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +9 -0
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +9 -0
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +9 -0
- package/core/harnesses/kiro/hooks/session-start.sh +9 -0
- package/core/harnesses/kiro/hooks/stop-check.sh +43 -0
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +39 -0
- package/core/harnesses/shared/hooks/adapters/antigravity.js +111 -0
- package/core/harnesses/shared/hooks/adapters/arg-fields.js +19 -0
- package/core/harnesses/shared/hooks/adapters/gemini.js +114 -0
- package/core/harnesses/shared/hooks/hooks.json +47 -0
- package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +91 -0
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +97 -0
- package/core/harnesses/shared/hooks/policies/deny-json.sh +29 -0
- package/core/harnesses/shared/hooks/policies/lib.sh +501 -0
- package/core/harnesses/shared/hooks/policies/mcp-policy.conf +21 -0
- package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +91 -0
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +328 -0
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +496 -0
- package/core/harnesses/shared/hooks/policies/prompt-nudge.jq +131 -0
- package/core/harnesses/shared/hooks/policies/session-context.sh +141 -0
- package/core/harnesses/shared/hooks/policies/stop-check.sh +264 -0
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +46 -0
- package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +235 -0
- package/core/harnesses/shared/hooks/stream-hook-runner.js +590 -0
- package/core/harnesses/shared/locator/doflow-run +87 -0
- package/core/registry/advice.json +101 -0
- package/core/registry/assets.json +792 -0
- package/core/registry/capabilities.json +120 -0
- package/core/registry/contracts.json +189 -0
- package/core/registry/external-tools.json +191 -0
- package/core/registry/harnesses.json +2062 -0
- package/core/registry/lifecycle.json +231 -0
- package/core/registry/mcp.json +18 -0
- package/core/registry/models.json +79 -0
- package/core/registry/readiness-templates.json +118 -0
- package/core/registry/routes.json +47 -0
- package/core/registry/storage.json +1061 -0
- package/core/registry/verification.json +258 -0
- package/core/registry/workflows.json +790 -0
- package/core/shared/agent-specs/core-implementer.md +73 -0
- package/core/shared/agent-specs/quality-guardian.md +28 -0
- package/core/shared/agent-specs/research-writer.md +31 -0
- package/core/shared/agent-specs/spec-analyst.md +33 -0
- package/core/shared/agent-specs/system-architect.md +29 -0
- package/core/shared/guidance/DOFLOW_CORE.md +8 -0
- package/core/shared/guidance/FLAGS.md +25 -0
- package/core/shared/guidance/PRINCIPLES.md +61 -0
- package/core/shared/guidance/VERSION +1 -0
- package/core/shared/guidance/mcp/MCP_Context7.md +18 -0
- package/core/shared/guidance/mcp/MCP_Sequential.md +17 -0
- package/core/shared/guidance/modes/MODE_Brainstorming.md +46 -0
- package/core/shared/guidance/modes/MODE_DeepResearch.md +69 -0
- package/core/shared/guidance/modes/MODE_Introspection.md +33 -0
- package/core/shared/guidance/modes/MODE_Orchestration.md +57 -0
- package/core/shared/guidance/modes/MODE_Task_Management.md +74 -0
- package/core/shared/guidance/pointers/claude-gemini.md +2 -0
- package/core/shared/guidance/pointers/codex.md +6 -0
- package/core/shared/guidance/references/ARTIFACT_FORMAT.md +373 -0
- package/core/shared/guidance/references/ARTIFACT_VOICE.md +104 -0
- package/core/shared/guidance/references/CONSTITUTION_BASE.md +47 -0
- package/core/shared/guidance/references/DIAGRAM_GUIDE.md +161 -0
- package/core/shared/guidance/references/DOFLOW_CHAIN.md +87 -0
- package/core/shared/guidance/references/EVIDENCE_LEDGER.md +93 -0
- package/core/shared/guidance/references/MODEL_SELECTION.md +74 -0
- package/core/shared/guidance/references/ORCHESTRATION.md +36 -0
- package/core/shared/guidance/references/RESEARCH_CONFIG.md +21 -0
- package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +81 -0
- package/core/shared/guidance/rules/RULE_01_SAFETY.md +25 -0
- package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +23 -0
- package/core/shared/guidance/rules/RULE_03_QUALITY.md +14 -0
- package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +46 -0
- package/core/shared/scripts/doflow/assets/mermaid-theme.json +46 -0
- package/core/shared/scripts/doflow/bash/do-exec-paths.sh +167 -0
- package/core/shared/scripts/doflow/bash/do-git-state.sh +546 -0
- package/core/shared/scripts/doflow/bash/do-parallel-check.sh +208 -0
- package/core/shared/scripts/doflow/bash/do-paths.sh +347 -0
- package/core/shared/scripts/doflow/bash/do-prereqs.sh +66 -0
- package/core/shared/scripts/doflow/bash/do-review-package.sh +127 -0
- package/core/shared/scripts/doflow/bash/do-task-brief.sh +698 -0
- package/core/shared/scripts/doflow/bash/render-audit.sh +224 -0
- package/core/shared/scripts/doflow/bash/render-diagrams.sh +177 -0
- package/core/shared/scripts/doflow/bash/render-puml.sh +223 -0
- package/core/shared/scripts/doflow/bash/sync-context.sh +66 -0
- package/core/shared/scripts/doflow/bash/validate-artifacts.sh +526 -0
- package/core/shared/scripts/doflow/bin/doflow-run +592 -0
- package/core/shared/skills/do/SKILL.md +128 -0
- package/core/shared/skills/do/references/estimation.md +13 -0
- package/core/shared/skills/do/references/pm_routing.md +25 -0
- package/core/shared/skills/do/references/tool_matrix.md +52 -0
- package/core/shared/skills/do-brainstorm/SKILL.md +252 -0
- package/core/shared/skills/do-code-review/README.md +49 -0
- package/core/shared/skills/do-code-review/SKILL.md +333 -0
- package/core/shared/skills/do-code-review/assets/sample_c_clean.c +71 -0
- package/core/shared/skills/do-code-review/assets/sample_c_smells.c +66 -0
- package/core/shared/skills/do-code-review/assets/sample_cpp_shift.cpp +19 -0
- package/core/shared/skills/do-code-review/assets/sample_csharp_clean.cs +100 -0
- package/core/shared/skills/do-code-review/assets/sample_csharp_smells.cs +78 -0
- package/core/shared/skills/do-code-review/assets/sample_java_clean.java +55 -0
- package/core/shared/skills/do-code-review/assets/sample_java_smells.java +56 -0
- package/core/shared/skills/do-code-review/assets/sample_json_clean.json +7 -0
- package/core/shared/skills/do-code-review/assets/sample_markdown_clean.md +30 -0
- package/core/shared/skills/do-code-review/assets/sample_markdown_smells.md +29 -0
- package/core/shared/skills/do-code-review/assets/sample_shell_heredoc.sh +38 -0
- package/core/shared/skills/do-code-review/assets/sample_shell_smells.sh +15 -0
- package/core/shared/skills/do-code-review/assets/sample_typescript_strings.ts +36 -0
- package/core/shared/skills/do-code-review/assets/sample_yaml_smells.yaml +6 -0
- package/core/shared/skills/do-code-review/content-types/config.md +83 -0
- package/core/shared/skills/do-code-review/content-types/markdown.md +132 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_c_clean_quality.json +79 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_c_smells_quality.json +169 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_cpp_shift_quality.json +49 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_clean_quality.json +149 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_smells_quality.json +157 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_java_clean_quality.json +67 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_java_smells_quality.json +97 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_json_clean_quality.json +33 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_clean_quality.json +1 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_smells_quality.json +16 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_shell_heredoc_quality.json +54 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_shell_smells_quality.json +91 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_typescript_strings_quality.json +60 -0
- package/core/shared/skills/do-code-review/expected_outputs/sample_yaml_smells_quality.json +46 -0
- package/core/shared/skills/do-code-review/languages/c.md +103 -0
- package/core/shared/skills/do-code-review/languages/cpp.md +103 -0
- package/core/shared/skills/do-code-review/languages/csharp.md +97 -0
- package/core/shared/skills/do-code-review/languages/dart.md +108 -0
- package/core/shared/skills/do-code-review/languages/go.md +92 -0
- package/core/shared/skills/do-code-review/languages/java.md +103 -0
- package/core/shared/skills/do-code-review/languages/kotlin.md +88 -0
- package/core/shared/skills/do-code-review/languages/php.md +109 -0
- package/core/shared/skills/do-code-review/languages/python.md +94 -0
- package/core/shared/skills/do-code-review/languages/ruby.md +105 -0
- package/core/shared/skills/do-code-review/languages/rust.md +99 -0
- package/core/shared/skills/do-code-review/languages/shell.md +90 -0
- package/core/shared/skills/do-code-review/languages/swift.md +88 -0
- package/core/shared/skills/do-code-review/languages/typescript.md +97 -0
- package/core/shared/skills/do-code-review/review-policy.json +47 -0
- package/core/shared/skills/do-code-review/rules/universal.md +49 -0
- package/core/shared/skills/do-code-review/scripts/code_quality_checker.py +1696 -0
- package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +532 -0
- package/core/shared/skills/do-code-review/scripts/pr_analyzer.py +620 -0
- package/core/shared/skills/do-code-review/scripts/review_report_generator.py +505 -0
- package/core/shared/skills/do-constitution/SKILL.md +72 -0
- package/core/shared/skills/do-design/SKILL.md +212 -0
- package/core/shared/skills/do-diagnose/SKILL.md +156 -0
- package/core/shared/skills/do-diagnose/references/code_audit.md +15 -0
- package/core/shared/skills/do-diagnose/references/refactoring.md +12 -0
- package/core/shared/skills/do-diagnose/references/root_cause.md +17 -0
- package/core/shared/skills/do-document/SKILL.md +81 -0
- package/core/shared/skills/do-document/references/api-reference.md +42 -0
- package/core/shared/skills/do-document/references/deep_research.md +18 -0
- package/core/shared/skills/do-document/references/embedded-research.md +11 -0
- package/core/shared/skills/do-document/references/implementation-flow.md +105 -0
- package/core/shared/skills/do-document/references/index_generator.md +9 -0
- package/core/shared/skills/do-document/references/user-guide.md +22 -0
- package/core/shared/skills/do-execute-plan/SKILL.md +261 -0
- package/core/shared/skills/do-execute-plan/references/handoff_record.md +57 -0
- package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +92 -0
- package/core/shared/skills/do-execute-plan/references/readiness_gate.md +155 -0
- package/core/shared/skills/do-execute-plan/references/run_position.md +63 -0
- package/core/shared/skills/do-execute-plan/references/scaffold.md +441 -0
- package/core/shared/skills/do-execute-plan/references/task_attempts.md +41 -0
- package/core/shared/skills/do-flow/SKILL.md +186 -0
- package/core/shared/skills/do-flow/references/task_classes.md +134 -0
- package/core/shared/skills/do-git/SKILL.md +115 -0
- package/core/shared/skills/do-git/references/hotfix-ritual.md +44 -0
- package/core/shared/skills/do-git/references/lifecycle-policy.md +54 -0
- package/core/shared/skills/do-git/references/release-ritual.md +64 -0
- package/core/shared/skills/do-implement/SKILL.md +222 -0
- package/core/shared/skills/do-plan/SKILL.md +219 -0
- package/core/shared/skills/do-test/SKILL.md +113 -0
- package/core/shared/templates/doflow/constitution-template.md +28 -0
- package/core/shared/templates/doflow/data-model-template.md +169 -0
- package/core/shared/templates/doflow/design-template.md +193 -0
- package/core/shared/templates/doflow/external-contract-template.md +35 -0
- package/core/shared/templates/doflow/intent-template.md +45 -0
- package/core/shared/templates/doflow/plan-template.md +151 -0
- package/core/shared/templates/doflow/question-log-template.md +51 -0
- package/core/shared/templates/doflow/requirement-template.md +126 -0
- package/core/shared/templates/doflow/specs-template.md +55 -0
- package/core/shared/templates/doflow/state-template.md +59 -0
- package/core/shared/workflows/do-flow-chain.md +17 -0
- package/package.json +48 -4
- package/src/adapters/antigravity/index.js +631 -0
- package/src/adapters/claude/index.js +548 -0
- package/src/adapters/claude/mcp.js +94 -0
- package/src/adapters/codex/agents.js +208 -0
- package/src/adapters/codex/config.js +272 -0
- package/src/adapters/codex/hooks.js +203 -0
- package/src/adapters/codex/index.js +707 -0
- package/src/adapters/codex/mcp.js +271 -0
- package/src/adapters/codex/native-projection.js +34 -0
- package/src/adapters/copilot/index.js +413 -0
- package/src/adapters/copy-tree.js +620 -0
- package/src/adapters/gemini/hooks.js +210 -0
- package/src/adapters/gemini/index.js +390 -0
- package/src/adapters/hook-commands.js +60 -0
- package/src/adapters/index.js +106 -0
- package/src/adapters/kiro/index.js +310 -0
- package/src/adapters/mcp-entries.js +331 -0
- package/src/adapters/opencode/index.js +466 -0
- package/src/adapters/pi/index.js +279 -0
- package/src/adapters/pi/json-members.js +185 -0
- package/src/adapters/pi/mcp.js +373 -0
- package/src/adapters/resolve-source.js +19 -0
- package/src/cli/commands/install.js +218 -0
- package/src/cli/commands/list-backups.js +21 -0
- package/src/cli/commands/reconcile.js +120 -0
- package/src/cli/commands/remove.js +82 -0
- package/src/cli/commands/rollback.js +172 -0
- package/src/cli/commands/self-update.js +33 -0
- package/src/cli/commands/status.js +138 -0
- package/src/cli/commands/tools.js +92 -0
- package/src/cli/commands/update.js +162 -0
- package/src/cli/index.js +568 -0
- package/src/cli/runtime-commands.js +281 -0
- package/src/cli/shared.js +218 -0
- package/src/helper/bash-helper.js +34 -0
- package/src/helper/git.js +24 -0
- package/src/helper/guardrails.js +49 -0
- package/src/helper/harness-paths.js +140 -0
- package/src/helper/marker-merge.js +116 -0
- package/src/helper/prompt.js +61 -0
- package/src/helper/repo-root.js +29 -0
- package/src/helper/settings-merge.js +151 -0
- package/src/helper/settings-scope.js +33 -0
- package/src/helper/toml.js +244 -0
- package/src/install/backup-set.js +149 -0
- package/src/install/backup.js +724 -0
- package/src/install/context.js +58 -0
- package/src/install/manifest.js +145 -0
- package/src/install/mcp.js +254 -0
- package/src/install/paths.js +84 -0
- package/src/install/targets.js +90 -0
- package/src/install/tool-lifecycle.js +151 -0
- package/src/lifecycle/bash-availability.js +25 -0
- package/src/lifecycle/index.js +812 -0
- package/src/lifecycle/mcp-index.js +28 -0
- package/src/lifecycle/policies.js +73 -0
- package/src/lifecycle/view.js +175 -0
- package/src/registry/index.js +611 -0
- package/src/release/build-package.js +91 -0
- package/src/release/changelog-section.js +70 -0
- package/src/release/sync-plugin-versions.js +66 -0
- package/src/runtime/advice/cli.js +283 -0
- package/src/runtime/advice/client.js +324 -0
- package/src/runtime/advice/config.js +189 -0
- package/src/runtime/advice/doctor.js +169 -0
- package/src/runtime/advice/endpoint-guard.js +134 -0
- package/src/runtime/advice/kinds.js +154 -0
- package/src/runtime/advice/providers/ollama-systemone.js +209 -0
- package/src/runtime/advice/record.js +166 -0
- package/src/runtime/advice/registry.js +170 -0
- package/src/runtime/advice/strength.js +66 -0
- package/src/runtime/brief-tools.js +342 -0
- package/src/runtime/c4-project.js +371 -0
- package/src/runtime/capability-router.js +484 -0
- package/src/runtime/checkouts.js +170 -0
- package/src/runtime/claims.js +468 -0
- package/src/runtime/cli-result.js +55 -0
- package/src/runtime/cli.js +678 -0
- package/src/runtime/command-detect.js +516 -0
- package/src/runtime/context-pack.js +492 -0
- package/src/runtime/decision-register.js +493 -0
- package/src/runtime/evidence-ledger.js +338 -0
- package/src/runtime/failure/capture.js +272 -0
- package/src/runtime/failure/classifier.js +68 -0
- package/src/runtime/failure/cli.js +178 -0
- package/src/runtime/failure/home.js +64 -0
- package/src/runtime/failure/store.js +226 -0
- package/src/runtime/feature-resolve.js +79 -0
- package/src/runtime/freshness.js +177 -0
- package/src/runtime/health.js +863 -0
- package/src/runtime/history-compactor.js +237 -0
- package/src/runtime/implementation-gate.js +321 -0
- package/src/runtime/inventory/coverage.js +218 -0
- package/src/runtime/inventory/identity.js +65 -0
- package/src/runtime/inventory/index.js +705 -0
- package/src/runtime/inventory/precedence.js +134 -0
- package/src/runtime/inventory/read-scopes.js +131 -0
- package/src/runtime/inventory/siblings.js +192 -0
- package/src/runtime/knowledge/chunker.js +124 -0
- package/src/runtime/knowledge/hybrid.js +149 -0
- package/src/runtime/knowledge/index-store.js +145 -0
- package/src/runtime/knowledge/retrieval.js +194 -0
- package/src/runtime/leak-scan.js +185 -0
- package/src/runtime/lifecycle/cli.js +276 -0
- package/src/runtime/lifecycle/event-store.js +340 -0
- package/src/runtime/lifecycle/fold.js +353 -0
- package/src/runtime/lifecycle/followup.js +432 -0
- package/src/runtime/lifecycle/goal.js +249 -0
- package/src/runtime/lifecycle/intent-writer.js +86 -0
- package/src/runtime/lifecycle/overview.js +292 -0
- package/src/runtime/lifecycle/release.js +241 -0
- package/src/runtime/lifecycle/report-store.js +221 -0
- package/src/runtime/lifecycle/retention.js +212 -0
- package/src/runtime/lifecycle/root.js +71 -0
- package/src/runtime/lifecycle/status.js +353 -0
- package/src/runtime/lifecycle/store-upkeep.js +393 -0
- package/src/runtime/locator-resolve.js +158 -0
- package/src/runtime/mask.js +210 -0
- package/src/runtime/mcp-consultations.js +412 -0
- package/src/runtime/mcp-reach.js +157 -0
- package/src/runtime/model-router.js +153 -0
- package/src/runtime/outcome.js +467 -0
- package/src/runtime/reach.js +148 -0
- package/src/runtime/readiness-record.js +150 -0
- package/src/runtime/readiness.js +435 -0
- package/src/runtime/recovery.js +282 -0
- package/src/runtime/research-request.js +231 -0
- package/src/runtime/retrieval-plan.js +578 -0
- package/src/runtime/scaffold/artifacts.js +217 -0
- package/src/runtime/scaffold/fingerprint.js +56 -0
- package/src/runtime/scaffold/generate.js +911 -0
- package/src/runtime/scaffold/languages.js +245 -0
- package/src/runtime/storage/cli.js +64 -0
- package/src/runtime/storage/engine.js +249 -0
- package/src/runtime/storage/registry.js +130 -0
- package/src/runtime/storage/roots.js +63 -0
- package/src/runtime/storage/rules.js +282 -0
- package/src/runtime/storage/upkeep.js +243 -0
- package/src/runtime/storage/work-status.js +326 -0
- package/src/runtime/task-attempts.js +415 -0
- package/src/runtime/task-classifier.js +550 -0
- package/src/runtime/task-scope.js +130 -0
- package/src/runtime/task-state.js +176 -0
- package/src/runtime/trace/indicators.js +235 -0
- package/src/runtime/trace/ledger.js +626 -0
- package/src/runtime/trace/render.js +76 -0
- package/src/runtime/trace/views.js +459 -0
- package/src/runtime/verification/contract-runner.js +341 -0
- package/src/runtime/verification/engine.js +1461 -0
- package/src/runtime/verification/registry.js +130 -0
- package/src/runtime/verification/scope-bound.js +418 -0
- package/src/runtime/verification/test-selection.js +172 -0
- package/src/runtime/workflow-engine.js +588 -0
- package/src/runtime/workflow-orchestrator.js +953 -0
- package/src/runtime/worktree.js +340 -0
- package/src/state/index.js +193 -0
- package/src/state/lockfile.js +136 -0
- package/src/state/run-lock.js +408 -0
- package/types/node-commonjs.d.ts +68 -0
- package/types/runtime.d.ts +91 -0
package/src/cli/index.js
ADDED
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// doflow CLI — argument parsing, the installer command table, and dispatch.
|
|
3
|
+
//
|
|
4
|
+
// bin/doflow.js is only a forwarder into main() here. This module owns: parseArgs (verbatim from
|
|
5
|
+
// the pre-extraction monolith), the ONE table mapping the nine installer command names to their
|
|
6
|
+
// handlers under commands/, and the runtime verbs' forwarding via ./runtime-commands — whose
|
|
7
|
+
// implementations stay one-per-module in src/runtime/. Adding an installer command means a new
|
|
8
|
+
// file in src/cli/commands/, an entry in COMMANDS, and an edit to test/guards/cli-boundary.test.js,
|
|
9
|
+
// which ratchets this surface.
|
|
10
|
+
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
11
|
+
const {
|
|
12
|
+
handleCapabilitiesCommand, handleReadinessCommand, handleEvidenceCommand,
|
|
13
|
+
EVIDENCE_SCORE_FIELDS, scoreFieldRefusal,
|
|
14
|
+
} = require('../runtime/cli.js');
|
|
15
|
+
const { pkg } = require('./shared.js');
|
|
16
|
+
const { VALID: VALID_TARGETS, DEFAULT_TARGETS } = require('../install/targets.js');
|
|
17
|
+
const { dispatchRuntimeCommand } = require('./runtime-commands.js');
|
|
18
|
+
const { usageError } = require('../runtime/cli-result.js');
|
|
19
|
+
|
|
20
|
+
const cmdInstall = require('./commands/install.js');
|
|
21
|
+
const cmdUpdate = require('./commands/update.js');
|
|
22
|
+
const cmdReconcile = require('./commands/reconcile.js');
|
|
23
|
+
const cmdRemove = require('./commands/remove.js');
|
|
24
|
+
const cmdStatus = require('./commands/status.js');
|
|
25
|
+
const cmdTools = require('./commands/tools.js');
|
|
26
|
+
const cmdListBackups = require('./commands/list-backups.js');
|
|
27
|
+
const cmdRollback = require('./commands/rollback.js');
|
|
28
|
+
const cmdSelfUpdate = require('./commands/self-update.js');
|
|
29
|
+
|
|
30
|
+
/** The installer command surface, written down once. The runtime verbs are dispatched separately
|
|
31
|
+
* (see ./runtime-commands) because their namespace is owned by the doflow-run verb table. */
|
|
32
|
+
const COMMANDS = {
|
|
33
|
+
install: cmdInstall,
|
|
34
|
+
update: cmdUpdate,
|
|
35
|
+
reconcile: cmdReconcile,
|
|
36
|
+
remove: cmdRemove,
|
|
37
|
+
status: cmdStatus,
|
|
38
|
+
tools: cmdTools,
|
|
39
|
+
'list-backups': cmdListBackups,
|
|
40
|
+
rollback: cmdRollback,
|
|
41
|
+
'self-update': cmdSelfUpdate,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** "skip all backup protection" must be an explicit, deliberate choice, never a default combo. */
|
|
45
|
+
function assertNoBackupRequiresForce(o ) {
|
|
46
|
+
if (o.noBackup && !o.force) {
|
|
47
|
+
console.error('doflow: --no-backup skips all backup protection and requires --force');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function parseArgs(argv ) {
|
|
53
|
+
const o = { cmd: null, positional: [], targets: [], mcp: null, dryRun: false, force: false, adopt: false,
|
|
54
|
+
noBackup: false, prune: null, global: false, json: false, help: false, version: false,
|
|
55
|
+
tools: null, action: 'status', days: null, slug: null,
|
|
56
|
+
// Explicitly null, not absent. `handleReadinessCommand` declares defaults of `'feature'` and
|
|
57
|
+
// `'default'`, and a JavaScript default parameter fires on `undefined` — so an *absent* key
|
|
58
|
+
// silently reinstated exactly the identity defect readiness.ts fixed by failing closed.
|
|
59
|
+
taskClass: null, taskId: null };
|
|
60
|
+
for (let i = 0; i < argv.length; i++) {
|
|
61
|
+
const a = argv[i];
|
|
62
|
+
switch (a) {
|
|
63
|
+
case '-h': case '--help': o.help = true; break;
|
|
64
|
+
case '-v': case '--version': o.version = true; break;
|
|
65
|
+
case '-n': case '--dry-run': o.dryRun = true; break;
|
|
66
|
+
case '-f': case '--force': o.force = true; break;
|
|
67
|
+
case '--adopt': o.adopt = true; break;
|
|
68
|
+
case '-g': case '--global': o.global = true; break;
|
|
69
|
+
case '--no-backup': o.noBackup = true; break;
|
|
70
|
+
case '--permissions': o.permissions = true; break;
|
|
71
|
+
case '--statusline': o.statusline = true; break;
|
|
72
|
+
case '--json': o.json = true; break;
|
|
73
|
+
case '--check': o.check = true; break;
|
|
74
|
+
// decision --action list: every decision by id, not just the live ones.
|
|
75
|
+
case '--all': o.all = true; break;
|
|
76
|
+
// lifecycle --action overview: the /do maintain view, with a larger list and a pending count.
|
|
77
|
+
case '--maintain': o.maintain = true; break;
|
|
78
|
+
// lifecycle --action release: record the previewed release instead of only previewing it.
|
|
79
|
+
case '--confirm': o.confirm = true; break;
|
|
80
|
+
// followup --action report: the report body comes from stdin instead of --file or --text.
|
|
81
|
+
case '--stdin': o.stdin = true; break;
|
|
82
|
+
// advise --action configure: these are deliberately presence-only switches.
|
|
83
|
+
case '--off': o.off = true; break;
|
|
84
|
+
case '--project': o.project = true; break;
|
|
85
|
+
// goal --action check: record the item as not met (evidence is still required, as the reason).
|
|
86
|
+
case '--unmet': o.unmet = true; break;
|
|
87
|
+
// goal --action link: move a feature that already serves another goal.
|
|
88
|
+
case '--replace': o.replace = true; break;
|
|
89
|
+
// readiness: the caller declares a decision is owed by the user. A flag rather than an
|
|
90
|
+
// inference, because nothing the runtime can see distinguishes "a decision is pending"
|
|
91
|
+
// from "nobody has looked yet", and guessing would be the gate answering unasked.
|
|
92
|
+
case '--user-decision-pending': o.userDecisionPending = true; break;
|
|
93
|
+
case '-t': case '--target': {
|
|
94
|
+
const val = argv[i + 1];
|
|
95
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
96
|
+
o.targets = val.split(',').map((s) => s.trim()).filter(Boolean); i++; break;
|
|
97
|
+
}
|
|
98
|
+
case '--mcp': {
|
|
99
|
+
const val = argv[i + 1];
|
|
100
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
101
|
+
o.mcp = val.split(',').map((s) => s.trim()).filter(Boolean); i++; break;
|
|
102
|
+
}
|
|
103
|
+
case '--tool': {
|
|
104
|
+
const val = argv[i + 1];
|
|
105
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
106
|
+
o.tools = val.split(',').map((s) => s.trim()).filter(Boolean); i++; break;
|
|
107
|
+
}
|
|
108
|
+
case '--action': {
|
|
109
|
+
const val = argv[i + 1];
|
|
110
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
111
|
+
o.action = val; o.actionGiven = true; i++; break;
|
|
112
|
+
}
|
|
113
|
+
case '--task-class': {
|
|
114
|
+
const val = argv[i + 1];
|
|
115
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
116
|
+
o.taskClass = val; i++; break;
|
|
117
|
+
}
|
|
118
|
+
case '--task-id': {
|
|
119
|
+
const val = argv[i + 1];
|
|
120
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
121
|
+
o.taskId = val; i++; break;
|
|
122
|
+
}
|
|
123
|
+
case '--stage': {
|
|
124
|
+
const val = argv[i + 1];
|
|
125
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
126
|
+
o.stage = val; i++; break;
|
|
127
|
+
}
|
|
128
|
+
case '--gate': {
|
|
129
|
+
const val = argv[i + 1];
|
|
130
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
131
|
+
o.gate = val; i++; break;
|
|
132
|
+
}
|
|
133
|
+
case '--node': {
|
|
134
|
+
const val = argv[i + 1];
|
|
135
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
136
|
+
o.node = val; i++; break;
|
|
137
|
+
}
|
|
138
|
+
case '--forced': o.forced = true; break;
|
|
139
|
+
case '--decision': {
|
|
140
|
+
const val = argv[i + 1];
|
|
141
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
142
|
+
o.decision = val; i++; break;
|
|
143
|
+
}
|
|
144
|
+
case '--note': {
|
|
145
|
+
const val = argv[i + 1];
|
|
146
|
+
if (val === undefined) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
147
|
+
o.note = val; i++; break;
|
|
148
|
+
}
|
|
149
|
+
case '--reason': {
|
|
150
|
+
const val = argv[i + 1];
|
|
151
|
+
if (val === undefined) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
152
|
+
o.reason = val; i++; break;
|
|
153
|
+
}
|
|
154
|
+
case '--query': {
|
|
155
|
+
const val = argv[i + 1];
|
|
156
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
157
|
+
o.query = val; i++; break;
|
|
158
|
+
}
|
|
159
|
+
case '-k': case '--top': {
|
|
160
|
+
const val = argv[i + 1];
|
|
161
|
+
const parsed = parseInt(val, 10);
|
|
162
|
+
if (!Number.isFinite(parsed) || parsed < 1) { console.error(`doflow: ${a} expects a positive number`); process.exit(2); }
|
|
163
|
+
o.top = parsed; i++; break;
|
|
164
|
+
}
|
|
165
|
+
case '--role': {
|
|
166
|
+
const val = argv[i + 1];
|
|
167
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a value`); process.exit(1); }
|
|
168
|
+
o.role = val; i++; break;
|
|
169
|
+
}
|
|
170
|
+
case '--days': {
|
|
171
|
+
const val = argv[i + 1];
|
|
172
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a number`); process.exit(2); }
|
|
173
|
+
const parsed = parseInt(val, 10);
|
|
174
|
+
// Run-ledger windows are calendar days; a zero or negative window is a typo, not "all
|
|
175
|
+
// history", and silently reading everything would answer a question nobody asked.
|
|
176
|
+
if (!Number.isFinite(parsed) || parsed < 1) { console.error(`doflow: ${a} expects a positive number of days, got '${val}'`); process.exit(2); }
|
|
177
|
+
o.days = parsed; i++; break;
|
|
178
|
+
}
|
|
179
|
+
case '--prune': {
|
|
180
|
+
const val = argv[i + 1];
|
|
181
|
+
if (val === undefined || val.startsWith('-')) { console.error(`doflow: ${a} requires a number`); process.exit(1); }
|
|
182
|
+
// Digits only: parseInt accepted `5abc` and `1.5`, and 0 is valid (keep every backup).
|
|
183
|
+
if (!/^[0-9]+$/.test(val) || Number(val) > Number.MAX_SAFE_INTEGER) { console.error(`doflow: ${a} requires a non-negative whole number, got '${val}'`); process.exit(2); }
|
|
184
|
+
o.prune = Number(val); i++; break;
|
|
185
|
+
}
|
|
186
|
+
default: {
|
|
187
|
+
// Value-taking arguments of the runtime verbs. Table-driven rather than fifteen more
|
|
188
|
+
// near-identical `case` blocks: the blocks above differ from one another only in the key
|
|
189
|
+
// they write, and copying that shape once per new verb is how one of them eventually gets
|
|
190
|
+
// its validation subtly wrong.
|
|
191
|
+
const runtime = parseRuntimeFlag(a, argv, i, o);
|
|
192
|
+
if (runtime !== null) { i = runtime; break; }
|
|
193
|
+
if (a.startsWith('-')) { console.error(`doflow: unknown flag '${a}'`); process.exit(1); }
|
|
194
|
+
else if (!o.cmd) o.cmd = a;
|
|
195
|
+
else o.positional.push(a);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return o;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Single-value arguments of the runtime verbs → the option key each one writes. */
|
|
203
|
+
const RUNTIME_STRING_FLAGS = new Map([
|
|
204
|
+
// `scaffold`. The resolver's own ambiguous-feature error tells the caller to "re-run with
|
|
205
|
+
// --slug=<chosen>"; without this flag that hint would name an argument this CLI rejects.
|
|
206
|
+
['--slug', 'slug'],
|
|
207
|
+
['--rationale', 'rationale'], // classify: why this class was proposed · decision --action add: why it was decided
|
|
208
|
+
['--request', 'request'], // classify: request text for an advisory second opinion
|
|
209
|
+
['--request-file', 'requestFile'], // classify: request text read from a file
|
|
210
|
+
// decision --action add. `--statement`, `--stage`, `--slug` and `--batch` above are shared.
|
|
211
|
+
['--topic', 'topic'], // the subject key a decision is live on
|
|
212
|
+
['--channel', 'channel'], // question | gate | prompt | default | resolution
|
|
213
|
+
['--supersedes', 'supersedes'], // comma-separated DEC-### ids this decision replaces
|
|
214
|
+
['--refs', 'refs'], // comma-separated ids the decision touches, e.g. FR-001,IC-002
|
|
215
|
+
['--source', 'source'], // where the decision was stated, e.g. design/design-02-question.md#question-1
|
|
216
|
+
// followup and lifecycle (feature 046). `--statement`, `--stage`, `--slug`, `--batch`, `--reason`,
|
|
217
|
+
// `--channel`, `--state`, `--source`, `--intent`, `--task-class` and `--task-id` above are shared.
|
|
218
|
+
['--ids', 'ids'], // followup: comma-separated FU-xxxxxx ids to take, settle or promote
|
|
219
|
+
['--as', 'as'], // followup --action settle: kept | dismissed | fix | done
|
|
220
|
+
['--evidence', 'evidence'], // followup --action settle --as done: what shows it was done
|
|
221
|
+
['--title', 'title'], // followup --action promote: the new intent's title
|
|
222
|
+
['--release', 'release'], // followup --action add --source release: the release tag
|
|
223
|
+
['--take', 'take'], // lifecycle --action init: comma-separated FU ids the feature takes
|
|
224
|
+
['--goal', 'goal'], // lifecycle --action init: the goal the feature serves
|
|
225
|
+
['--since', 'since'], // lifecycle --action overview --maintain: ISO time the pass started
|
|
226
|
+
['--file', 'file'], // followup --action report: the report body, read as text (at most 16 MiB)
|
|
227
|
+
['--text', 'text'], // followup --action report: the report body inline (a value starting with - needs --text=...) · goal --action item: the checklist item
|
|
228
|
+
['--tag', 'tag'], // lifecycle --action release: the version tag (`--version` is the CLI's own flag)
|
|
229
|
+
['--fp', 'fp'], // failure --action settle: the 16 hex characters of an entry
|
|
230
|
+
['--set', 'set'], // failure --action capture: on | off
|
|
231
|
+
['--proposed-by', 'proposedBy'], // classify: which worker proposed it
|
|
232
|
+
['--calling-skill', 'callingSkill'], // classify: which skill is asking, for the fit check
|
|
233
|
+
['--intent', 'intent'], // route: the information need being resolved
|
|
234
|
+
['--query', 'query'], // route: what the resolved provider would be asked
|
|
235
|
+
['--statement', 'statement'], // claim --action add
|
|
236
|
+
['--claim-id', 'claimId'], // claim --action link
|
|
237
|
+
['--evidence-id', 'evidenceId'], // claim --action link · evidence --action supersede
|
|
238
|
+
['--relation', 'relation'], // claim --action link: supports | contradicts
|
|
239
|
+
['--role', 'role'], // claim --action add: the claim's relationship to the task, e.g. root-cause
|
|
240
|
+
['--replaced-by', 'replacedBy'], // claim --action supersede: the claim replacing this one ·
|
|
241
|
+
// evidence --action supersede: the evidence replacing this one
|
|
242
|
+
['--kind', 'kind'], // evidence --action add: one of VALID_EVIDENCE_KINDS · advise --action ask
|
|
243
|
+
['--server', 'server'], // advise: MCP server for the mcp-need kind
|
|
244
|
+
['--state-file', 'stateFile'], // advise: request state from a UTF-8 file
|
|
245
|
+
['--questions-file', 'questionsFile'], // advise: ad hoc question set JSON
|
|
246
|
+
['--static', 'staticAnswer'], // advise: explicit caller answer for comparison
|
|
247
|
+
['--provenance', 'provenance'], // evidence --action add: extracted | inferred | asserted
|
|
248
|
+
['--provider', 'provider'], // evidence --action add: source.provider
|
|
249
|
+
['--capability', 'capability'], // evidence --action add: source.capability
|
|
250
|
+
['--locator', 'locator'], // evidence --action add: 'path/file[:line]' or a URI
|
|
251
|
+
['--content', 'content'], // evidence --action add: the fact or the analysis itself
|
|
252
|
+
['--establishes', 'establishes'], // evidence --action add: requirement id(s) this item proves, comma-separated
|
|
253
|
+
['--observed-command', 'observedCommand'], // evidence --action add: the command a test-result/runtime-observation ran
|
|
254
|
+
['--batch', 'batchPath'], // evidence --action add: a stage's batch file, or '-'
|
|
255
|
+
['--verification-plan', 'verificationPlan'], // readiness: how success will be established
|
|
256
|
+
['--mode', 'mode'], // readiness: execution mode, workflow (default) | standalone
|
|
257
|
+
['--scope', 'scope'], // readiness: the stated scope boundary; verify: the declared
|
|
258
|
+
// change scope, <path>[,<path>...], unioned with the plan's bound
|
|
259
|
+
['--invariants', 'invariants'], // readiness: the invariants a refactor must preserve
|
|
260
|
+
['--objective', 'objective'], // context-pack
|
|
261
|
+
['--stage-id', 'stageId'], // research-request: active feature stage
|
|
262
|
+
['--question', 'question'], // research-request: external question
|
|
263
|
+
['--blocking', 'blocking'], // research-request: true | false
|
|
264
|
+
['--request-id', 'requestId'], // research-request: request to resolve
|
|
265
|
+
['--outcome', 'researchOutcome'], // research-request: answered | unresolved
|
|
266
|
+
['--gap', 'gap'], // research-request: unresolved reason
|
|
267
|
+
['--stage', 'stage'], // retrieval-plan: the stage id declaring the plan;
|
|
268
|
+
// outcome: the stage writing it, refused unless terminal
|
|
269
|
+
['--state', 'state'], // outcome: the terminal state being recorded
|
|
270
|
+
['--result', 'result'], // orchestrate complete-stage: the stage's own outcome, passed | failed (omit → unverified)
|
|
271
|
+
// outcome: the verdicts the run saw, stated by it and validated against the vocabulary the
|
|
272
|
+
// owning module exports. Recording an outcome never re-evaluates readiness and never re-runs
|
|
273
|
+
// verification, so these arrive as statements rather than as measurements taken here.
|
|
274
|
+
['--readiness', 'readiness'],
|
|
275
|
+
['--verification', 'verification'],
|
|
276
|
+
['--risk', 'risk'], // verify: risk level selecting the required tiers
|
|
277
|
+
['--pick-id', 'pickId'], // advise --action outcome: retained pick to label
|
|
278
|
+
['--actual', 'actual'], // advise --action outcome: observed outcome
|
|
279
|
+
['--model', 'model'], // advise --action configure: installed decision-capable model
|
|
280
|
+
['--endpoint', 'endpoint'], // advise --action configure: loopback Ollama endpoint
|
|
281
|
+
['--owner', 'owner'], // brief-tools: the agent type the brief is for
|
|
282
|
+
['--tier', 'tier'], // brief-tools: the task line's tier (light | standard | frontier)
|
|
283
|
+
['--harness', 'harness'], // brief-tools: the harness the brief is for
|
|
284
|
+
['--heading-level', 'headingLevel'], // brief-tools: 2 (default) or 3
|
|
285
|
+
['--tasks', 'tasks'], // brief-tools: comma-separated plan task ids for tier advice
|
|
286
|
+
['--plan-path', 'planPath'], // verify: a feature plan.md whose doflow-verification
|
|
287
|
+
// block overrides manifest detection. Without this the
|
|
288
|
+
// override was implemented but unreachable (FR-011).
|
|
289
|
+
['--verification-input', 'verificationInput'], // verify: manifest JSON file for explicit structuralChecks/requirements (IC-022)
|
|
290
|
+
['--verification-phase', 'verificationPhase'], // verify: postimplementation (IC-022)
|
|
291
|
+
['--baseline-ref', 'baselineRef'], // verify: explicit ancestor commit or ref to measure change against (IC-022)
|
|
292
|
+
['--error', 'errorMessage'], // recover: the failure text to classify
|
|
293
|
+
['--agent', 'agent'], // recover: which agent produced the failure
|
|
294
|
+
['--task', 'task'], // task-attempt: the plan task id, e.g. A.1
|
|
295
|
+
['--token', 'token'], // task-attempt finish|release: the fencing token claim returned
|
|
296
|
+
]);
|
|
297
|
+
|
|
298
|
+
/** Repeatable arguments — each occurrence appends rather than replaces. */
|
|
299
|
+
const RUNTIME_LIST_FLAGS = new Map([
|
|
300
|
+
['--mcp-outcome', 'mcpOutcome'], // orchestrate handoff: <server>=<outcome>, one per MCP server the step names
|
|
301
|
+
['--failed-check', 'failedChecks'], // recover: check names outrank the error prose (see recovery.js)
|
|
302
|
+
// retrieval-plan: the intents a stage declares, or (on report) the ones it states it reached.
|
|
303
|
+
// Repeatable as well as comma-separated, because a plan assembled a need at a time should not
|
|
304
|
+
// have to be re-spelled as one string to be declared.
|
|
305
|
+
['--need', 'need'],
|
|
306
|
+
['--path', 'paths'], // leak-scan: the files to scan, one per occurrence
|
|
307
|
+
['--exclude', 'exclude'], // leak-scan: extra path segments to skip · lifecycle --action release: slugs left out
|
|
308
|
+
['--feature', 'feature'], // lifecycle --action release: a feature slug to add, one per occurrence
|
|
309
|
+
['--item', 'item'], // goal --action add: a checklist item, one per occurrence · goal --action check: the one item id (C3)
|
|
310
|
+
]);
|
|
311
|
+
|
|
312
|
+
/** Non-negative integer arguments. */
|
|
313
|
+
const RUNTIME_INT_FLAGS = new Map([
|
|
314
|
+
['--iteration', 'iteration'], // recover: retries already spent, bounding the retry budget
|
|
315
|
+
['--observed-exit', 'observedExit'], // evidence --action add: exit status of the observed command (0 is meaningful)
|
|
316
|
+
]);
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Reads one runtime-verb argument, in either `--flag value` or `--flag=value` spelling.
|
|
320
|
+
*
|
|
321
|
+
* Both spellings are accepted because the messages users copy from are not consistent about it:
|
|
322
|
+
* `do-paths.sh`'s own hint says `--slug=<chosen>` while the rest of this CLI is space-separated,
|
|
323
|
+
* and rejecting either would punish following the instructions.
|
|
324
|
+
*
|
|
325
|
+
* Returns the new loop index, or null when `arg` is not a runtime flag.
|
|
326
|
+
*/
|
|
327
|
+
function parseRuntimeFlag(arg , argv , i , o ) {
|
|
328
|
+
const eq = arg.indexOf('=');
|
|
329
|
+
const name = eq === -1 ? arg : arg.slice(0, eq);
|
|
330
|
+
// A score-shaped flag is refused by name rather than falling through to "unknown flag", which
|
|
331
|
+
// reads as "not built yet" and invites someone to build it. The name set and the reason both
|
|
332
|
+
// come from the evidence write boundary (src/runtime/cli.js), so argv and a --batch JSON file
|
|
333
|
+
// are refused by one rule with two enforcement points rather than two rules.
|
|
334
|
+
const camel = name.replace(/^--/, '').replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
335
|
+
if (EVIDENCE_SCORE_FIELDS.has(camel)) { console.error(`doflow: ${scoreFieldRefusal(name)}`); process.exit(2); }
|
|
336
|
+
const inline = eq === -1 ? null : arg.slice(eq + 1);
|
|
337
|
+
const key = RUNTIME_STRING_FLAGS.get(name) || RUNTIME_LIST_FLAGS.get(name) || RUNTIME_INT_FLAGS.get(name);
|
|
338
|
+
if (!key) return null;
|
|
339
|
+
|
|
340
|
+
let value = inline;
|
|
341
|
+
let next = i;
|
|
342
|
+
if (value === null) {
|
|
343
|
+
value = argv[i + 1];
|
|
344
|
+
// A value that itself starts with `-` is far more likely the next flag than a deliberate
|
|
345
|
+
// argument, and consuming it would silently drop that flag.
|
|
346
|
+
// A bare `-` is the conventional name for stdin, not a flag, and the help advertises
|
|
347
|
+
// `--batch <file|->`. Rejecting it made the documented spelling exit 2 while only `--batch=-`
|
|
348
|
+
// worked — a help text endorsing a form the parser refuses.
|
|
349
|
+
const isStdin = value === '-';
|
|
350
|
+
if (value === undefined || (value.startsWith('-') && !isStdin)) { console.error(`doflow: ${name} requires a value`); process.exit(2); }
|
|
351
|
+
next = i + 1;
|
|
352
|
+
}
|
|
353
|
+
if (value === '') { console.error(`doflow: ${name} requires a value`); process.exit(2); }
|
|
354
|
+
|
|
355
|
+
if (RUNTIME_INT_FLAGS.has(name)) {
|
|
356
|
+
const parsed = parseInt(value, 10);
|
|
357
|
+
if (!Number.isFinite(parsed) || parsed < 0) { console.error(`doflow: ${name} expects a non-negative integer, got '${value}'`); process.exit(2); }
|
|
358
|
+
o[key] = parsed;
|
|
359
|
+
} else if (RUNTIME_LIST_FLAGS.has(name)) {
|
|
360
|
+
// --exclude alone also accepts a comma-joined value (`--exclude bin,src,core`), not just the
|
|
361
|
+
// repeatable form (`--exclude bin --exclude src`) every other list flag uses — the two used to
|
|
362
|
+
// be parsed by two separate code paths (a dedicated switch case handling only the space
|
|
363
|
+
// spelling's comma-splitting, this generic path handling both spellings but never splitting),
|
|
364
|
+
// so `--exclude=bin,src` silently excluded nothing while `--exclude bin,src` worked. One path,
|
|
365
|
+
// both spellings, same behavior now.
|
|
366
|
+
const parts = name === '--exclude' ? value.split(',').map((s ) => s.trim()).filter(Boolean) : [value];
|
|
367
|
+
(o[key] = o[key] || []).push(...parts);
|
|
368
|
+
} else if (name === '--evidence-id' && o.cmd === 'research-request') {
|
|
369
|
+
(o.evidenceIds = o.evidenceIds || []).push(value);
|
|
370
|
+
} else {
|
|
371
|
+
o[key] = value;
|
|
372
|
+
}
|
|
373
|
+
return next;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const HELP = `doflow — DoFlow config installer
|
|
377
|
+
|
|
378
|
+
Usage: doflow <command> [path] [options]
|
|
379
|
+
|
|
380
|
+
Commands:
|
|
381
|
+
install [path] Install configs to target tools (use --dry-run to preview)
|
|
382
|
+
update Incremental update of changed files only
|
|
383
|
+
reconcile Converge observed state onto the doflow.lock pin (drift report + heal)
|
|
384
|
+
status Show resolved context + installed state from manifest (--json for scripting)
|
|
385
|
+
rollback [id] Restore from a backup (interactive pick if id omitted)
|
|
386
|
+
remove [path] Remove only lifecycle-owned native resources
|
|
387
|
+
list-backups List available backups
|
|
388
|
+
self-update git pull + reinstall
|
|
389
|
+
tools Inspect or manage registered external tools
|
|
390
|
+
capabilities Show registered abstract capabilities and resolved providers
|
|
391
|
+
doctor System health and capability smoke check diagnostics
|
|
392
|
+
readiness Evaluate task readiness contract (--task-class, --task-id, both required)
|
|
393
|
+
evidence Record a stage's evidence batch, or inspect what is recorded (--task-id)
|
|
394
|
+
claim Record a claim, link evidence to it, or list them (--task-id, --action)
|
|
395
|
+
context-pack Compile a task's evidence and claims into a context block (--task-id)
|
|
396
|
+
retrieval-plan Declare a stage's information needs, then report every declared item
|
|
397
|
+
outcome Record a task's terminal state with its basis, or show it (--task-id)
|
|
398
|
+
classify Validate a proposed task class and return its workflow (--task-class)
|
|
399
|
+
workflow Resolve a task class to its stages, gates and readiness templates
|
|
400
|
+
orchestrate Start or resume a run: complete stages, decide gates (--action)
|
|
401
|
+
research-request Open, list or resolve a feature-stage research question (--task-id)
|
|
402
|
+
task-attempt Claim, finish, release or read the attempts on a plan's tasks (--action, --slug)
|
|
403
|
+
retrieve BM25 search over the installed guidance tree (--query)
|
|
404
|
+
model-role Resolve a model role to ranked provider candidates (--role)
|
|
405
|
+
advise Route decision questions to the configured local model (--action)
|
|
406
|
+
brief-tools Tier, tools and report-format block for a dispatch brief (--owner)
|
|
407
|
+
route Resolve an information need to a healthy provider (--intent)
|
|
408
|
+
verify Compile the verification contract and report against it (--task-id)
|
|
409
|
+
recover Classify a verification failure and plan the bounded retry (--error)
|
|
410
|
+
trace Trajectory of the current or most recent workflow (run ledger)
|
|
411
|
+
stats Aggregate local run-ledger usage
|
|
412
|
+
indicators Per-stage and per-gate timings from the orchestration record
|
|
413
|
+
discover Missed capability opportunities in recorded runs
|
|
414
|
+
inventory Shadowed copies, drift and unmanaged files across both install scopes
|
|
415
|
+
storage Report stored data and retention bounds (--action report|prune|upkeep)
|
|
416
|
+
scaffold Emit the reviewable code scaffold the active feature's artifacts imply
|
|
417
|
+
decision Register, list or compact the active feature's decisions (--action init|add|list|compact)
|
|
418
|
+
followup Record, list, take, settle, promote or report what a feature left unfinished (--action add|list|take|settle|promote|report)
|
|
419
|
+
lifecycle Open follow-ups, feature tracking, releases and status for the project (--action overview|init|release|status|merged)
|
|
420
|
+
goal Add, check, link, list or close a goal and its checklist (--action add|item|check|link|list|done)
|
|
421
|
+
failure List, settle or switch off the failures DoFlow captured on this machine (--action list|settle|capture)
|
|
422
|
+
(a value beginning with '-' must be written --flag=value)
|
|
423
|
+
leak-scan Report DoFlow-internal identifiers in shipped files (--path, repeatable)
|
|
424
|
+
|
|
425
|
+
Scope (mutually exclusive — global wins if both given):
|
|
426
|
+
-g, --global Install to each target's user-level directory under \$HOME (e.g. \$HOME/.claude),
|
|
427
|
+
and the shared runtime to \$HOME/.doflow
|
|
428
|
+
[path] Project-scoped install root (default: '.', i.e. cwd); e.g.
|
|
429
|
+
'doflow install ../my-app' -> each target's project files, plus
|
|
430
|
+
../my-app/.doflow
|
|
431
|
+
(rollback's one positional slot is the backup id instead — its scope is
|
|
432
|
+
always -g or cwd, no custom project path)
|
|
433
|
+
|
|
434
|
+
Options:
|
|
435
|
+
-t, --target <list> Comma-separated: ${VALID_TARGETS.join(',')} (default: ${DEFAULT_TARGETS.join(',')})
|
|
436
|
+
--mcp <list> Comma-separated MCP server names, or all or none, for every targeted
|
|
437
|
+
harness that takes MCP servers (all but gemini). Default: none, or the
|
|
438
|
+
selection a harness has recorded in doflow.lock, or the servers an
|
|
439
|
+
installed harness already has; a real terminal prompts on install.
|
|
440
|
+
Recorded per harness.
|
|
441
|
+
-n, --dry-run Preview without writing
|
|
442
|
+
-f, --force Skip confirmation prompts
|
|
443
|
+
--adopt Record ownership of resources that exist with no ledger record, instead
|
|
444
|
+
of refusing them. Not --force: a resource whose record disagrees with
|
|
445
|
+
the file is still a conflict. For a tree installed before the neutral
|
|
446
|
+
ledger existed, which nothing else can re-adopt
|
|
447
|
+
--no-backup Skip backup (requires --force; ignored by rollback's safety snapshot)
|
|
448
|
+
--prune <N> Keep the N newest backups after install or update (default 3; 0 keeps all)
|
|
449
|
+
--days <N> Run-ledger window in calendar days (trace, stats, discover)
|
|
450
|
+
--slug <name> Scaffold this feature instead of the branch-resolved active one
|
|
451
|
+
|
|
452
|
+
Runtime verb arguments (accept --flag value or --flag=value):
|
|
453
|
+
--task-class classify, workflow, readiness, context-pack, outcome --action record
|
|
454
|
+
--task-id readiness, evidence, claim, context-pack, retrieval-plan, outcome, verify, advise
|
|
455
|
+
--action claim: list|add|link|retract|supersede · evidence: list|add|supersede
|
|
456
|
+
verify: report|contract · retrieval-plan: declare|report
|
|
457
|
+
outcome: record|show · advise: ask|outcome|configure · tools: see above
|
|
458
|
+
followup: add|list|take|settle|promote|report
|
|
459
|
+
task-attempt: claim|finish|release|status
|
|
460
|
+
lifecycle: overview|init|release|status|merged
|
|
461
|
+
goal: add|item|check|link|list|done
|
|
462
|
+
failure: list|settle|capture
|
|
463
|
+
--task, --token, --owner, --mode,
|
|
464
|
+
--result, --evidence-id, --reason task-attempt (claim: --task --owner --mode manual|sequential|subagent;
|
|
465
|
+
finish: --task --token --result COMPLETED|BLOCKED|ABANDONED|INCONCLUSIVE
|
|
466
|
+
[--evidence-id]; release: --task --token --reason)
|
|
467
|
+
--rationale, --proposed-by, --calling-skill classify
|
|
468
|
+
--request <text>, --request-file <file> classify (mutually exclusive; optional second opinion)
|
|
469
|
+
--intent, --query, --check route
|
|
470
|
+
--statement, --claim-id,
|
|
471
|
+
--evidence-id, --relation claim
|
|
472
|
+
--kind, --provenance, --provider,
|
|
473
|
+
--capability, --locator, --content evidence --action add (one item)
|
|
474
|
+
--batch <file|-> evidence --action add (a stage's JSON batch)
|
|
475
|
+
--evidence-id, --replaced-by evidence --action supersede (retire one item, point
|
|
476
|
+
forward to the item that replaces it)
|
|
477
|
+
--verification-plan, --scope,
|
|
478
|
+
--invariants,
|
|
479
|
+
--user-decision-pending readiness: inputs the caller states rather than
|
|
480
|
+
evidence establishes; reported back as such
|
|
481
|
+
--objective context-pack
|
|
482
|
+
--need <intent[,intent]>,
|
|
483
|
+
--stage retrieval-plan (--need is repeatable), outcome
|
|
484
|
+
--mcp-outcome <server>=<outcome> orchestrate --action handoff, repeatable: used | nothing-usable |
|
|
485
|
+
skipped:<reason> | unavailable (a server left out only warns)
|
|
486
|
+
--state <COMPLETED|BLOCKED|
|
|
487
|
+
ABANDONED|INCONCLUSIVE>,
|
|
488
|
+
--readiness, --verification outcome --action record
|
|
489
|
+
--risk, --plan-path, --scope,
|
|
490
|
+
--verification-input,
|
|
491
|
+
--verification-phase,
|
|
492
|
+
--baseline-ref verify
|
|
493
|
+
--owner, --tier, --harness, --tasks <id,...>,
|
|
494
|
+
--heading-level 2|3 brief-tools (--slug names the feature whose run gives the stage)
|
|
495
|
+
--kind, --state, --state-file,
|
|
496
|
+
--questions-file, --server,
|
|
497
|
+
--static advise --action ask
|
|
498
|
+
--pick-id, --actual advise --action outcome
|
|
499
|
+
--model, --endpoint, --project,
|
|
500
|
+
--off advise --action configure
|
|
501
|
+
--path, --exclude (repeatable) leak-scan
|
|
502
|
+
--ids, --as, --evidence, --title,
|
|
503
|
+
--release, --source, --channel followup (add, list, take, settle, promote)
|
|
504
|
+
--file <path|->, --stdin, --text,
|
|
505
|
+
--feature followup --action report (the body comes from exactly one; - is stdin)
|
|
506
|
+
--take, --goal, --intent, --since,
|
|
507
|
+
--maintain lifecycle (overview, init)
|
|
508
|
+
--goal, --statement, --item (repeatable),
|
|
509
|
+
--text, --evidence, --unmet, --slug,
|
|
510
|
+
--replace, --reason, --channel goal (add, item, check, link, list, done)
|
|
511
|
+
--tag, --confirm, --feature,
|
|
512
|
+
--exclude (repeatable), --reason lifecycle (release, merged)
|
|
513
|
+
--fp, --as, --reason, --set, --all failure (list, settle, capture)
|
|
514
|
+
--error, --failed-check,
|
|
515
|
+
--iteration, --agent recover
|
|
516
|
+
--json Machine-readable output (status)
|
|
517
|
+
|
|
518
|
+
External tools:
|
|
519
|
+
--tool <list> Comma-separated: rtk,graphify (required outside an interactive terminal)
|
|
520
|
+
--action <name> status (default), install, update, or uninstall
|
|
521
|
+
--force is intentionally unavailable: every mutation is separately confirmed
|
|
522
|
+
-h, --help Show help
|
|
523
|
+
-v, --version Show version`;
|
|
524
|
+
|
|
525
|
+
// The names a failure may be recorded under (IC-011): the installer table and the verbs HELP lists,
|
|
526
|
+
// so a record can only ever carry a name from DoFlow's own tables and never an argument value.
|
|
527
|
+
const COMMAND_NAMES = new Set([...Object.keys(COMMANDS), ...[...HELP.matchAll(/^ ([a-z][a-z-]*) {2,}\S/gm)].map((m) => m[1])]);
|
|
528
|
+
|
|
529
|
+
/** `name` when it is one of DoFlow's own command names, else `unknown`. */
|
|
530
|
+
function commandName(name ) { return typeof name === 'string' && COMMAND_NAMES.has(name) ? name : 'unknown'; }
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Run one CLI invocation. Same behavior as the pre-extraction monolith's main(): --version and
|
|
534
|
+
* --help answer first, --no-backup-without-force is refused, then the command resolves either
|
|
535
|
+
* through the installer table above or through the runtime-verb dispatcher.
|
|
536
|
+
*/
|
|
537
|
+
async function main(argv ) {
|
|
538
|
+
const o = parseArgs(argv);
|
|
539
|
+
if (o.version) { console.log(pkg.version); return; }
|
|
540
|
+
if (o.help || !o.cmd) { console.log(HELP); return; }
|
|
541
|
+
assertNoBackupRequiresForce(o);
|
|
542
|
+
if (o.cmd === 'classify' && o.request !== undefined && o.requestFile !== undefined) {
|
|
543
|
+
return usageError('classify', '--request and --request-file are mutually exclusive; provide only one.', o.json);
|
|
544
|
+
}
|
|
545
|
+
try {
|
|
546
|
+
const handler = COMMANDS[o.cmd];
|
|
547
|
+
if (handler) return handler(o);
|
|
548
|
+
return await dispatchRuntimeCommand(o);
|
|
549
|
+
} catch (error ) {
|
|
550
|
+
// Recorded silently when it is a programming error (IC-016); the output and exit status below
|
|
551
|
+
// are the same whether or not anything was written.
|
|
552
|
+
// Required here, not at load, so a CLI whose failure modules cannot be loaded still runs as today.
|
|
553
|
+
try { require('../runtime/failure/capture.js').captureError(error, { command: commandName(o.cmd), exit: 1 }); } catch { /* best-effort */ }
|
|
554
|
+
// A lifecycle apply/remove can throw mid-mutation (fs error, TOCTOU ownership mismatch on a
|
|
555
|
+
// multi-harness run) — surface a clean, actionable message instead of a raw stack trace, and
|
|
556
|
+
// point at the recovery record applyLifecycle already wrote before rethrowing.
|
|
557
|
+
console.error(`[ERROR] ${error.message}`);
|
|
558
|
+
// Only the commands that actually mutate native resources can leave a partial application.
|
|
559
|
+
// Printing this after a rejected `readiness --task-id` or any other read-only query told the
|
|
560
|
+
// user to go inspect recovery records for a run that never wrote anything.
|
|
561
|
+
if (['install', 'update', 'remove', 'rollback', 'self-update', 'tools'].includes(o.cmd)) {
|
|
562
|
+
console.error('[ERROR] Some native resources may be partially applied — check .doflow/state/recovery/ (or ~/.doflow/state/recovery/ for -g) for the latest record before retrying.');
|
|
563
|
+
}
|
|
564
|
+
process.exit(1);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
module.exports = { main, COMMANDS, commandName };
|