@khoavu882/doflow 0.0.0-stage → 2.0.0-beta.3
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 +1057 -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 +46 -4
- package/src/adapters/antigravity/index.ts +631 -0
- package/src/adapters/claude/index.ts +548 -0
- package/src/adapters/claude/mcp.ts +94 -0
- package/src/adapters/codex/agents.ts +208 -0
- package/src/adapters/codex/config.ts +272 -0
- package/src/adapters/codex/hooks.ts +203 -0
- package/src/adapters/codex/index.ts +707 -0
- package/src/adapters/codex/mcp.ts +271 -0
- package/src/adapters/codex/native-projection.ts +34 -0
- package/src/adapters/copilot/index.ts +413 -0
- package/src/adapters/copy-tree.ts +620 -0
- package/src/adapters/gemini/hooks.ts +210 -0
- package/src/adapters/gemini/index.ts +390 -0
- package/src/adapters/hook-commands.ts +60 -0
- package/src/adapters/index.ts +106 -0
- package/src/adapters/kiro/index.ts +310 -0
- package/src/adapters/mcp-entries.ts +331 -0
- package/src/adapters/opencode/index.ts +466 -0
- package/src/adapters/pi/index.ts +279 -0
- package/src/adapters/pi/json-members.ts +185 -0
- package/src/adapters/pi/mcp.ts +373 -0
- package/src/adapters/resolve-source.ts +19 -0
- package/src/cli/commands/install.ts +218 -0
- package/src/cli/commands/list-backups.ts +21 -0
- package/src/cli/commands/reconcile.ts +120 -0
- package/src/cli/commands/remove.ts +82 -0
- package/src/cli/commands/rollback.ts +172 -0
- package/src/cli/commands/self-update.ts +33 -0
- package/src/cli/commands/status.ts +138 -0
- package/src/cli/commands/tools.ts +92 -0
- package/src/cli/commands/update.ts +162 -0
- package/src/cli/index.ts +568 -0
- package/src/cli/runtime-commands.ts +281 -0
- package/src/cli/shared.ts +218 -0
- package/src/helper/bash-helper.ts +34 -0
- package/src/helper/git.ts +24 -0
- package/src/helper/guardrails.ts +49 -0
- package/src/helper/harness-paths.ts +140 -0
- package/src/helper/marker-merge.ts +116 -0
- package/src/helper/prompt.ts +61 -0
- package/src/helper/repo-root.ts +29 -0
- package/src/helper/settings-merge.ts +151 -0
- package/src/helper/settings-scope.ts +33 -0
- package/src/helper/toml.ts +244 -0
- package/src/install/backup-set.ts +149 -0
- package/src/install/backup.ts +724 -0
- package/src/install/context.ts +58 -0
- package/src/install/manifest.ts +145 -0
- package/src/install/mcp.ts +254 -0
- package/src/install/paths.ts +84 -0
- package/src/install/targets.ts +90 -0
- package/src/install/tool-lifecycle.ts +151 -0
- package/src/lifecycle/bash-availability.ts +25 -0
- package/src/lifecycle/index.ts +812 -0
- package/src/lifecycle/mcp-index.ts +28 -0
- package/src/lifecycle/policies.ts +73 -0
- package/src/lifecycle/view.ts +175 -0
- package/src/registry/index.ts +611 -0
- package/src/release/sync-plugin-versions.ts +66 -0
- package/src/runtime/advice/cli.ts +283 -0
- package/src/runtime/advice/client.ts +324 -0
- package/src/runtime/advice/config.ts +189 -0
- package/src/runtime/advice/doctor.ts +169 -0
- package/src/runtime/advice/endpoint-guard.ts +134 -0
- package/src/runtime/advice/kinds.ts +154 -0
- package/src/runtime/advice/providers/ollama-systemone.ts +209 -0
- package/src/runtime/advice/record.ts +166 -0
- package/src/runtime/advice/registry.ts +170 -0
- package/src/runtime/advice/strength.ts +66 -0
- package/src/runtime/brief-tools.ts +342 -0
- package/src/runtime/c4-project.ts +371 -0
- package/src/runtime/capability-router.ts +484 -0
- package/src/runtime/checkouts.ts +170 -0
- package/src/runtime/claims.ts +468 -0
- package/src/runtime/cli-result.ts +55 -0
- package/src/runtime/cli.ts +678 -0
- package/src/runtime/command-detect.ts +516 -0
- package/src/runtime/context-pack.ts +492 -0
- package/src/runtime/decision-register.ts +493 -0
- package/src/runtime/evidence-ledger.ts +338 -0
- package/src/runtime/failure/capture.ts +272 -0
- package/src/runtime/failure/classifier.ts +68 -0
- package/src/runtime/failure/cli.ts +178 -0
- package/src/runtime/failure/home.ts +64 -0
- package/src/runtime/failure/store.ts +226 -0
- package/src/runtime/feature-resolve.ts +79 -0
- package/src/runtime/freshness.ts +177 -0
- package/src/runtime/health.ts +863 -0
- package/src/runtime/history-compactor.ts +237 -0
- package/src/runtime/implementation-gate.ts +321 -0
- package/src/runtime/inventory/coverage.ts +218 -0
- package/src/runtime/inventory/identity.ts +65 -0
- package/src/runtime/inventory/index.ts +705 -0
- package/src/runtime/inventory/precedence.ts +134 -0
- package/src/runtime/inventory/read-scopes.ts +131 -0
- package/src/runtime/inventory/siblings.ts +192 -0
- package/src/runtime/knowledge/chunker.ts +124 -0
- package/src/runtime/knowledge/hybrid.ts +149 -0
- package/src/runtime/knowledge/index-store.ts +145 -0
- package/src/runtime/knowledge/retrieval.ts +194 -0
- package/src/runtime/leak-scan.ts +185 -0
- package/src/runtime/lifecycle/cli.ts +276 -0
- package/src/runtime/lifecycle/event-store.ts +340 -0
- package/src/runtime/lifecycle/fold.ts +353 -0
- package/src/runtime/lifecycle/followup.ts +432 -0
- package/src/runtime/lifecycle/goal.ts +249 -0
- package/src/runtime/lifecycle/intent-writer.ts +86 -0
- package/src/runtime/lifecycle/overview.ts +292 -0
- package/src/runtime/lifecycle/release.ts +241 -0
- package/src/runtime/lifecycle/report-store.ts +221 -0
- package/src/runtime/lifecycle/retention.ts +212 -0
- package/src/runtime/lifecycle/root.ts +71 -0
- package/src/runtime/lifecycle/status.ts +353 -0
- package/src/runtime/lifecycle/store-upkeep.ts +393 -0
- package/src/runtime/locator-resolve.ts +158 -0
- package/src/runtime/mask.ts +210 -0
- package/src/runtime/mcp-consultations.ts +412 -0
- package/src/runtime/mcp-reach.ts +157 -0
- package/src/runtime/model-router.ts +153 -0
- package/src/runtime/outcome.ts +467 -0
- package/src/runtime/reach.ts +148 -0
- package/src/runtime/readiness-record.ts +150 -0
- package/src/runtime/readiness.ts +435 -0
- package/src/runtime/recovery.ts +282 -0
- package/src/runtime/research-request.ts +231 -0
- package/src/runtime/retrieval-plan.ts +578 -0
- package/src/runtime/scaffold/artifacts.ts +217 -0
- package/src/runtime/scaffold/fingerprint.ts +56 -0
- package/src/runtime/scaffold/generate.ts +911 -0
- package/src/runtime/scaffold/languages.ts +245 -0
- package/src/runtime/storage/cli.ts +64 -0
- package/src/runtime/storage/engine.ts +249 -0
- package/src/runtime/storage/registry.ts +130 -0
- package/src/runtime/storage/roots.ts +63 -0
- package/src/runtime/storage/rules.ts +282 -0
- package/src/runtime/storage/upkeep.ts +243 -0
- package/src/runtime/storage/work-status.ts +326 -0
- package/src/runtime/task-attempts.ts +415 -0
- package/src/runtime/task-classifier.ts +550 -0
- package/src/runtime/task-scope.ts +130 -0
- package/src/runtime/task-state.ts +176 -0
- package/src/runtime/trace/indicators.ts +235 -0
- package/src/runtime/trace/ledger.ts +626 -0
- package/src/runtime/trace/render.ts +76 -0
- package/src/runtime/trace/views.ts +459 -0
- package/src/runtime/verification/contract-runner.ts +341 -0
- package/src/runtime/verification/engine.ts +1461 -0
- package/src/runtime/verification/registry.ts +130 -0
- package/src/runtime/verification/scope-bound.ts +418 -0
- package/src/runtime/verification/test-selection.ts +172 -0
- package/src/runtime/workflow-engine.ts +588 -0
- package/src/runtime/workflow-orchestrator.ts +953 -0
- package/src/runtime/worktree.ts +340 -0
- package/src/state/index.ts +193 -0
- package/src/state/lockfile.ts +136 -0
- package/src/state/run-lock.ts +408 -0
- package/types/node-commonjs.d.ts +68 -0
- package/types/runtime.d.ts +91 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "doflow",
|
|
3
|
+
"description": "DoFlow main session: spec-driven delivery with lifecycle hooks and specialist dispatch",
|
|
4
|
+
"prompt": "You are the DoFlow main session. Follow the DoFlow steering files under .kiro/steering (principles, rules, the spec-driven chain) and the skills under .kiro/skills. Dispatch specialist work by role to core-implementer, quality-guardian, spec-analyst, system-architect or research-writer, and keep decisions, verification and records in this session.\n",
|
|
5
|
+
"tools": [
|
|
6
|
+
"*"
|
|
7
|
+
],
|
|
8
|
+
"hooks": [
|
|
9
|
+
{
|
|
10
|
+
"name": "doflow-pre-implementation-gate",
|
|
11
|
+
"trigger": "preToolUse",
|
|
12
|
+
"matcher": "write",
|
|
13
|
+
"action": {
|
|
14
|
+
"type": "command",
|
|
15
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/pre-implement-gate.sh\" ] && printf '%s/.kiro/hooks/pre-implement-gate.sh' \"$root\" || printf '%s/.kiro/hooks/pre-implement-gate.sh' \"$HOME\")\""
|
|
16
|
+
},
|
|
17
|
+
"timeout": 10
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "doflow-pre-bash-guard",
|
|
21
|
+
"trigger": "preToolUse",
|
|
22
|
+
"matcher": "shell",
|
|
23
|
+
"action": {
|
|
24
|
+
"type": "command",
|
|
25
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/pre-bash-guard.sh\" ] && printf '%s/.kiro/hooks/pre-bash-guard.sh' \"$root\" || printf '%s/.kiro/hooks/pre-bash-guard.sh' \"$HOME\")\""
|
|
26
|
+
},
|
|
27
|
+
"timeout": 10
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "doflow-mcp-tool-guard",
|
|
31
|
+
"trigger": "preToolUse",
|
|
32
|
+
"matcher": "*",
|
|
33
|
+
"action": {
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/mcp-tool-guard.sh\" ] && printf '%s/.kiro/hooks/mcp-tool-guard.sh' \"$root\" || printf '%s/.kiro/hooks/mcp-tool-guard.sh' \"$HOME\")\""
|
|
36
|
+
},
|
|
37
|
+
"timeout": 10
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "doflow-session-context",
|
|
41
|
+
"trigger": "agentSpawn",
|
|
42
|
+
"action": {
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/session-start.sh\" ] && printf '%s/.kiro/hooks/session-start.sh' \"$root\" || printf '%s/.kiro/hooks/session-start.sh' \"$HOME\")\""
|
|
45
|
+
},
|
|
46
|
+
"timeout": 10
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "doflow-stop-check",
|
|
50
|
+
"trigger": "stop",
|
|
51
|
+
"action": {
|
|
52
|
+
"type": "command",
|
|
53
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/stop-check.sh\" ] && printf '%s/.kiro/hooks/stop-check.sh' \"$root\" || printf '%s/.kiro/hooks/stop-check.sh' \"$HOME\")\""
|
|
54
|
+
},
|
|
55
|
+
"timeout": 30
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "v1",
|
|
3
|
+
"hooks": [
|
|
4
|
+
{
|
|
5
|
+
"name": "doflow-session-context",
|
|
6
|
+
"trigger": "SessionStart",
|
|
7
|
+
"action": {
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/session-start.sh\" ] && printf '%s/.kiro/hooks/session-start.sh' \"$root\" || printf '%s/.kiro/hooks/session-start.sh' \"$HOME\")\""
|
|
10
|
+
},
|
|
11
|
+
"enabled": true
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "doflow-pre-implementation-gate",
|
|
15
|
+
"trigger": "PreToolUse",
|
|
16
|
+
"action": {
|
|
17
|
+
"type": "command",
|
|
18
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/pre-implement-gate.sh\" ] && printf '%s/.kiro/hooks/pre-implement-gate.sh' \"$root\" || printf '%s/.kiro/hooks/pre-implement-gate.sh' \"$HOME\")\""
|
|
19
|
+
},
|
|
20
|
+
"enabled": true
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "doflow-pre-bash-guard",
|
|
24
|
+
"trigger": "PreToolUse",
|
|
25
|
+
"matcher": "shell",
|
|
26
|
+
"action": {
|
|
27
|
+
"type": "command",
|
|
28
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/pre-bash-guard.sh\" ] && printf '%s/.kiro/hooks/pre-bash-guard.sh' \"$root\" || printf '%s/.kiro/hooks/pre-bash-guard.sh' \"$HOME\")\""
|
|
29
|
+
},
|
|
30
|
+
"enabled": true
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "doflow-mcp-tool-guard",
|
|
34
|
+
"trigger": "PreToolUse",
|
|
35
|
+
"matcher": "@mcp",
|
|
36
|
+
"action": {
|
|
37
|
+
"type": "command",
|
|
38
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/mcp-tool-guard.sh\" ] && printf '%s/.kiro/hooks/mcp-tool-guard.sh' \"$root\" || printf '%s/.kiro/hooks/mcp-tool-guard.sh' \"$HOME\")\""
|
|
39
|
+
},
|
|
40
|
+
"enabled": true
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "doflow-stop-check",
|
|
44
|
+
"trigger": "Stop",
|
|
45
|
+
"action": {
|
|
46
|
+
"type": "command",
|
|
47
|
+
"command": "bash \"$(root=$(git rev-parse --show-toplevel 2>/dev/null) && [ -f \"$root/.kiro/hooks/stop-check.sh\" ] && printf '%s/.kiro/hooks/stop-check.sh' \"$root\" || printf '%s/.kiro/hooks/stop-check.sh' \"$HOME\")\""
|
|
48
|
+
},
|
|
49
|
+
"timeout": 30,
|
|
50
|
+
"enabled": true
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# lib.sh — shared constants and helpers for session lifecycle hooks
|
|
3
|
+
#
|
|
4
|
+
# Usage: source "$(dirname "$0")/lib.sh"
|
|
5
|
+
#
|
|
6
|
+
# All hooks must:
|
|
7
|
+
# 1. source this file at the top
|
|
8
|
+
# 2. call require_jq immediately after
|
|
9
|
+
# 3. capture stdin once: INPUT=$(cat)
|
|
10
|
+
# 4. use: json_field "$INPUT" ".field_name"
|
|
11
|
+
#
|
|
12
|
+
# Deployment:
|
|
13
|
+
# This file is installed by the doflow CLI and overwritten on update — do
|
|
14
|
+
# not edit an installed copy directly.
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
# ── State directories ────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
# XDG-compliant, agent-agnostic store shared by Claude Code, Codex, Gemini, etc.
|
|
21
|
+
DOFLOW_HOME="${XDG_CONFIG_HOME:-$HOME/.config}/doflow"
|
|
22
|
+
STATE_DIR="$DOFLOW_HOME/session-env"
|
|
23
|
+
SESSION_DIR="$STATE_DIR/sessions"
|
|
24
|
+
PROJECTS_DIR="$STATE_DIR/projects"
|
|
25
|
+
# shellcheck disable=SC2034 # used by session-start.sh and session-end.sh which source this file
|
|
26
|
+
SESSIONS_LOG="$DOFLOW_HOME/sessions.log"
|
|
27
|
+
|
|
28
|
+
# Identifies which agent is running. Override via env var for non-Claude agents.
|
|
29
|
+
export DOFLOW_AGENT="${DOFLOW_AGENT:-unknown}"
|
|
30
|
+
|
|
31
|
+
# ── canonicalize_path ────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
# Print an absolute, symlink-resolved form of $1 when it exists; otherwise
|
|
34
|
+
# print $1 unchanged. Replaces `realpath -e "$1" 2>/dev/null || echo "$1"`,
|
|
35
|
+
# which silently falls back to an uncanonicalized path on stock macOS (BSD
|
|
36
|
+
# realpath has no -e flag). Uses only primitives present on every target
|
|
37
|
+
# (cd, pwd -P, dirname, basename) — no GNU-only flag, no assumed Homebrew
|
|
38
|
+
# coreutils.
|
|
39
|
+
#
|
|
40
|
+
# Hardening notes:
|
|
41
|
+
# - `CDPATH=` resets CDPATH for the internal `cd` so a user's exported
|
|
42
|
+
# CDPATH can't redirect it to an unrelated directory of the same name
|
|
43
|
+
# (and can't make `cd` echo a stray "found via CDPATH" line to stdout).
|
|
44
|
+
# - `--` guards `dirname`/`basename`/`cd` against a path that begins with
|
|
45
|
+
# `-` being parsed as an option.
|
|
46
|
+
# - if the internal `cd` fails for any reason, `||` falls through to the
|
|
47
|
+
# uncanonicalized-path branch instead of aborting under this file's
|
|
48
|
+
# `set -e` (matching the old `realpath ... || echo "$1"` degrade path).
|
|
49
|
+
# - a root-level parent directory ("/") is special-cased so the result
|
|
50
|
+
# never gets a leading `//`, which POSIX leaves undefined and which
|
|
51
|
+
# Cygwin/MSYS2 (a DoFlow target platform) interprets as a UNC path.
|
|
52
|
+
canonicalize_path() {
|
|
53
|
+
local path="$1" dir base
|
|
54
|
+
if [[ -e "$path" ]] \
|
|
55
|
+
&& dir=$(CDPATH= cd -P -- "$(dirname -- "$path")" 2>/dev/null && pwd -P); then
|
|
56
|
+
base=$(basename -- "$path")
|
|
57
|
+
if [[ "$dir" == "/" ]]; then
|
|
58
|
+
printf '/%s\n' "$base"
|
|
59
|
+
else
|
|
60
|
+
printf '%s/%s\n' "$dir" "$base"
|
|
61
|
+
fi
|
|
62
|
+
else
|
|
63
|
+
printf '%s\n' "$path"
|
|
64
|
+
fi
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# ── with_file_lock ───────────────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
# Internal: break in on $1 (a lock directory) if it looks abandoned — its
|
|
70
|
+
# recorded owner PID is no longer alive, or it's older than 5x the caller's
|
|
71
|
+
# timeout (floored at 30s so short test timeouts don't make legitimately-held
|
|
72
|
+
# locks look stale). Best-effort: mkdir-based locking has no kernel-enforced
|
|
73
|
+
# ownership the way flock did, so a PID can in principle be reused by an
|
|
74
|
+
# unrelated process — the age check is the backstop for that race. The
|
|
75
|
+
# guarded section this protects (session-log trimming) tolerates a rare
|
|
76
|
+
# double-run; this is a soft safety net against a lock leaking forever after
|
|
77
|
+
# its owner is SIGKILLed, not a hard mutual-exclusion guarantee.
|
|
78
|
+
_with_file_lock_break_if_stale() {
|
|
79
|
+
local lockfile="$1"
|
|
80
|
+
local timeout_seconds="$2"
|
|
81
|
+
|
|
82
|
+
local owner_pid=""
|
|
83
|
+
[ -f "$lockfile/pid" ] && owner_pid=$(cat "$lockfile/pid" 2>/dev/null || true)
|
|
84
|
+
local owner_dead=0
|
|
85
|
+
if [ -n "$owner_pid" ] && ! kill -0 "$owner_pid" 2>/dev/null; then
|
|
86
|
+
owner_dead=1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
local too_old=0
|
|
90
|
+
local mtime
|
|
91
|
+
mtime=$(stat -f %m "$lockfile" 2>/dev/null || stat -c %Y "$lockfile" 2>/dev/null || echo "")
|
|
92
|
+
if [ -n "$mtime" ]; then
|
|
93
|
+
local max_age=$((timeout_seconds * 5))
|
|
94
|
+
[ "$max_age" -lt 30 ] && max_age=30
|
|
95
|
+
if [ $(($(date +%s) - mtime)) -gt "$max_age" ]; then
|
|
96
|
+
too_old=1
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
if [ "$owner_dead" -eq 1 ] || [ "$too_old" -eq 1 ]; then
|
|
101
|
+
rm -rf "$lockfile" 2>/dev/null || true
|
|
102
|
+
fi
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# Acquire a lock via atomic `mkdir` (atomic on every filesystem DoFlow runs
|
|
106
|
+
# on, including NTFS via MSYS2) — replaces `flock -x -w 5 200`, which is
|
|
107
|
+
# util-linux-only and confirmed absent entirely on macOS.
|
|
108
|
+
#
|
|
109
|
+
# Usage: call to acquire, run the guarded section in the same shell/subshell,
|
|
110
|
+
# then call again with "release" to release. The lock is also released
|
|
111
|
+
# automatically on exit (normal or error) via an EXIT trap, so a crashed or
|
|
112
|
+
# early-exiting guarded section never leaves the lock held.
|
|
113
|
+
#
|
|
114
|
+
# if with_file_lock "$LOCK_FILE" 5; then
|
|
115
|
+
# ...guarded section...
|
|
116
|
+
# with_file_lock "$LOCK_FILE" release
|
|
117
|
+
# fi
|
|
118
|
+
#
|
|
119
|
+
# Returns 1 (without acquiring the lock) if timeout_seconds elapses first.
|
|
120
|
+
# A lock whose owner process is gone, or that has sat far longer than the
|
|
121
|
+
# caller's own timeout, is treated as abandoned and broken into rather than
|
|
122
|
+
# waited out (see _with_file_lock_break_if_stale) — a `flock`-held lock was
|
|
123
|
+
# always released by the kernel on process death; a bare `mkdir` lock is not,
|
|
124
|
+
# so this replaces that guarantee instead of silently dropping it.
|
|
125
|
+
#
|
|
126
|
+
# Any EXIT trap the caller already had installed (e.g. its own temp-file
|
|
127
|
+
# cleanup) is preserved: it still runs at real process exit (after this
|
|
128
|
+
# lock's own cleanup), and is still armed as the active EXIT trap after an
|
|
129
|
+
# explicit "release" call — acquiring/releasing this lock never discards it.
|
|
130
|
+
with_file_lock() {
|
|
131
|
+
local lockfile="$1"
|
|
132
|
+
local arg="$2"
|
|
133
|
+
|
|
134
|
+
if [ "$arg" = "release" ]; then
|
|
135
|
+
rm -f "$lockfile/pid" 2>/dev/null || true
|
|
136
|
+
rmdir "$lockfile" 2>/dev/null || true
|
|
137
|
+
if [ -n "${_DOFLOW_LOCK_PREV_TRAP:-}" ]; then
|
|
138
|
+
eval "$_DOFLOW_LOCK_PREV_TRAP"
|
|
139
|
+
else
|
|
140
|
+
trap - EXIT
|
|
141
|
+
fi
|
|
142
|
+
unset _DOFLOW_LOCK_PREV_TRAP
|
|
143
|
+
return 0
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
local timeout_seconds="$arg"
|
|
147
|
+
local waited=0
|
|
148
|
+
while ! mkdir "$lockfile" 2>/dev/null; do
|
|
149
|
+
_with_file_lock_break_if_stale "$lockfile" "$timeout_seconds"
|
|
150
|
+
if [ "$waited" -ge "$timeout_seconds" ]; then
|
|
151
|
+
return 1
|
|
152
|
+
fi
|
|
153
|
+
sleep 1
|
|
154
|
+
waited=$((waited + 1))
|
|
155
|
+
done
|
|
156
|
+
echo "$$" >"$lockfile/pid" 2>/dev/null || true
|
|
157
|
+
|
|
158
|
+
# Capture the caller's existing EXIT trap (if any) so releasing this lock
|
|
159
|
+
# can restore it verbatim, and so real process exit runs both this lock's
|
|
160
|
+
# cleanup and the caller's original cleanup rather than only the latest
|
|
161
|
+
# one registered.
|
|
162
|
+
_DOFLOW_LOCK_PREV_TRAP=$(trap -p EXIT)
|
|
163
|
+
local prev_cmd=""
|
|
164
|
+
if [ -n "$_DOFLOW_LOCK_PREV_TRAP" ]; then
|
|
165
|
+
local prev_body="${_DOFLOW_LOCK_PREV_TRAP#trap -- }"
|
|
166
|
+
prev_body="${prev_body% EXIT}"
|
|
167
|
+
eval "prev_cmd=$prev_body"
|
|
168
|
+
fi
|
|
169
|
+
# shellcheck disable=SC2064 # intentional immediate expansion of $lockfile/$prev_cmd
|
|
170
|
+
trap "rm -f '$lockfile/pid' 2>/dev/null; rmdir '$lockfile' 2>/dev/null; $prev_cmd" EXIT
|
|
171
|
+
return 0
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
# ── run_with_timeout ─────────────────────────────────────────────────────────
|
|
175
|
+
|
|
176
|
+
# Run <command...> and terminate it if it exceeds <seconds>. Replaces bare
|
|
177
|
+
# GNU `timeout` calls, which are not installed by default on stock macOS
|
|
178
|
+
# without Homebrew coreutils. When neither a verified-GNU `timeout` nor
|
|
179
|
+
# `gtimeout` (the Homebrew coreutils name) is on PATH, runs the command
|
|
180
|
+
# directly with no enforced budget — a soft safety net, not a correctness
|
|
181
|
+
# requirement.
|
|
182
|
+
#
|
|
183
|
+
# `timeout` is not trusted just because something by that name is on PATH:
|
|
184
|
+
# on Git Bash/MSYS2, PATH can resolve it to Windows' native
|
|
185
|
+
# `System32\timeout.exe`, whose syntax (`timeout /T n`) is incompatible —
|
|
186
|
+
# invoking it the GNU way would fail the command outright instead of just
|
|
187
|
+
# running it unbounded. `timeout --version` is a cheap, side-effect-free way
|
|
188
|
+
# to confirm it's the GNU coreutils build before trusting it (Windows'
|
|
189
|
+
# timeout.exe doesn't understand --version and errors).
|
|
190
|
+
#
|
|
191
|
+
# Usage: run_with_timeout <seconds> -- <command...>
|
|
192
|
+
run_with_timeout() {
|
|
193
|
+
local seconds="$1"
|
|
194
|
+
shift
|
|
195
|
+
if [ "${1:-}" = "--" ]; then
|
|
196
|
+
shift
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
if command -v timeout &>/dev/null && timeout --version &>/dev/null; then
|
|
200
|
+
timeout "$seconds" "$@"
|
|
201
|
+
elif command -v gtimeout &>/dev/null; then
|
|
202
|
+
gtimeout "$seconds" "$@"
|
|
203
|
+
else
|
|
204
|
+
"$@"
|
|
205
|
+
fi
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
# ── cwd_hash ─────────────────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
# Derive a stable 16-char hash of an absolute directory path.
|
|
211
|
+
# Used to namespace per-project state (compact summaries, warnings).
|
|
212
|
+
#
|
|
213
|
+
# For a path that is (or resolves to) an existing directory — the case this
|
|
214
|
+
# function exists for — fully resolves it, including a symlink at the path's
|
|
215
|
+
# own leaf component, via `(cd "$1" && pwd -P)`, so equivalent directories
|
|
216
|
+
# always hash identically. Callers that ever pass a non-directory or
|
|
217
|
+
# nonexistent path fall back to the general-purpose canonicalize_path, which
|
|
218
|
+
# — being usable by any file or missing path, not just directories — only
|
|
219
|
+
# resolves symlinks in the parent chain, not the leaf itself.
|
|
220
|
+
#
|
|
221
|
+
# Hash fallback chain: sha256sum -> shasum -a 256 -> cksum (last resort).
|
|
222
|
+
# The cksum branch is normalized via printf '%016x' to the same 16-char
|
|
223
|
+
# hex contract every other branch provides — raw cksum output is a decimal
|
|
224
|
+
# CRC, not hex, and not guaranteed to be 16 characters. Collision risk from
|
|
225
|
+
# the cksum fallback is acceptable here — this is only a cache-key
|
|
226
|
+
# namespace, not security-relevant.
|
|
227
|
+
cwd_hash() {
|
|
228
|
+
local canonical
|
|
229
|
+
if [ -d "$1" ]; then
|
|
230
|
+
canonical=$(cd "$1" && pwd -P)
|
|
231
|
+
else
|
|
232
|
+
canonical=$(canonicalize_path "$1")
|
|
233
|
+
fi
|
|
234
|
+
if command -v sha256sum &>/dev/null; then
|
|
235
|
+
echo "$canonical" | sha256sum | cut -c1-16
|
|
236
|
+
elif command -v shasum &>/dev/null; then
|
|
237
|
+
echo "$canonical" | shasum -a 256 | cut -c1-16
|
|
238
|
+
else
|
|
239
|
+
printf '%016x\n' "$(echo "$canonical" | cksum | cut -d' ' -f1)"
|
|
240
|
+
fi
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
# ── Directory helpers ─────────────────────────────────────────────────────────
|
|
244
|
+
|
|
245
|
+
# Create and return the session-scoped state directory for a given session_id.
|
|
246
|
+
# Safe to call multiple times (mkdir -p is idempotent).
|
|
247
|
+
ensure_session_dir() {
|
|
248
|
+
local session_id="$1"
|
|
249
|
+
mkdir -p "$SESSION_DIR/$session_id"
|
|
250
|
+
echo "$SESSION_DIR/$session_id"
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
# Create and return the project-scoped state directory for a given cwd.
|
|
254
|
+
# Shared across all sessions in the same directory.
|
|
255
|
+
ensure_project_dir() {
|
|
256
|
+
local cwd="$1"
|
|
257
|
+
local hash
|
|
258
|
+
hash=$(cwd_hash "$cwd")
|
|
259
|
+
mkdir -p "$PROJECTS_DIR/$hash"
|
|
260
|
+
echo "$PROJECTS_DIR/$hash"
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
# ── JSON helpers ──────────────────────────────────────────────────────────────
|
|
264
|
+
|
|
265
|
+
# Extract a field from a JSON string.
|
|
266
|
+
# Usage: json_field "$INPUT" ".field_name"
|
|
267
|
+
# Returns empty string if field is null or jq fails.
|
|
268
|
+
json_field() {
|
|
269
|
+
local json="$1"
|
|
270
|
+
local query="$2"
|
|
271
|
+
echo "$json" | jq -r "$query // empty" 2>/dev/null || echo ""
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# ── Dependency guard ──────────────────────────────────────────────────────────
|
|
275
|
+
|
|
276
|
+
# Verify jq is available at runtime. If absent, emit a diagnostic to stderr
|
|
277
|
+
# and exit 0 (never block the harness — degraded operation is preferable to failure).
|
|
278
|
+
require_jq() {
|
|
279
|
+
if ! command -v jq &>/dev/null; then
|
|
280
|
+
echo "[hooks] jq not found — install jq to enable session lifecycle hooks (apt install jq / brew install jq)" >&2
|
|
281
|
+
exit 0
|
|
282
|
+
fi
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
# ── kiro_bridge_payload ───────────────────────────────────────────────────────
|
|
286
|
+
|
|
287
|
+
# Read a Kiro hook payload on stdin and print the canonical payload the shared policies read.
|
|
288
|
+
# The shared policies understand Claude-style names; Kiro differs in four places, mapped here so
|
|
289
|
+
# the policies stay untouched:
|
|
290
|
+
# - session_id: absent from some Kiro events; taken from $KIRO_SESSION_ID when empty
|
|
291
|
+
# - tool_name: write|fs_write|fs_append|str_replace|delete_file|write_file -> Write
|
|
292
|
+
# (tool_input.path also copied to tool_input.file_path),
|
|
293
|
+
# shell|execute_bash|execute_cmd|execute_pwsh -> Bash,
|
|
294
|
+
# @server/tool -> mcp__server__tool. Kiro CLI V3 already sanitizes MCP tool IDs to
|
|
295
|
+
# mcp_<server>_<tool>; those pass through unchanged, because the shared
|
|
296
|
+
# mcp-tool-guard matches the single-underscore mcp_ prefix case-insensitively.
|
|
297
|
+
# - assistant_response -> last_assistant_message (stop event)
|
|
298
|
+
# Any other name passes through unchanged, so an unmapped tool fails open as it does without the
|
|
299
|
+
# bridge. When jq is missing or rejects the payload, the original payload is printed unchanged.
|
|
300
|
+
kiro_bridge_payload() {
|
|
301
|
+
local payload rewritten
|
|
302
|
+
payload=$(cat)
|
|
303
|
+
if command -v jq &>/dev/null \
|
|
304
|
+
&& rewritten=$(printf '%s' "$payload" | jq -c --arg sid "${KIRO_SESSION_ID:-}" '
|
|
305
|
+
(if ((.session_id // "") == "") and ($sid != "") then .session_id = $sid else . end)
|
|
306
|
+
| (.tool_name // "") as $t
|
|
307
|
+
| (if ($t == "write" or $t == "fs_write" or $t == "fs_append" or $t == "str_replace" or $t == "delete_file" or $t == "write_file") then
|
|
308
|
+
.tool_name = "Write"
|
|
309
|
+
| (if ((.tool_input | type) == "object") and (.tool_input.path != null) and (.tool_input.file_path == null)
|
|
310
|
+
then .tool_input.file_path = .tool_input.path else . end)
|
|
311
|
+
elif ($t == "shell" or $t == "execute_bash" or $t == "execute_cmd" or $t == "execute_pwsh") then
|
|
312
|
+
.tool_name = "Bash"
|
|
313
|
+
elif ($t | startswith("@")) then
|
|
314
|
+
.tool_name = ("mcp__" + ($t[1:] | gsub("/"; "__")))
|
|
315
|
+
else . end)
|
|
316
|
+
| (if (.assistant_response != null) and (.last_assistant_message == null)
|
|
317
|
+
then .last_assistant_message = .assistant_response else . end)
|
|
318
|
+
' 2>/dev/null) \
|
|
319
|
+
&& [ -n "$rewritten" ]; then
|
|
320
|
+
printf '%s\n' "$rewritten"
|
|
321
|
+
else
|
|
322
|
+
printf '%s\n' "$payload"
|
|
323
|
+
fi
|
|
324
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Kiro adapter: reuse the canonical mcp-tool-guard policy with Kiro attribution.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
export DOFLOW_AGENT="${DOFLOW_AGENT:-kiro}"
|
|
5
|
+
# shellcheck source=lib.sh
|
|
6
|
+
source "$(dirname "$0")/lib.sh"
|
|
7
|
+
# Translate Kiro's payload (tool names, KIRO_SESSION_ID, assistant_response) to the canonical one.
|
|
8
|
+
payload=$(kiro_bridge_payload)
|
|
9
|
+
exec bash "$(dirname "$0")/../../.doflow/shared/hooks/policies/mcp-tool-guard.sh" <<<"$payload"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Kiro adapter: reuse the canonical pre-bash-guard policy with Kiro attribution.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
export DOFLOW_AGENT="${DOFLOW_AGENT:-kiro}"
|
|
5
|
+
# shellcheck source=lib.sh
|
|
6
|
+
source "$(dirname "$0")/lib.sh"
|
|
7
|
+
# Translate Kiro's payload (tool names, KIRO_SESSION_ID, assistant_response) to the canonical one.
|
|
8
|
+
payload=$(kiro_bridge_payload)
|
|
9
|
+
exec bash "$(dirname "$0")/../../.doflow/shared/hooks/policies/pre-bash-guard.sh" <<<"$payload"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Kiro adapter: reuse the canonical pre-implementation-gate policy with Kiro attribution.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
export DOFLOW_AGENT="${DOFLOW_AGENT:-kiro}"
|
|
5
|
+
# shellcheck source=lib.sh
|
|
6
|
+
source "$(dirname "$0")/lib.sh"
|
|
7
|
+
# Translate Kiro's payload (tool names, KIRO_SESSION_ID, assistant_response) to the canonical one.
|
|
8
|
+
payload=$(kiro_bridge_payload)
|
|
9
|
+
exec bash "$(dirname "$0")/../../.doflow/shared/hooks/policies/pre-implementation-gate.sh" <<<"$payload"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Kiro adapter: reuse the canonical session-context policy with Kiro attribution.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
export DOFLOW_AGENT="${DOFLOW_AGENT:-kiro}"
|
|
5
|
+
# shellcheck source=lib.sh
|
|
6
|
+
source "$(dirname "$0")/lib.sh"
|
|
7
|
+
# Translate Kiro's payload (tool names, KIRO_SESSION_ID, assistant_response) to the canonical one.
|
|
8
|
+
payload=$(kiro_bridge_payload)
|
|
9
|
+
exec bash "$(dirname "$0")/../../.doflow/shared/hooks/policies/session-context.sh" <<<"$payload"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Kiro adapter: run the canonical stop-check policy and translate its verdict to the Kiro engine.
|
|
3
|
+
#
|
|
4
|
+
# The policy exits 2 to deny the stop. Kiro engines read a Stop hook differently:
|
|
5
|
+
# - Kiro CLI V3 / IDE (payload carries session_id): exit 0 finishes the turn; exit 0 with stdout
|
|
6
|
+
# JSON {"decision":"block","reason":"..."} starts another turn with that reason; exit 1 also
|
|
7
|
+
# starts another turn; other codes finish without forwarding output. Exit 2 does NOT block.
|
|
8
|
+
# So a policy deny becomes the JSON block on stdout with exit 0.
|
|
9
|
+
# - Kiro CLI 2.x (payload has no session_id): exit 0 succeeded, any other code shows stderr to the
|
|
10
|
+
# user as a warning. A policy deny is passed through as stderr with exit 2.
|
|
11
|
+
# Every other policy outcome exits 0, never 1: V3 treats exit 1 as "continue another turn".
|
|
12
|
+
# The policy blocks a given message once, so the continuation turn is not blocked again.
|
|
13
|
+
# Docs: https://kiro.dev/docs/hooks/types/ , https://kiro.dev/docs/cli/v3/hooks-migration/
|
|
14
|
+
set -uo pipefail
|
|
15
|
+
export DOFLOW_AGENT="${DOFLOW_AGENT:-kiro}"
|
|
16
|
+
here="$(dirname "$0")"
|
|
17
|
+
# shellcheck source=lib.sh
|
|
18
|
+
source "$here/lib.sh"
|
|
19
|
+
set +e # lib.sh enables errexit; the policy exit code is handled explicitly below
|
|
20
|
+
|
|
21
|
+
raw=$(cat)
|
|
22
|
+
# Translate Kiro's payload (tool names, KIRO_SESSION_ID, assistant_response) to the canonical one.
|
|
23
|
+
payload=$(kiro_bridge_payload <<<"$raw")
|
|
24
|
+
|
|
25
|
+
# V3 and the IDE send session_id in the payload; 2.x does not (the bridge injects it from the env).
|
|
26
|
+
raw_sid=""
|
|
27
|
+
if command -v jq >/dev/null 2>&1; then
|
|
28
|
+
raw_sid=$(printf '%s' "$raw" | jq -r '.session_id // empty' 2>/dev/null) || raw_sid=""
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Capture the policy's stderr (stdout discarded) and its exit code without a temp file.
|
|
32
|
+
errtext=$(bash "$here/../../.doflow/shared/hooks/policies/stop-check.sh" <<<"$payload" 2>&1 >/dev/null)
|
|
33
|
+
rc=$?
|
|
34
|
+
|
|
35
|
+
if [ "$rc" -eq 2 ]; then
|
|
36
|
+
if [ -n "$raw_sid" ] && command -v jq >/dev/null 2>&1; then
|
|
37
|
+
jq -n --arg reason "$errtext" '{decision: "block", reason: $reason}'
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
printf '%s\n' "$errtext" >&2
|
|
41
|
+
exit 2
|
|
42
|
+
fi
|
|
43
|
+
exit 0
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# The normalized hook envelope, and each front door's share of the migration
|
|
2
|
+
|
|
3
|
+
`policies/pre-implementation-gate.sh` prefers one normalized event over every native payload
|
|
4
|
+
shape (review R7):
|
|
5
|
+
|
|
6
|
+
```json
|
|
7
|
+
{"doflow_event": {"operation": "edit", "paths": ["src/a.js"], "projectRoot": "/repo", "taskId": "001-auth"}}
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
A front door that sends this envelope needs none of the policy's legacy union parsing — the four
|
|
11
|
+
tool-name spellings, five file-path field names, and Codex `apply_patch` diff extraction exist
|
|
12
|
+
only for front doors still forwarding raw native payloads. Each adapter that adopts the envelope
|
|
13
|
+
retires its share of that union; when the last one does, the union decoder is deleted.
|
|
14
|
+
|
|
15
|
+
## Which native event each front door decodes
|
|
16
|
+
|
|
17
|
+
Per-harness pre-edit event names, from the hook-event inventory compiled 2026-08-28 against each
|
|
18
|
+
tool's official docs (cross-checked against tool source where docs were incomplete):
|
|
19
|
+
|
|
20
|
+
| Harness | Native pre-edit event | Notes for the decoder |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| Claude Code | `PreToolUse` | `tool_name` Edit/Write/MultiEdit; `tool_input.file_path` |
|
|
23
|
+
| Codex | `PreToolUse` | `apply_patch` carries paths inside a unified diff under `tool_input.command` — the ONE decoder that must parse patch text |
|
|
24
|
+
| Gemini CLI | `BeforeTool` | also offers `BeforeToolSelection` (pre-selection restriction), which the gate does not use |
|
|
25
|
+
| GitHub Copilot | `preToolUse` | camelCase event names; `permissionRequest` is CLI-only, not fired in the cloud agent |
|
|
26
|
+
| OpenCode | `tool.execute.before` | a pluggable hook method, not a sub-event of the generic `event` hook |
|
|
27
|
+
| Pi | `tool_execution_start` | Pi's 36-event surface also exposes `tool_call`; the execution-start event is the gate's anchor |
|
|
28
|
+
| Antigravity | `PreToolUse` | 5-event surface, `hooks.json` + stdin/stdout JSON contract |
|
|
29
|
+
|
|
30
|
+
`operation` is `"edit"` for anything that writes source; a decoder maps its native create/replace/
|
|
31
|
+
patch tool vocabulary down to that one word. Non-edit operations may be sent (the policy allows
|
|
32
|
+
them through), but sending nothing for a non-edit tool is equally correct and cheaper.
|
|
33
|
+
|
|
34
|
+
## Rules that hold on both paths
|
|
35
|
+
|
|
36
|
+
- The envelope, when present, **outranks** any native fields beside it.
|
|
37
|
+
- Root resolution: `DOFLOW_PROJECT_DIR` beats the envelope's `projectRoot` beats git discovery.
|
|
38
|
+
- The policy remains a pure file-existence gate (FR-012): the envelope changes how it hears about
|
|
39
|
+
an edit, never what it decides, and it must never consult readiness or evidence state.
|