@khoavu882/doflow 2.0.0-beta.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/bin/doflow.js +21 -11
- package/core/.antigravity-plugin/plugin.json +1 -3
- package/core/.claude-plugin/plugin.json +1 -1
- package/core/.codex-plugin/plugin.json +1 -1
- package/core/.plugin/plugin.json +1 -1
- package/core/harnesses/claude/hooks/lib.sh +43 -24
- package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
- package/core/harnesses/claude/hooks/permission-audit.sh +3 -0
- package/core/harnesses/claude/hooks/post-compact.sh +35 -32
- package/core/harnesses/claude/hooks/post-edit-lint.sh +2 -0
- package/core/harnesses/claude/hooks/post-shell-observe.sh +48 -0
- package/core/harnesses/claude/hooks/post-tool-failure.sh +3 -0
- package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
- package/core/harnesses/claude/hooks/pre-compact.sh +23 -27
- package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
- package/core/harnesses/claude/hooks/session-end.sh +23 -10
- package/core/harnesses/claude/hooks/session-start.sh +5 -3
- package/core/harnesses/claude/hooks/skill-config-audit.sh +3 -0
- package/core/harnesses/claude/hooks/stop-check.sh +5 -3
- package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
- package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
- package/core/harnesses/claude/settings/settings.json +18 -0
- package/core/harnesses/claude/statusline/doflow-statusline.sh +1 -0
- package/core/harnesses/codex/agents/core-implementer.toml +1 -0
- package/core/harnesses/codex/agents/delivery-lead.toml +10 -0
- package/core/harnesses/codex/agents/quality-guardian.toml +1 -1
- package/core/harnesses/codex/agents/research-writer.toml +1 -1
- package/core/harnesses/codex/agents/reviewer.toml +10 -0
- package/core/harnesses/codex/agents/spec-analyst.toml +1 -1
- package/core/harnesses/codex/agents/system-architect.toml +1 -1
- package/core/harnesses/codex/hooks/lib.sh +44 -25
- package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
- package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +3 -1
- package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
- package/core/harnesses/codex/hooks/pre-compact.impl.sh +29 -26
- package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
- package/core/harnesses/codex/hooks/session-end.impl.sh +23 -10
- package/core/harnesses/codex/hooks/session-start.sh +5 -3
- package/core/harnesses/codex/hooks/stop-check.sh +6 -5
- package/core/harnesses/codex/hooks/subagent-audit.sh +18 -6
- package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
- package/core/harnesses/copilot/hooks/doflow-lib.sh +93 -0
- package/core/harnesses/copilot/hooks/doflow-mcp-tool-guard.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-pre-bash-guard.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-pre-implement-gate.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-session-start.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-stop-check.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-subagent-start.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-subagent-stop.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow.json +57 -0
- package/core/harnesses/kiro/agents/doflow.json +1 -1
- package/core/harnesses/kiro/hooks/lib.sh +26 -6
- package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +21 -5
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +21 -5
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +21 -5
- package/core/harnesses/kiro/hooks/session-start.sh +12 -5
- package/core/harnesses/kiro/hooks/stop-check.sh +22 -30
- package/core/harnesses/pi/extensions/doflow-guard.js +167 -0
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -12
- package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
- package/core/harnesses/shared/hooks/bridge/bridge.sh +277 -0
- package/core/harnesses/shared/hooks/bridge/envelope.jq +129 -0
- package/core/harnesses/shared/hooks/bridge/observe-model.sh +75 -0
- package/core/harnesses/shared/hooks/bridge/respond.sh +70 -0
- package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +28 -14
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +51 -16
- package/core/harnesses/shared/hooks/policies/compact-text.sh +46 -0
- package/core/harnesses/shared/hooks/policies/contract.sh +78 -0
- package/core/harnesses/shared/hooks/policies/deny-json.sh +35 -9
- package/core/harnesses/shared/hooks/policies/emission-rules.sh +37 -0
- package/core/harnesses/shared/hooks/policies/emission.jq +209 -0
- package/core/harnesses/shared/hooks/policies/emission.sh +383 -0
- package/core/harnesses/shared/hooks/policies/identity.sh +177 -0
- package/core/harnesses/shared/hooks/policies/lib.sh +65 -40
- package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +48 -35
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +284 -33
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +180 -110
- package/core/harnesses/shared/hooks/policies/session-context.sh +66 -7
- package/core/harnesses/shared/hooks/policies/stop-check.sh +61 -23
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +39 -6
- package/core/harnesses/shared/hooks/policies/summary-store.sh +347 -0
- package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +97 -159
- package/core/harnesses/shared/hooks/stream-hook-runner.js +114 -187
- package/core/harnesses/shared/locator/doflow-run +2 -3
- package/core/registry/advice.json +3 -3
- package/core/registry/assets.json +72 -80
- package/core/registry/capabilities.json +12 -0
- package/core/registry/contracts.json +60 -33
- package/core/registry/contribution-points.json +32 -0
- package/core/registry/gates.json +32 -0
- package/core/registry/guidance-caps.json +40 -0
- package/core/registry/harnesses.json +1542 -277
- package/core/registry/lifecycle.json +2837 -37
- package/core/registry/mcp.json +5 -1
- package/core/registry/models.json +7 -1
- package/core/registry/package-templates/README.md +19 -0
- package/core/registry/package-templates/agent/files/agent.md +9 -0
- package/core/registry/package-templates/agent/template.json +4 -0
- package/core/registry/package-templates/capability-provider/files/provider.json +9 -0
- package/core/registry/package-templates/capability-provider/template.json +11 -0
- package/core/registry/package-templates/debate-preset/files/preset.json +26 -0
- package/core/registry/package-templates/debate-preset/template.json +4 -0
- package/core/registry/package-templates/review-preset/files/preset.json +30 -0
- package/core/registry/package-templates/review-preset/template.json +4 -0
- package/core/registry/package-templates/skill/files/SKILL.md +8 -0
- package/core/registry/package-templates/skill/template.json +4 -0
- package/core/registry/package-templates/worker/files/worker.json +92 -0
- package/core/registry/package-templates/worker/template.json +11 -0
- package/core/registry/packages/doflow/doflow-package.json +15 -0
- package/core/registry/packages/doflow/presets/debate-3.json +26 -0
- package/core/registry/protocols.json +61 -0
- package/core/registry/routes.json +17 -0
- package/core/registry/rules.json +431 -0
- package/core/registry/settings.json +276 -0
- package/core/registry/storage.json +701 -30
- package/core/registry/telemetry.json +236 -0
- package/core/registry/transcripts.json +142 -0
- package/core/registry/verification.json +76 -1
- package/core/registry/workflows.json +55 -0
- package/core/shared/agent-specs/core-implementer.md +3 -0
- package/core/shared/agent-specs/delivery-lead.md +68 -0
- package/core/shared/agent-specs/quality-guardian.md +5 -1
- package/core/shared/agent-specs/research-writer.md +10 -3
- package/core/shared/agent-specs/reviewer.md +53 -0
- package/core/shared/agent-specs/spec-analyst.md +5 -6
- package/core/shared/agent-specs/system-architect.md +5 -1
- package/core/shared/guidance/DOFLOW_CORE.md +1 -5
- package/core/shared/guidance/modes/MODE_DeepResearch.md +1 -1
- package/core/shared/guidance/modes/MODE_Orchestration.md +4 -3
- package/core/shared/guidance/modes/MODE_Task_Management.md +14 -14
- package/core/shared/guidance/pointers/codex.md +1 -4
- package/core/shared/guidance/references/ARTIFACT_FORMAT.md +30 -16
- package/core/shared/guidance/references/ARTIFACT_VOICE.md +3 -2
- package/core/shared/guidance/references/CONSTITUTION_BASE.md +17 -15
- package/core/shared/guidance/references/DIAGRAM_GUIDE.md +1 -1
- package/core/shared/guidance/references/DOFLOW_CHAIN.md +17 -19
- package/core/shared/guidance/references/EVIDENCE_LEDGER.md +7 -8
- package/core/shared/guidance/references/MODEL_SELECTION.md +5 -3
- package/core/shared/guidance/references/ORCHESTRATION.md +1 -2
- package/core/shared/guidance/rules/RULES.md +45 -0
- package/core/shared/scripts/doflow/bash/do-args.sh +37 -0
- package/core/shared/scripts/doflow/bash/do-exec-paths.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-git-state.sh +15 -4
- package/core/shared/scripts/doflow/bash/do-parallel-check.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-paths.sh +40 -2
- package/core/shared/scripts/doflow/bash/do-prereqs.sh +2 -1
- package/core/shared/scripts/doflow/bash/do-review-package.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-task-brief.sh +58 -16
- package/core/shared/scripts/doflow/bash/render-audit.sh +26 -2
- package/core/shared/scripts/doflow/bash/render-diagrams.sh +1 -0
- package/core/shared/scripts/doflow/bash/render-puml.sh +2 -1
- package/core/shared/scripts/doflow/bash/validate-artifacts.sh +48 -4
- package/core/shared/scripts/doflow/bin/doflow-run +154 -35
- package/core/shared/skills/do/SKILL.md +12 -10
- package/core/shared/skills/do/references/advice_calls.md +26 -0
- package/core/shared/skills/do/references/pm_routing.md +1 -2
- package/core/shared/skills/do/references/program_mode.md +31 -0
- package/core/shared/skills/do-brainstorm/SKILL.md +20 -74
- package/core/shared/skills/do-brainstorm/references/handoff_branches.md +35 -0
- package/core/shared/skills/do-brainstorm/references/intent_seed.md +21 -0
- package/core/shared/skills/do-brainstorm/references/round_log.md +17 -0
- package/core/shared/skills/do-code-review/SKILL.md +41 -144
- package/core/shared/skills/do-code-review/content-types/markdown.md +24 -2
- package/core/shared/skills/do-code-review/references/tools.md +90 -0
- package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +549 -7
- package/core/shared/skills/do-design/SKILL.md +24 -23
- package/core/shared/skills/do-diagnose/SKILL.md +14 -4
- package/core/shared/skills/do-document/SKILL.md +11 -1
- package/core/shared/skills/do-document/references/deep_research.md +1 -2
- package/core/shared/skills/do-document/references/embedded-research.md +18 -6
- package/core/shared/skills/do-document/references/implementation-flow.md +5 -6
- package/core/shared/skills/do-execute-plan/SKILL.md +17 -59
- package/core/shared/skills/do-execute-plan/references/handoff_record.md +7 -2
- package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +13 -0
- package/core/shared/skills/do-execute-plan/references/readiness_gate.md +28 -1
- package/core/shared/skills/do-execute-plan/references/run_position.md +13 -1
- package/core/shared/skills/do-execute-plan/references/scaffold.md +17 -9
- package/core/shared/skills/do-execute-plan/references/state_checkpoint.md +11 -0
- package/core/shared/skills/do-execute-plan/references/task_attempts.md +78 -24
- package/core/shared/skills/do-flow/SKILL.md +8 -9
- package/core/shared/skills/do-flow/references/task_classes.md +2 -2
- package/core/shared/skills/do-git/SKILL.md +4 -0
- package/core/shared/skills/do-implement/SKILL.md +7 -9
- package/core/shared/skills/do-plan/SKILL.md +29 -19
- package/core/shared/skills/do-test/SKILL.md +7 -4
- package/core/shared/templates/doflow/constitution-template.md +9 -3
- package/core/shared/templates/doflow/data-model-template.md +1 -1
- package/core/shared/templates/doflow/design-template.md +113 -16
- package/core/shared/templates/doflow/plan-template.md +11 -10
- package/core/shared/templates/doflow/question-log-template.md +14 -2
- package/core/shared/templates/doflow/requirement-template.md +1 -1
- package/core/worker-evidence/antigravity/checks.json +14 -0
- package/core/worker-evidence/codex/2026-10-18-cli-check.json +107 -0
- package/core/worker-evidence/codex/2026-10-18-live-run-edit.json +73 -0
- package/core/worker-evidence/codex/2026-10-18-live-run-read-only.json +62 -0
- package/core/worker-evidence/codex/2026-10-24-cli-check.json +126 -0
- package/core/worker-evidence/codex/checks.json +38 -0
- package/package.json +10 -6
- package/src/adapters/antigravity/index.js +226 -113
- package/src/adapters/claude/index.js +39 -5
- package/src/adapters/codex/agents.js +25 -15
- package/src/adapters/codex/hooks.js +40 -5
- package/src/adapters/codex/index.js +100 -22
- package/src/adapters/codex/native-projection.js +6 -2
- package/src/adapters/copilot/index.js +58 -23
- package/src/adapters/copy-tree.js +294 -48
- package/src/adapters/guidance-manifest.js +71 -0
- package/src/adapters/guidance-pointer.js +19 -0
- package/src/adapters/hook-commands.js +6 -10
- package/src/adapters/index.js +1 -0
- package/src/adapters/kiro/index.js +38 -13
- package/src/adapters/opencode/index.js +8 -8
- package/src/adapters/pi/hooks.js +120 -0
- package/src/adapters/pi/index.js +48 -16
- package/src/adapters/resolve-source.js +26 -2
- package/src/cli/commands/install.js +3 -2
- package/src/cli/commands/reconcile.js +53 -9
- package/src/cli/commands/remove.js +2 -2
- package/src/cli/commands/rollback.js +6 -3
- package/src/cli/commands/self-update.js +18 -9
- package/src/cli/commands/status.js +21 -2
- package/src/cli/commands/ui.js +99 -0
- package/src/cli/commands/update.js +3 -2
- package/src/cli/index.js +338 -33
- package/src/cli/runtime-commands.js +243 -52
- package/src/cli/shared.js +0 -2
- package/src/helper/git.js +1 -1
- package/src/helper/guardrails.js +1 -1
- package/src/helper/marker-merge.js +31 -13
- package/src/helper/package-ids.js +37 -0
- package/src/helper/semver.js +94 -0
- package/src/install/backup.js +105 -15
- package/src/install/context.js +1 -1
- package/src/install/targets.js +31 -16
- package/src/lifecycle/coverage.js +74 -0
- package/src/lifecycle/hook-step.js +61 -0
- package/src/lifecycle/hook-tier.js +160 -0
- package/src/lifecycle/index.js +434 -86
- package/src/lifecycle/retired-harnesses.js +318 -0
- package/src/lifecycle/view.js +35 -15
- package/src/registry/index.js +686 -32
- package/src/registry/worker-ids.js +45 -0
- package/src/release/build-package.js +0 -3
- package/src/release/docs-blocks.js +492 -0
- package/src/release/preflight.js +425 -0
- package/src/release/rehearse.js +401 -0
- package/src/release/release-workflow.js +733 -0
- package/src/release/sync-plugin-versions.js +43 -7
- package/src/runtime/advice/bench-gate.js +25 -0
- package/src/runtime/advice/cli.js +59 -16
- package/src/runtime/advice/client.js +32 -9
- package/src/runtime/advice/config.js +98 -133
- package/src/runtime/advice/doctor.js +1 -1
- package/src/runtime/advice/elevation.js +97 -0
- package/src/runtime/advice/endpoint-guard.js +9 -3
- package/src/runtime/advice/mode.js +37 -0
- package/src/runtime/advice/record.js +18 -5
- package/src/runtime/advice/registry.js +4 -1
- package/src/runtime/advice/shadow-config.js +229 -0
- package/src/runtime/advice/shadow-dispatcher.js +276 -0
- package/src/runtime/brief-rules.js +81 -0
- package/src/runtime/brief-tools.js +111 -34
- package/src/runtime/candidate.js +514 -0
- package/src/runtime/capabilities/executor.js +450 -0
- package/src/runtime/capabilities/loopback.js +41 -0
- package/src/runtime/capabilities/sanitizer.js +88 -0
- package/src/runtime/capability-router.js +135 -3
- package/src/runtime/checkouts.js +73 -11
- package/src/runtime/claims.js +27 -12
- package/src/runtime/cli-result.js +11 -4
- package/src/runtime/cli.js +221 -277
- package/src/runtime/config-home.js +42 -0
- package/src/runtime/context/arbitrate.js +767 -0
- package/src/runtime/context/budget.js +203 -0
- package/src/runtime/context/compose.js +1367 -0
- package/src/runtime/context/delivery-store.js +100 -0
- package/src/runtime/context/emission-rules.js +118 -0
- package/src/runtime/context/identity.js +227 -0
- package/src/runtime/context/mandatory.js +594 -0
- package/src/runtime/context/pointer.js +142 -0
- package/src/runtime/context/primary-command.js +117 -0
- package/src/runtime/context/primary.js +344 -0
- package/src/runtime/context/summary-store.js +655 -0
- package/src/runtime/context-pack.js +1106 -245
- package/src/runtime/decision-register.js +13 -4
- package/src/runtime/dispatch/admission.js +392 -0
- package/src/runtime/dispatch/attempt-end.js +274 -0
- package/src/runtime/dispatch/command.js +628 -0
- package/src/runtime/dispatch/controls.js +904 -0
- package/src/runtime/dispatch/envelope.js +276 -0
- package/src/runtime/dispatch/grants.js +310 -0
- package/src/runtime/dispatch/integrate.js +617 -0
- package/src/runtime/dispatch/loop.js +1835 -0
- package/src/runtime/dispatch/store.js +352 -0
- package/src/runtime/dispatch/verify-run.js +201 -0
- package/src/runtime/evidence-fields.js +39 -0
- package/src/runtime/evidence-ledger.js +41 -7
- package/src/runtime/failure/capture.js +3 -1
- package/src/runtime/failure/cli.js +25 -9
- package/src/runtime/failure/home.js +57 -30
- package/src/runtime/failure/store.js +7 -2
- package/src/runtime/feature-pointer.js +174 -0
- package/src/runtime/feature-resolve.js +13 -2
- package/src/runtime/fleet/command.js +77 -0
- package/src/runtime/fleet/projects.js +178 -0
- package/src/runtime/fleet/tree.js +383 -0
- package/src/runtime/freshness.js +77 -10
- package/src/runtime/git-memo.js +46 -0
- package/src/runtime/guidance/ablation.js +427 -0
- package/src/runtime/health.js +565 -17
- package/src/runtime/history-compactor.js +13 -3
- package/src/runtime/implementation-gate.js +277 -22
- package/src/runtime/inventory/coverage.js +1 -1
- package/src/runtime/inventory/index.js +1 -1
- package/src/runtime/inventory/precedence.js +2 -2
- package/src/runtime/inventory/siblings.js +6 -4
- package/src/runtime/knowledge/code-corpus.js +277 -0
- package/src/runtime/knowledge/code-lexical.js +130 -0
- package/src/runtime/knowledge/code-retrieval.js +307 -0
- package/src/runtime/knowledge/code-validation.js +106 -0
- package/src/runtime/knowledge/gp3-gate.js +74 -0
- package/src/runtime/knowledge/graph-adapter.js +288 -0
- package/src/runtime/knowledge/graph-fallback.js +394 -0
- package/src/runtime/knowledge/hybrid.js +136 -8
- package/src/runtime/knowledge/retrieval.js +34 -1
- package/src/runtime/knowledge/rtk-compress.js +77 -0
- package/src/runtime/knowledge/semble-bridge.py +106 -0
- package/src/runtime/knowledge/semble-lifecycle.js +114 -0
- package/src/runtime/knowledge/semble-provider.js +365 -0
- package/src/runtime/lifecycle/cli.js +16 -6
- package/src/runtime/lifecycle/event-store.js +8 -6
- package/src/runtime/lifecycle/followup.js +6 -1
- package/src/runtime/lifecycle/overview.js +24 -1
- package/src/runtime/lifecycle/report-store.js +8 -10
- package/src/runtime/lifecycle/retention.js +95 -31
- package/src/runtime/lifecycle/root.js +9 -1
- package/src/runtime/lifecycle/status.js +34 -17
- package/src/runtime/lifecycle/store-upkeep.js +56 -7
- package/src/runtime/mask.js +134 -7
- package/src/runtime/mcp-consultations.js +40 -6
- package/src/runtime/model-router.js +79 -7
- package/src/runtime/models/catalogue.js +191 -0
- package/src/runtime/models/command.js +153 -0
- package/src/runtime/off-words.js +12 -0
- package/src/runtime/outcome.js +3 -3
- package/src/runtime/packages/command.js +1009 -0
- package/src/runtime/packages/contributions.js +116 -0
- package/src/runtime/packages/digest.js +132 -0
- package/src/runtime/packages/fetch.js +182 -0
- package/src/runtime/packages/grants.js +192 -0
- package/src/runtime/packages/index-file.js +134 -0
- package/src/runtime/packages/instruction.js +90 -0
- package/src/runtime/packages/manifest.js +331 -0
- package/src/runtime/packages/points.js +477 -0
- package/src/runtime/packages/programs.js +216 -0
- package/src/runtime/packages/scaffold.js +277 -0
- package/src/runtime/packages/source.js +90 -0
- package/src/runtime/packages/state.js +164 -0
- package/src/runtime/packages/store.js +449 -0
- package/src/runtime/packages/tar.js +106 -0
- package/src/runtime/packages/view.js +406 -0
- package/src/runtime/plan-check.js +59 -0
- package/src/runtime/plan-content.js +324 -0
- package/src/runtime/policy-init.js +118 -0
- package/src/runtime/profiles/doctor.js +96 -0
- package/src/runtime/profiles/resolve.js +244 -0
- package/src/runtime/profiles/rollback.js +254 -0
- package/src/runtime/profiles/sampler.js +41 -0
- package/src/runtime/readiness-record.js +16 -11
- package/src/runtime/readiness.js +127 -16
- package/src/runtime/research-request.js +50 -25
- package/src/runtime/retrieval-plan.js +402 -73
- package/src/runtime/retrieval-record.js +293 -0
- package/src/runtime/review/command.js +246 -0
- package/src/runtime/review/dominance.js +68 -0
- package/src/runtime/review/findings.js +434 -0
- package/src/runtime/review/identity.js +255 -0
- package/src/runtime/review/protocol-command.js +109 -0
- package/src/runtime/review/protocols.js +405 -0
- package/src/runtime/review/resolve-protocol.js +302 -0
- package/src/runtime/review/start.js +530 -0
- package/src/runtime/roadmap/facts.js +479 -0
- package/src/runtime/roadmap/gates.js +270 -0
- package/src/runtime/roadmap/loop.js +1636 -0
- package/src/runtime/roadmap/merge.js +381 -0
- package/src/runtime/roadmap/rows.js +1113 -0
- package/src/runtime/roadmap/seed.js +951 -0
- package/src/runtime/rules-report.js +336 -0
- package/src/runtime/scaffold/artifacts.js +63 -9
- package/src/runtime/scaffold/generate.js +21 -9
- package/src/runtime/settings/autopilot.js +106 -0
- package/src/runtime/settings/cli.js +280 -0
- package/src/runtime/settings/config-write.js +314 -0
- package/src/runtime/settings/files.js +271 -0
- package/src/runtime/settings/legacy.js +154 -0
- package/src/runtime/settings/lexical.js +56 -0
- package/src/runtime/settings/prepared-run.js +269 -0
- package/src/runtime/settings/project-layers.js +118 -0
- package/src/runtime/settings/refs.js +288 -0
- package/src/runtime/settings/registry.js +553 -0
- package/src/runtime/settings/resolve.js +713 -0
- package/src/runtime/settings/shared.js +37 -0
- package/src/runtime/settings/worker-billing.js +107 -0
- package/src/runtime/settings/write.js +269 -0
- package/src/runtime/slot-command.js +78 -0
- package/src/runtime/slots.js +671 -0
- package/src/runtime/source-version.js +290 -0
- package/src/runtime/state-root.js +217 -0
- package/src/runtime/storage/cli.js +12 -5
- package/src/runtime/storage/engine.js +9 -2
- package/src/runtime/storage/registry.js +14 -1
- package/src/runtime/storage/roots.js +66 -16
- package/src/runtime/storage/rules.js +82 -10
- package/src/runtime/storage/upkeep.js +10 -2
- package/src/runtime/storage/work-status.js +245 -26
- package/src/runtime/task-attempts.js +589 -69
- package/src/runtime/task-classifier.js +47 -11
- package/src/runtime/task-graph.js +373 -0
- package/src/runtime/task-run.js +778 -0
- package/src/runtime/task-scope.js +202 -56
- package/src/runtime/task-sources.js +147 -0
- package/src/runtime/task-state.js +440 -65
- package/src/runtime/team/admission.js +301 -0
- package/src/runtime/team/envelope.js +324 -0
- package/src/runtime/team/review-guard.js +156 -0
- package/src/runtime/trace/analyze.js +427 -0
- package/src/runtime/trace/baseline.js +770 -0
- package/src/runtime/trace/ledger.js +63 -140
- package/src/runtime/trace/otlp-export.js +568 -0
- package/src/runtime/trace/otlp-map.js +481 -0
- package/src/runtime/trace/spans.js +745 -0
- package/src/runtime/trace/telemetry.js +225 -0
- package/src/runtime/trace/views.js +1 -0
- package/src/runtime/transcripts/command.js +98 -0
- package/src/runtime/transcripts/cursor.js +326 -0
- package/src/runtime/transcripts/read.js +126 -0
- package/src/runtime/transcripts/readers/claude-jsonl.js +74 -0
- package/src/runtime/transcripts/readers/codex-rollout.js +70 -0
- package/src/runtime/transcripts/readers/copilot-events.js +90 -0
- package/src/runtime/transcripts/readers/kiro-jsonl.js +77 -0
- package/src/runtime/transcripts/readers/pi-jsonl.js +59 -0
- package/src/runtime/transcripts/registry.js +161 -0
- package/src/runtime/transcripts/stats.js +161 -0
- package/src/runtime/verification/check-key.js +628 -0
- package/src/runtime/verification/contract-runner.js +546 -11
- package/src/runtime/verification/engine.js +499 -9
- package/src/runtime/verification/impact.js +617 -0
- package/src/runtime/verification/inflight.js +205 -0
- package/src/runtime/verification/registry.js +176 -0
- package/src/runtime/verification/reuse.js +184 -0
- package/src/runtime/verification/telemetry-emit.js +254 -0
- package/src/runtime/verification/test-selection.js +67 -7
- package/src/runtime/worker/active.js +90 -0
- package/src/runtime/worker/cancel.js +222 -0
- package/src/runtime/worker/catalogue.js +122 -0
- package/src/runtime/worker/command.js +677 -0
- package/src/runtime/worker/evidence.js +288 -0
- package/src/runtime/worker/launch.js +288 -0
- package/src/runtime/worker/models.js +137 -0
- package/src/runtime/worker/parsers.js +218 -0
- package/src/runtime/worker/probes/index.js +706 -0
- package/src/runtime/worker/process-tree.js +415 -0
- package/src/runtime/worker/quota.js +43 -0
- package/src/runtime/worker/readiness.js +713 -0
- package/src/runtime/worker/run-store.js +166 -0
- package/src/runtime/worker/supervisor.js +541 -0
- package/src/runtime/worker/worktree-check.js +252 -0
- package/src/runtime/workflow-engine.js +5 -1
- package/src/runtime/workflow-orchestrator.js +578 -63
- package/src/runtime/worktree.js +149 -22
- package/src/state/index.js +1 -1
- package/src/state/lockfile.js +64 -10
- package/src/state/run-lock.js +1 -1
- package/types/node-commonjs.d.ts +106 -7
- package/core/.antigravity-plugin/hooks.json +0 -39
- package/core/harnesses/gemini/hooks/hooks.json +0 -77
- package/core/harnesses/gemini/hooks/lib.sh +0 -302
- package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +0 -21
- package/core/harnesses/gemini/hooks/post-edit-lint.sh +0 -39
- package/core/harnesses/gemini/hooks/pre-bash-guard.sh +0 -21
- package/core/harnesses/gemini/hooks/pre-compact.sh +0 -38
- package/core/harnesses/gemini/hooks/pre-implement-gate.sh +0 -22
- package/core/harnesses/gemini/hooks/session-end.impl.sh +0 -89
- package/core/harnesses/gemini/hooks/session-end.sh +0 -5
- package/core/harnesses/gemini/hooks/session-start.sh +0 -5
- package/core/harnesses/gemini/settings/adapter-defaults.json +0 -4
- package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
- package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
- package/core/harnesses/shared/hooks/hooks.json +0 -47
- package/core/shared/guidance/FLAGS.md +0 -25
- package/core/shared/guidance/rules/RULE_01_SAFETY.md +0 -25
- package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +0 -23
- package/core/shared/guidance/rules/RULE_03_QUALITY.md +0 -14
- package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +0 -46
- package/src/adapters/gemini/hooks.js +0 -210
- package/src/adapters/gemini/index.js +0 -390
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Gemini CLI payload/decision adapter for the Cross-Harness Hook Runner (design.md C2's
|
|
5
|
-
* Payload Adapter / Decision Adapter seam, D2).
|
|
6
|
-
*
|
|
7
|
-
* Gemini's own native contract — evidenced by core/harnesses/gemini/hooks/*.sh and
|
|
8
|
-
* core/harnesses/gemini/hooks/hooks.json, all currently invoked directly by bash rather than
|
|
9
|
-
* through this runner — already speaks field names close to Claude/Codex/Kiro's, NOT
|
|
10
|
-
* Antigravity's toolCall/args envelope:
|
|
11
|
-
*
|
|
12
|
-
* SessionStart : stdin { session_id, cwd } (session-start.sh)
|
|
13
|
-
* BeforeTool (~PreToolUse): stdin { tool_name, tool_input: { file_path, command } }
|
|
14
|
-
* stdout { decision: "allow"|"deny", reason } — TOP-LEVEL, not
|
|
15
|
-
* nested under hookSpecificOutput.permissionDecision like
|
|
16
|
-
* Claude/Codex (confirmed in gemini/hooks/pre-bash-guard.sh's header).
|
|
17
|
-
* AfterTool (~PostToolUse): stdin { tool_name, tool_input: { file_path }, session_id }
|
|
18
|
-
* (post-edit-lint.sh) — stdout {} (ack; no Phase A policy owns this
|
|
19
|
-
* event, post-edit-lint.sh's collector role is out of FR-001's scope)
|
|
20
|
-
* Stop : NOT a documented Gemini lifecycle event — gemini/hooks/
|
|
21
|
-
* post-edit-lint.sh's own comment states "Gemini has no
|
|
22
|
-
* Stop-equivalent event," and no stop-check.sh ships under
|
|
23
|
-
* gemini/hooks/ today. Handled defensively below (same field-name
|
|
24
|
-
* union stop-check.sh itself accepts) in case a future Gemini
|
|
25
|
-
* version adds one, or in case core/harnesses/shared/hooks/hooks.json's
|
|
26
|
-
* existing (currently dangling) Stop entry is corrected to a real target.
|
|
27
|
-
*
|
|
28
|
-
* NFR-002 note: core/harnesses/shared/hooks/hooks.json has historically routed PreToolUse through
|
|
29
|
-
* this runner using Antigravity's { toolCall: { name, args } } envelope — inherited from this
|
|
30
|
-
* runner's original Antigravity-only design (see the runner's own prior header comment), not
|
|
31
|
-
* verified against Gemini's own documented schema above. toCanonical() below reads the
|
|
32
|
-
* tool_name/tool_input shape first (Gemini's own evidenced contract) and falls back to the
|
|
33
|
-
* toolCall envelope only if that shape isn't present, so this adapter is correct once that
|
|
34
|
-
* wiring is corrected without silently breaking before it is.
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
const { FILE_PATH_ARG_FIELDS, COMMAND_ARG_FIELDS, firstArgField } = require('./arg-fields');
|
|
38
|
-
|
|
39
|
-
function toCanonical(event, payload) {
|
|
40
|
-
const safePayload = payload && typeof payload === 'object' ? payload : {};
|
|
41
|
-
|
|
42
|
-
switch (event) {
|
|
43
|
-
case 'SessionStart':
|
|
44
|
-
return { session_id: safePayload.session_id || '', cwd: safePayload.cwd || '' };
|
|
45
|
-
|
|
46
|
-
case 'PreToolUse': {
|
|
47
|
-
if (safePayload.tool_name !== undefined || safePayload.tool_input !== undefined) {
|
|
48
|
-
const toolInput = safePayload.tool_input || {};
|
|
49
|
-
return {
|
|
50
|
-
tool_name: safePayload.tool_name || '',
|
|
51
|
-
tool_input: {
|
|
52
|
-
file_path: toolInput.file_path || '',
|
|
53
|
-
command: toolInput.command || '',
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
// Defensive fallback: Antigravity-shaped envelope (see header note).
|
|
58
|
-
const toolCall = safePayload.toolCall || {};
|
|
59
|
-
const args = toolCall.args || {};
|
|
60
|
-
return {
|
|
61
|
-
tool_name: toolCall.name || '',
|
|
62
|
-
tool_input: {
|
|
63
|
-
file_path: firstArgField(args, FILE_PATH_ARG_FIELDS),
|
|
64
|
-
command: firstArgField(args, COMMAND_ARG_FIELDS),
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
case 'PostToolUse':
|
|
70
|
-
return {
|
|
71
|
-
tool_name: safePayload.tool_name || '',
|
|
72
|
-
session_id: safePayload.session_id || '',
|
|
73
|
-
tool_input: { file_path: (safePayload.tool_input && safePayload.tool_input.file_path) || '' },
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
case 'Stop':
|
|
77
|
-
return {
|
|
78
|
-
session_id: safePayload.session_id || '',
|
|
79
|
-
transcript_path: safePayload.transcript_path || safePayload.transcriptPath || '',
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
default:
|
|
83
|
-
return safePayload;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function toNative(event, decision) {
|
|
88
|
-
const safeDecision = decision || { decision: 'allow' };
|
|
89
|
-
|
|
90
|
-
switch (event) {
|
|
91
|
-
case 'PreToolUse':
|
|
92
|
-
if (safeDecision.decision === 'deny') {
|
|
93
|
-
return { decision: 'deny', reason: safeDecision.reason };
|
|
94
|
-
}
|
|
95
|
-
return { decision: 'allow' };
|
|
96
|
-
|
|
97
|
-
case 'PostToolUse':
|
|
98
|
-
return {};
|
|
99
|
-
|
|
100
|
-
case 'Stop':
|
|
101
|
-
if (safeDecision.decision === 'deny') {
|
|
102
|
-
return { decision: 'deny', reason: safeDecision.reason };
|
|
103
|
-
}
|
|
104
|
-
return { decision: 'allow' };
|
|
105
|
-
|
|
106
|
-
case 'SessionStart':
|
|
107
|
-
return {};
|
|
108
|
-
|
|
109
|
-
default:
|
|
110
|
-
return { decision: 'allow' };
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
module.exports = { toCanonical, toNative };
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"description": "DoFlow shared lifecycle hooks schema for Antigravity, Gemini, and Claude.",
|
|
3
|
-
"hooks": {
|
|
4
|
-
"SessionStart": [
|
|
5
|
-
{
|
|
6
|
-
"hooks": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"command": "bash \"$DOFLOW_PROJECT_DIR/.gemini/hooks/session-start.sh\""
|
|
10
|
-
}
|
|
11
|
-
]
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"PreToolUse": [
|
|
15
|
-
{
|
|
16
|
-
"matcher": "^(run_command|run_shell_command|replace_file_content|write_to_file|multi_replace_file_content|edit_file|Edit|Write)$",
|
|
17
|
-
"hooks": [
|
|
18
|
-
{
|
|
19
|
-
"type": "command",
|
|
20
|
-
"command": "node \"$DOFLOW_PROJECT_DIR/.doflow/scripts/stream-hook-runner.js\""
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
"PostToolUse": [
|
|
26
|
-
{
|
|
27
|
-
"matcher": "^(replace_file_content|write_to_file|multi_replace_file_content|edit_file|Edit|Write)$",
|
|
28
|
-
"hooks": [
|
|
29
|
-
{
|
|
30
|
-
"type": "command",
|
|
31
|
-
"command": "bash \"$DOFLOW_PROJECT_DIR/.gemini/hooks/post-edit-lint.sh\""
|
|
32
|
-
}
|
|
33
|
-
]
|
|
34
|
-
}
|
|
35
|
-
],
|
|
36
|
-
"Stop": [
|
|
37
|
-
{
|
|
38
|
-
"hooks": [
|
|
39
|
-
{
|
|
40
|
-
"type": "command",
|
|
41
|
-
"command": "bash \"$DOFLOW_PROJECT_DIR/.gemini/hooks/stop-check.sh\""
|
|
42
|
-
}
|
|
43
|
-
]
|
|
44
|
-
}
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Runtime Behavior and Flags
|
|
2
|
-
|
|
3
|
-
Loaded into **every** session on every harness. What a flag used to request is now mostly
|
|
4
|
-
unconditional, so this states the behavior once rather than listing knobs.
|
|
5
|
-
|
|
6
|
-
## Always on
|
|
7
|
-
|
|
8
|
-
**Readiness gating** — a stage that edits source is graded against its class contract first;
|
|
9
|
-
the verdict is one of four states, never a number.
|
|
10
|
-
**Recovery bounds** — a failed verification is classified and retried under a bound the runtime
|
|
11
|
-
sets. You do not pick a cycle count.
|
|
12
|
-
**Run tracing** — every runtime call is recorded as it happens and read back; where a run
|
|
13
|
-
stopped is read from that record, never reconstructed.
|
|
14
|
-
**Capability routing** — an information need resolves to a provider healthy on this machine, not to
|
|
15
|
-
a habitual tool.
|
|
16
|
-
|
|
17
|
-
## Flags
|
|
18
|
-
|
|
19
|
-
What the user typed beats auto-detection. Every flag belongs to one skill and is declared in that
|
|
20
|
-
skill's `argument-hint`, except this one, which crosses them:
|
|
21
|
-
|
|
22
|
-
**--focus [quality|security|performance|architecture]** — narrows analysis to one domain. Consumed
|
|
23
|
-
by `do-diagnose`.
|
|
24
|
-
|
|
25
|
-
MCP short flags are generated per install into `MCP_INDEX.md`; this file names no server.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Safety Rules (CRITICAL)
|
|
2
|
-
|
|
3
|
-
## Priority System
|
|
4
|
-
**CRITICAL** — Security, data safety, production — never compromise
|
|
5
|
-
**IMPORTANT** — Quality, maintainability, professionalism — strong preference
|
|
6
|
-
**RECOMMENDED** — Optimization, style, best practices — apply when practical
|
|
7
|
-
|
|
8
|
-
Conflict order: Safety > Scope > Quality > Speed. Prototype != Production requirements.
|
|
9
|
-
|
|
10
|
-
<important if="debugging, fixing a bug, or investigating a failure">
|
|
11
|
-
## Failure Investigation
|
|
12
|
-
- Root cause always — understand WHY, not just THAT; fix the cause, not the symptom
|
|
13
|
-
- Never skip/disable/comment-out tests or validation to pass builds
|
|
14
|
-
</important>
|
|
15
|
-
|
|
16
|
-
<important if="performing git operations or starting work on a codebase">
|
|
17
|
-
## Git Workflow
|
|
18
|
-
- `git status && git branch` first; feature branches for ALL work; never force-push main
|
|
19
|
-
- Commit incrementally with descriptive messages; `git diff` before staging; restore-point commit
|
|
20
|
-
before anything risky
|
|
21
|
-
</important>
|
|
22
|
-
|
|
23
|
-
## Temporal Awareness
|
|
24
|
-
- Read the date from `<env>` before any temporal claim; never infer it from your knowledge cutoff,
|
|
25
|
-
and state its source
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Workflow Rules
|
|
2
|
-
|
|
3
|
-
## Planning
|
|
4
|
-
- **Parallel by default** — sequential only for hard dependencies; a task list once past 3 tasks, when the session offers one
|
|
5
|
-
- Validate before execution, verify after; run lint/typecheck before marking complete
|
|
6
|
-
- Check deps (package.json) and existing patterns before any changes
|
|
7
|
-
- Feature delivery follows the doflow chain — see `references/DOFLOW_CHAIN.md` for the phase-gated
|
|
8
|
-
flow, artifact contracts, and the enforced gate
|
|
9
|
-
|
|
10
|
-
<important if="planning or starting a multi-step task">
|
|
11
|
-
## Planning Efficiency
|
|
12
|
-
- Identify concurrent vs sequential operations
|
|
13
|
-
- Map dependencies; batch tool calls; estimate parallelization gains
|
|
14
|
-
</important>
|
|
15
|
-
|
|
16
|
-
## Implementation Completeness
|
|
17
|
-
- Start it = Finish it. No partial features, TODO stubs, mocks, or "not implemented" throws
|
|
18
|
-
- All generated code must work as specified; no scaffolding placeholders
|
|
19
|
-
|
|
20
|
-
## Scope Discipline
|
|
21
|
-
- Build ONLY what's asked — no bonus features, no enterprise bloat (auth/monitoring/deployment
|
|
22
|
-
unless requested)
|
|
23
|
-
- MVP first; YAGNI; single responsibility per component
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Quality Rules
|
|
2
|
-
|
|
3
|
-
## Organization & Hygiene
|
|
4
|
-
**Naming**: Follow language standards (camelCase JS, snake_case Python); no mixed conventions
|
|
5
|
-
**Files**: Organize by feature/domain; tests → `tests/`; scripts → `scripts/`; reports → `agent-docs/`
|
|
6
|
-
**Workspace**: Remove temp files, debug scripts, build artifacts after use; never leave clutter in VCS
|
|
7
|
-
|
|
8
|
-
## Professional Honesty
|
|
9
|
-
- No marketing language ("blazingly fast", "100% secure", "magnificent")
|
|
10
|
-
- No invented sources, figures, citations or quotes; leave out what you cannot trace; state "untested/MVP/needs validation" honestly
|
|
11
|
-
- If you are not sure, say so plainly and name what is unknown; do not present a guess as established
|
|
12
|
-
- Warn when a claim may be outdated: information from memory or an old source can have changed since it was written
|
|
13
|
-
- Never attribute a statement or view to a real person unless you have verified it; otherwise omit the name
|
|
14
|
-
- Push back on bad approaches; evidence-based claims only
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# Question & Clarification Rules
|
|
2
|
-
|
|
3
|
-
## When to Ask
|
|
4
|
-
- Ask ONLY for genuine user-owned decisions unresolved by the request, the code, or sensible defaults
|
|
5
|
-
- Enough to act → act; don't ask to confirm the obvious (see RULE_02 Scope Discipline)
|
|
6
|
-
- One question that unblocks beats three that re-litigate settled choices
|
|
7
|
-
|
|
8
|
-
<important if="asking the user a clarifying question or choosing between approaches">
|
|
9
|
-
## How to Ask (MANDATORY format)
|
|
10
|
-
Structured multiple-choice — never a free-form question buried in prose.
|
|
11
|
-
- **A native question tool exists in this session** (Claude Code's `AskUserQuestion`, or any
|
|
12
|
-
harness tool that presents options and returns the user's choice): use it. Which harness this
|
|
13
|
-
is is not the test — what THIS session offers is; Codex and Gemini sessions increasingly
|
|
14
|
-
carry one.
|
|
15
|
-
- **No native question tool** (truly non-interactive runs): write a `{stage}-questions.md` file
|
|
16
|
-
with `[Answer]:` tags — the fallback, never the preference.
|
|
17
|
-
|
|
18
|
-
Each question:
|
|
19
|
-
- 2–4 **meaningful, mutually-exclusive** options covering the real scenarios
|
|
20
|
-
- NEVER invent filler; an "Other"/free-text escape is always the last choice
|
|
21
|
-
- One topic per question; specific and unambiguous; lead with your recommended default
|
|
22
|
-
</important>
|
|
23
|
-
|
|
24
|
-
<important if="writing a question file because this session has no native question tool">
|
|
25
|
-
## Question-File Format
|
|
26
|
-
```markdown
|
|
27
|
-
## Question 1 — [the question]
|
|
28
|
-
A) [option] B) [option] X) Other (free text after the tag)
|
|
29
|
-
|
|
30
|
-
[Answer]:
|
|
31
|
-
```
|
|
32
|
-
Naming: `{stage}-questions.md` (e.g. `spec-questions.md`) in the directory the stage writes
|
|
33
|
-
its output to — not a fixed path outside the repo's layout.
|
|
34
|
-
|
|
35
|
-
Lifecycle: write the file → tell the user and wait for "done" → read answers →
|
|
36
|
-
**Validate Before Proceeding** (below) → act. A missing `[Answer]:`, or one that is not a listed
|
|
37
|
-
letter, means ask again — never guess, and never reinterpret free text as a letter choice.
|
|
38
|
-
</important>
|
|
39
|
-
|
|
40
|
-
<important if="reading the user's answers before you act on them">
|
|
41
|
-
## Validate Before Proceeding
|
|
42
|
-
- Scan answers for contradictions (scope vs risk, quick fix vs multi-subsystem) and ambiguity
|
|
43
|
-
- Conflict found → name it and ask one targeted follow-up in `{stage}-clarification-questions.md`,
|
|
44
|
-
same format, citing the conflicting answer; never proceed on an unresolved contradiction, and
|
|
45
|
-
never assume an answer to an ambiguous response
|
|
46
|
-
</important>
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
4
|
-
|
|
5
|
-
// Gemini hook planning. Unlike Codex (which owns a standalone hooks.json file), Gemini's hooks
|
|
6
|
-
// live as a "hooks" key inside settings.json — a file DoFlow does not fully own (it commonly
|
|
7
|
-
// pre-exists with unrelated content: mcpServers, ui, telemetry, model, etc.). planGeminiHooks
|
|
8
|
-
// therefore returns a key-scoped merge plan, never a full-file replace.
|
|
9
|
-
//
|
|
10
|
-
// NOTE: validateHooksConfig below intentionally duplicates codex-hooks.js's shape-checking logic
|
|
11
|
-
// (event -> array of {matcher, hooks:[{type,command,...}]} groups) rather than sharing it, since
|
|
12
|
-
// unifying it would mean introducing a new shared module beyond this feature's planned scope
|
|
13
|
-
// (agent-docs/doflow/013-codex-gemini-hooks-parity/plan.md's component list). Worth factoring out
|
|
14
|
-
// if a third harness with the same shape is ever added.
|
|
15
|
-
const fs = require('node:fs');
|
|
16
|
-
const path = require('node:path');
|
|
17
|
-
const { verifyHookCommands } = require('../hook-commands.js');
|
|
18
|
-
const { mergeHooks } = require('../../helper/settings-merge.js');
|
|
19
|
-
|
|
20
|
-
const SUPPORTED_EVENTS = new Set([
|
|
21
|
-
'SessionStart', 'SessionEnd', 'BeforeAgent', 'AfterAgent', 'BeforeModel', 'AfterModel',
|
|
22
|
-
'BeforeToolSelection', 'BeforeTool', 'AfterTool', 'PreCompress', 'Notification',
|
|
23
|
-
]);
|
|
24
|
-
|
|
25
|
-
// Claude guardrail event -> Gemini event, only where a real Gemini event has matching semantics
|
|
26
|
-
// (source: geminicli.com/docs/hooks/reference.md). UserPromptSubmit,
|
|
27
|
-
// Stop, SubagentStart/Stop, and ConfigChange have no correct Gemini equivalent and are
|
|
28
|
-
// intentionally omitted rather than approximated onto BeforeAgent/AfterAgent (design.md §7/§8 —
|
|
29
|
-
// no false parity).
|
|
30
|
-
const CLAUDE_TO_GEMINI_EVENT = {
|
|
31
|
-
SessionStart: 'SessionStart',
|
|
32
|
-
SessionEnd: 'SessionEnd',
|
|
33
|
-
PreToolUse: 'BeforeTool',
|
|
34
|
-
PostToolUse: 'AfterTool',
|
|
35
|
-
PreCompact: 'PreCompress',
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
function validationError(errors , message ) { errors.push(message); }
|
|
39
|
-
|
|
40
|
-
function validateHooksConfig(config ) {
|
|
41
|
-
const errors = [];
|
|
42
|
-
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
43
|
-
return { ok: false, errors: ['Hook configuration must be an object'], events: [] };
|
|
44
|
-
}
|
|
45
|
-
if (!config.hooks || typeof config.hooks !== 'object' || Array.isArray(config.hooks)) {
|
|
46
|
-
return { ok: false, errors: ['Hook configuration requires a hooks object'], events: [] };
|
|
47
|
-
}
|
|
48
|
-
for (const [event, groups] of Object.entries(config.hooks)) {
|
|
49
|
-
if (!SUPPORTED_EVENTS.has(event)) {
|
|
50
|
-
validationError(errors, `Unsupported Gemini hook event '${event}'`);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
if (!Array.isArray(groups) || groups.length === 0) {
|
|
54
|
-
validationError(errors, `Hook event '${event}' requires a non-empty array of matcher groups`);
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
groups.forEach((group , groupIndex ) => {
|
|
58
|
-
if (!group || typeof group !== 'object' || Array.isArray(group)) {
|
|
59
|
-
validationError(errors, `Hook event '${event}' group ${groupIndex} must be an object`);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (group.matcher !== undefined && typeof group.matcher !== 'string') {
|
|
63
|
-
validationError(errors, `Hook event '${event}' group ${groupIndex} matcher must be a string`);
|
|
64
|
-
}
|
|
65
|
-
if (!Array.isArray(group.hooks) || group.hooks.length === 0) {
|
|
66
|
-
validationError(errors, `Hook event '${event}' group ${groupIndex} requires a non-empty hooks array`);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
group.hooks.forEach((handler , handlerIndex ) => {
|
|
70
|
-
const label = `Hook event '${event}' group ${groupIndex} handler ${handlerIndex}`;
|
|
71
|
-
if (!handler || typeof handler !== 'object' || Array.isArray(handler)) {
|
|
72
|
-
validationError(errors, `${label} must be an object`); return;
|
|
73
|
-
}
|
|
74
|
-
if (handler.type !== 'command') validationError(errors, `${label} must have type 'command'`);
|
|
75
|
-
if (typeof handler.command !== 'string' || !handler.command.trim()) {
|
|
76
|
-
validationError(errors, `${label} requires a non-empty command string`);
|
|
77
|
-
}
|
|
78
|
-
if (handler.timeout !== undefined && typeof handler.timeout !== 'number') {
|
|
79
|
-
validationError(errors, `${label} timeout must be a number`);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
return { ok: errors.length === 0, errors, events: Object.keys(config.hooks) };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** Maps Claude guardrail intent, never fabricating a Gemini equivalent for unavailable events. */
|
|
88
|
-
function classifyClaudeGuardrails(claudeHooks = {}) {
|
|
89
|
-
const supported = [];
|
|
90
|
-
const unsupported = [];
|
|
91
|
-
for (const [event, groups] of Object.entries(claudeHooks || {})) {
|
|
92
|
-
const targetEvent = CLAUDE_TO_GEMINI_EVENT[event] || null;
|
|
93
|
-
const item = { sourceEvent: event, targetEvent, groups: Array.isArray(groups) ? groups.length : 0 };
|
|
94
|
-
if (targetEvent) supported.push(item);
|
|
95
|
-
else unsupported.push({ ...item, reason: `Gemini has no equivalent lifecycle event for Claude's '${event}'` });
|
|
96
|
-
}
|
|
97
|
-
return { supported, unsupported };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Plan a key-scoped merge of a "hooks" config into an existing (or absent) settings.json, never
|
|
102
|
-
* touching any other key. Mirrors src/mcp.js's readJsonOrThrow discipline: a settings.json that
|
|
103
|
-
* exists but fails to parse is a hard error, not silently treated as empty (this path merges
|
|
104
|
-
* into content DoFlow does not own — a malformed-file work-around here risks losing it).
|
|
105
|
-
*/
|
|
106
|
-
function planGeminiHooks({ config, sourceFile, sourceHooksDir, settingsFile, destinationHooksDir: declaredHooksDir, trusted = false, fsImpl = fs } = {}) {
|
|
107
|
-
let desired = config;
|
|
108
|
-
try {
|
|
109
|
-
if (!desired && sourceFile) desired = JSON.parse(fsImpl.readFileSync(sourceFile, 'utf8'));
|
|
110
|
-
} catch (error ) {
|
|
111
|
-
return { ok: false, status: 'malformed', changes: [], errors: [`Could not parse ${sourceFile}: ${error.message}`] };
|
|
112
|
-
}
|
|
113
|
-
if (!settingsFile) return { ok: false, status: 'invalid-request', changes: [], errors: ['settingsFile is required'] };
|
|
114
|
-
const schema = validateHooksConfig(desired);
|
|
115
|
-
const commands = verifyHookCommands(desired || {}, { scriptsDir: sourceHooksDir, trusted, fsImpl });
|
|
116
|
-
const errors = [...schema.errors, ...commands.checks.filter((check ) => !check.ok).map((check ) => `${check.event}: ${check.reason}${check.script ? ` (${check.script})` : ''}`)];
|
|
117
|
-
|
|
118
|
-
let existing = {};
|
|
119
|
-
if (fsImpl.existsSync(settingsFile)) {
|
|
120
|
-
try { existing = JSON.parse(fsImpl.readFileSync(settingsFile, 'utf8')); }
|
|
121
|
-
catch (error ) { return { ok: false, status: 'malformed', changes: [], errors: [`Refusing to touch malformed ${settingsFile}: ${error.message}`] }; }
|
|
122
|
-
}
|
|
123
|
-
if (errors.length) return { ok: false, status: 'invalid-request', settingsFile, existing, changes: [], errors, commands };
|
|
124
|
-
|
|
125
|
-
const mergedHooks = existing.hooks ? mergeHooks(existing.hooks, desired.hooks) : desired.hooks;
|
|
126
|
-
const merged = { ...existing, hooks: mergedHooks };
|
|
127
|
-
const changed = JSON.stringify(existing.hooks) !== JSON.stringify(mergedHooks);
|
|
128
|
-
// Preferred: the declared hooks directory (harnesses.json "paths".hooksDirectory); the derived
|
|
129
|
-
// sibling-of-settings fallback stays for direct callers passing raw inputs, and resolves to the
|
|
130
|
-
// same location.
|
|
131
|
-
const destinationHooksDir = declaredHooksDir || path.join(path.dirname(settingsFile), 'hooks');
|
|
132
|
-
// The scripts deployGeminiHooks copies beside settings.json, so a backup of this change holds them too.
|
|
133
|
-
const shipped = sourceHooksDir && fsImpl.existsSync(sourceHooksDir)
|
|
134
|
-
? fsImpl.readdirSync(sourceHooksDir).filter((name ) => !name.endsWith('.json') && fsImpl.statSync(path.join(sourceHooksDir, name)).isFile())
|
|
135
|
-
: [];
|
|
136
|
-
const companionTargets = [...new Set([
|
|
137
|
-
...commands.checks.map((check ) => path.join(destinationHooksDir, check.script)),
|
|
138
|
-
...shipped.map((name ) => path.join(destinationHooksDir, name)),
|
|
139
|
-
])].sort();
|
|
140
|
-
return { ok: true, status: changed ? 'change' : 'unchanged', settingsFile, existing, merged,
|
|
141
|
-
changes: changed ? [{ type: fsImpl.existsSync(settingsFile) ? 'update' : 'create', file: settingsFile, key: 'hooks' }] : [],
|
|
142
|
-
errors: [], commands, trust: commands.trust, scriptsDir: sourceHooksDir, destinationHooksDir, companionTargets };
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function deployGeminiHooks(plan , { dryRun = false, fsImpl = fs } = {}) {
|
|
146
|
-
if (!plan.ok) return { ...plan, applied: false };
|
|
147
|
-
if (dryRun || plan.status === 'unchanged') return { ...plan, applied: false };
|
|
148
|
-
fsImpl.mkdirSync(path.dirname(plan.settingsFile), { recursive: true });
|
|
149
|
-
const content = `${JSON.stringify(plan.merged, null, 2)}\n`;
|
|
150
|
-
const temporary = path.join(path.dirname(plan.settingsFile), `.${path.basename(plan.settingsFile)}.${process.pid}.${Date.now()}.tmp`);
|
|
151
|
-
try {
|
|
152
|
-
fsImpl.writeFileSync(temporary, content, { flag: 'wx' });
|
|
153
|
-
fsImpl.renameSync(temporary, plan.settingsFile);
|
|
154
|
-
} finally {
|
|
155
|
-
if (fsImpl.existsSync(temporary)) fsImpl.unlinkSync(temporary);
|
|
156
|
-
}
|
|
157
|
-
const deployed = new Set ();
|
|
158
|
-
for (const check of plan.commands.checks) {
|
|
159
|
-
const target = path.join(plan.destinationHooksDir, check.script);
|
|
160
|
-
fsImpl.mkdirSync(path.dirname(target), { recursive: true });
|
|
161
|
-
fsImpl.copyFileSync(check.file, target);
|
|
162
|
-
fsImpl.chmodSync(target, fsImpl.statSync(check.file).mode & 0o777);
|
|
163
|
-
deployed.add(check.script);
|
|
164
|
-
}
|
|
165
|
-
if (plan.scriptsDir && fsImpl.existsSync(plan.scriptsDir)) {
|
|
166
|
-
for (const name of fsImpl.readdirSync(plan.scriptsDir)) {
|
|
167
|
-
if (deployed.has(name) || name.endsWith('.json')) continue;
|
|
168
|
-
const source = path.join(plan.scriptsDir, name);
|
|
169
|
-
if (!fsImpl.statSync(source).isFile()) continue;
|
|
170
|
-
const target = path.join(plan.destinationHooksDir, name);
|
|
171
|
-
fsImpl.mkdirSync(path.dirname(target), { recursive: true });
|
|
172
|
-
fsImpl.copyFileSync(source, target);
|
|
173
|
-
fsImpl.chmodSync(target, fsImpl.statSync(source).mode & 0o777);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return { ...plan, applied: true };
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Plan stripping just the "hooks" key back out of settings.json — mirrors this codebase's
|
|
181
|
-
* existing GEMINI.md-instructions removal (structural presence check, not a ledger fingerprint
|
|
182
|
-
* cross-check): if the key isn't present, there's nothing to do; otherwise propose removing only
|
|
183
|
-
* that key, leaving every other key in the shared file untouched (FR-002).
|
|
184
|
-
*/
|
|
185
|
-
function planRemoveGeminiHooks({ settingsFile, fsImpl = fs } = {}) {
|
|
186
|
-
if (!settingsFile) return { ok: false, status: 'invalid-request', changes: [], errors: ['settingsFile is required'] };
|
|
187
|
-
if (!fsImpl.existsSync(settingsFile)) return { ok: true, status: 'unchanged', settingsFile, changes: [] };
|
|
188
|
-
let existing;
|
|
189
|
-
try { existing = JSON.parse(fsImpl.readFileSync(settingsFile, 'utf8')); }
|
|
190
|
-
catch (error ) { return { ok: false, status: 'malformed', changes: [], errors: [`Could not parse ${settingsFile}: ${error.message}`] }; }
|
|
191
|
-
if (existing.hooks === undefined) return { ok: true, status: 'unchanged', settingsFile, changes: [] };
|
|
192
|
-
const { hooks: _dropped, ...merged } = existing;
|
|
193
|
-
return { ok: true, status: 'change', settingsFile, merged, changes: [{ type: 'update', file: settingsFile, key: 'hooks', operation: 'remove' }] };
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function deployRemoveGeminiHooks(plan , { dryRun = false, fsImpl = fs } = {}) {
|
|
197
|
-
if (!plan.ok || plan.status !== 'change' || dryRun) return { ...plan, applied: false };
|
|
198
|
-
fsImpl.mkdirSync(path.dirname(plan.settingsFile), { recursive: true });
|
|
199
|
-
const content = `${JSON.stringify(plan.merged, null, 2)}\n`;
|
|
200
|
-
const temporary = path.join(path.dirname(plan.settingsFile), `.${path.basename(plan.settingsFile)}.${process.pid}.${Date.now()}.tmp`);
|
|
201
|
-
try {
|
|
202
|
-
fsImpl.writeFileSync(temporary, content, { flag: 'wx' });
|
|
203
|
-
fsImpl.renameSync(temporary, plan.settingsFile);
|
|
204
|
-
} finally {
|
|
205
|
-
if (fsImpl.existsSync(temporary)) fsImpl.unlinkSync(temporary);
|
|
206
|
-
}
|
|
207
|
-
return { ...plan, applied: true };
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
module.exports = { SUPPORTED_EVENTS, validateHooksConfig, classifyClaudeGuardrails, verifyHookCommands, planGeminiHooks, deployGeminiHooks, planRemoveGeminiHooks, deployRemoveGeminiHooks };
|