@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,29 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
case "${OSTYPE:-}" in msys*|cygwin*|win32*) if command -v jq >/dev/null 2>&1; then jq() { command jq -b "$@"; }; fi ;; esac # native jq.exe ends lines with CRLF unless -b
|
|
3
|
+
_DOFLOW_SRC=${0//\\//}; case $_DOFLOW_SRC in */*) _DOFLOW_POLDIR=${_DOFLOW_SRC%/*} ;; *) _DOFLOW_POLDIR=. ;; esac
|
|
2
4
|
# pre-bash-guard.sh — Canonical Policy Library: PreToolUse(shell-command) hook
|
|
3
5
|
#
|
|
4
6
|
# Intercepts every shell-command tool call and blocks dangerous commands by
|
|
5
7
|
# matching against POSIX ERE patterns in blocked-patterns.conf (grep -E).
|
|
6
8
|
#
|
|
7
|
-
# Multi-session safe:
|
|
9
|
+
# Multi-session safe: reads the conf and canonical worker/cwd directories only.
|
|
10
|
+
# Marked reset/clean rules and an exact DROP DATABASE launch snapshot may exempt a dispatch worker;
|
|
11
|
+
# every failed scope/command check retains the ordinary pattern verdict.
|
|
8
12
|
# Must complete in <50ms.
|
|
9
13
|
#
|
|
10
14
|
# Canonical Policy Script Contract (design.md §4):
|
|
11
15
|
# env DOFLOW_PROJECT_DIR, DOFLOW_AGENT (both optional; not required to
|
|
12
16
|
# evaluate this policy)
|
|
13
|
-
# stdin a
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# run_shell_command — Gemini; run_command — the generic name
|
|
17
|
-
# stream-hook-runner.js's own COMMAND_TOOL_PATTERN already
|
|
18
|
-
# recognized), since a native front door (Claude/Codex/Kiro) execs
|
|
19
|
-
# this script directly with no payload translation of its own.
|
|
20
|
-
# exit 0 = allow, non-zero = deny with the reason on stderr.
|
|
17
|
+
# stdin a native payload with envelope v1 under doflow_event; only the
|
|
18
|
+
# envelope's operation, tool and command and native root cwd are used.
|
|
19
|
+
# exit exit 2 + doflow_decide deny = deny; other faults per IC-011.
|
|
21
20
|
#
|
|
22
21
|
# Reconciliation note (022-normalize-hooks, Phase A / D1): this also absorbs
|
|
23
22
|
# stream-hook-runner.js's inline DESTRUCTIVE_COMMAND_PATTERN
|
|
24
23
|
# (`\brm\s+-rf\s+[/~]`, since narrowed to the recursive-rm-of-catastrophic-target
|
|
25
|
-
# rule below), which was the only pre-bash-guard protection
|
|
26
|
-
#
|
|
24
|
+
# rule below), which was the only pre-bash-guard protection
|
|
25
|
+
# Antigravity sessions routed through that runner actually had — it
|
|
27
26
|
# duplicated, rather than delegated to, this policy's fuller
|
|
28
27
|
# blocked-patterns.conf coverage (git force-push, git reset --hard, git clean
|
|
29
28
|
# -fd, SQL DROP/DELETE/TRUNCATE, curl|wget-pipe-to-shell, chmod -R 777, dd
|
|
@@ -32,40 +31,171 @@
|
|
|
32
31
|
# only the hardcoded regex before this change does not lose even that
|
|
33
32
|
# minimum floor of protection; once blocked-patterns.conf is present (the
|
|
34
33
|
# normal case), the full config-driven pattern list applies as it already
|
|
35
|
-
# does for claude/
|
|
36
|
-
# coverage for
|
|
34
|
+
# does for claude/codex today, which is a real, intended widening of
|
|
35
|
+
# coverage for Antigravity once B.5 wires this policy for them (see
|
|
37
36
|
# design.md R2/R3), not a silent side effect.
|
|
38
37
|
|
|
39
38
|
set -uo pipefail
|
|
40
39
|
|
|
41
|
-
command -v jq >/dev/null 2>&1 || exit 0 # no jq -> cannot evaluate -> allow
|
|
42
|
-
|
|
43
40
|
INPUT=$(cat)
|
|
41
|
+
if [ -f "$_DOFLOW_POLDIR/contract.sh" ]; then
|
|
42
|
+
. "$_DOFLOW_POLDIR/contract.sh"
|
|
43
|
+
else
|
|
44
|
+
doflow_decision_init() { :; }
|
|
45
|
+
doflow_decide() { :; }
|
|
46
|
+
doflow_read_envelope() { DF_ENV_CLASS=missing; DF_ENV_CODE=contract-missing; }
|
|
47
|
+
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard contract-missing ) >/dev/null 2>&1 || true
|
|
48
|
+
if [[ "${DOFLOW_AGENT:-}" =~ ^[a-z]+$ ]]; then
|
|
49
|
+
printf '[pre-bash-guard] DoFlow hooks out of step; run: doflow update -t %s\n' "$DOFLOW_AGENT" >&2
|
|
50
|
+
else
|
|
51
|
+
printf '[pre-bash-guard] DoFlow hooks out of step; run: doflow update\n' >&2
|
|
52
|
+
fi
|
|
53
|
+
doflow_decide deny contract-missing
|
|
54
|
+
exit 2
|
|
55
|
+
fi
|
|
56
|
+
doflow_decision_init pre-bash-guard 1
|
|
57
|
+
command -v jq >/dev/null 2>&1 || {
|
|
58
|
+
doflow_decide error dependency-missing:jq
|
|
59
|
+
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard dependency-missing:jq ) >/dev/null 2>&1 || true
|
|
60
|
+
exit 0
|
|
61
|
+
}
|
|
62
|
+
DF_ENV_CLASS=missing DF_ENV_CODE=envelope-missing
|
|
63
|
+
doflow_read_envelope || true
|
|
44
64
|
|
|
45
65
|
TOOL_NAME=""
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
[
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
COMMAND=""
|
|
67
|
+
if [ "$DF_ENV_CLASS" = v1 ]; then
|
|
68
|
+
[ "$DF_ENV_OP" = command ] || exit 0
|
|
69
|
+
TOOL_NAME=$DF_ENV_TOOL
|
|
70
|
+
COMMAND=$DF_ENV_COMMAND
|
|
71
|
+
elif [ "$DF_ENV_CLASS" = unsupported ]; then
|
|
72
|
+
doflow_decide unsupported envelope-version
|
|
73
|
+
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard unsupported:envelope-version ) >/dev/null 2>&1 || true
|
|
74
|
+
exit 0
|
|
75
|
+
else
|
|
76
|
+
if [ "${DF_ENV_CODE:-envelope-missing}" != contract-missing ]; then
|
|
77
|
+
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard envelope-missing ) >/dev/null 2>&1 || true
|
|
78
|
+
fi
|
|
79
|
+
if [[ "${DOFLOW_AGENT:-}" =~ ^[a-z]+$ ]]; then printf '[pre-bash-guard] DoFlow hooks out of step; run: doflow update -t %s\n' "$DOFLOW_AGENT" >&2; else printf '[pre-bash-guard] DoFlow hooks out of step; run: doflow update\n' >&2; fi
|
|
80
|
+
doflow_decide deny "${DF_ENV_CODE:-envelope-missing}"
|
|
81
|
+
exit 2
|
|
82
|
+
fi
|
|
59
83
|
|
|
60
84
|
# Nothing to check if command is empty
|
|
61
85
|
[ -z "$COMMAND" ] && exit 0
|
|
62
86
|
|
|
63
|
-
PATTERNS_FILE="$
|
|
87
|
+
PATTERNS_FILE="$_DOFLOW_POLDIR/blocked-patterns.conf"
|
|
64
88
|
|
|
65
89
|
# ASCII-only patterns: the C locale keeps bash's substring/pattern operations
|
|
66
90
|
# byte-wise (much faster than multibyte-aware in a UTF-8 locale).
|
|
67
91
|
export LC_ALL=C
|
|
68
92
|
|
|
93
|
+
# Shape checks accept one terminal line ending, never an additional command.
|
|
94
|
+
# Keep COMMAND raw for all ordinary pattern verdicts.
|
|
95
|
+
SHAPE_COMMAND=$COMMAND
|
|
96
|
+
case $SHAPE_COMMAND in
|
|
97
|
+
*$'\r\n') SHAPE_COMMAND=${SHAPE_COMMAND%$'\r\n'} ;;
|
|
98
|
+
*$'\n') SHAPE_COMMAND=${SHAPE_COMMAND%$'\n'} ;;
|
|
99
|
+
esac
|
|
100
|
+
|
|
101
|
+
# Lazy and cached: shape checks precede the shared scope's only two subshells
|
|
102
|
+
# (cd/pwd builtins), then one git probe for reset/clean only.
|
|
103
|
+
# Never infer worker identity from command text.
|
|
104
|
+
_WORKER_EXEMPT=
|
|
105
|
+
_worker_exempt() {
|
|
106
|
+
case $_WORKER_EXEMPT in allow) return 0 ;; deny) return 1 ;; esac
|
|
107
|
+
_WORKER_EXEMPT=deny
|
|
108
|
+
local reset_re='^[[:blank:]]*git[[:blank:]]+reset([[:blank:]]+(--hard|-q|--quiet))+([[:blank:]]+[A-Za-z0-9_@][A-Za-z0-9_./^~@{}-]*)?[[:blank:]]*$'
|
|
109
|
+
local clean_re='^[[:blank:]]*git[[:blank:]]+clean([[:blank:]]+(-[dfqxX]+|--force|--quiet))+[[:blank:]]*$'
|
|
110
|
+
local forces command=$SHAPE_COMMAND
|
|
111
|
+
if [[ $command =~ $reset_re ]]; then
|
|
112
|
+
case " $command " in *[[:blank:]]--hard[[:blank:]]*) ;; *) return 1 ;; esac
|
|
113
|
+
elif [[ $command =~ $clean_re ]]; then
|
|
114
|
+
forces=${command//[!f]/}
|
|
115
|
+
[ "${#forces}" -eq 1 ] || return 1
|
|
116
|
+
else
|
|
117
|
+
return 1
|
|
118
|
+
fi
|
|
119
|
+
_worker_scope || return 1
|
|
120
|
+
local project=${_WORKER_DIR%/.doflow/state/dispatch-worktrees/*}
|
|
121
|
+
local name=${_WORKER_DIR##*/} info git_dir top suffix
|
|
122
|
+
[ -d "$project/.git" ] || return 1
|
|
123
|
+
# No inherited GIT_* / config environment can redirect this read-only probe.
|
|
124
|
+
info=$(env -i PATH="$PATH" HOME="${HOME:-}" git -C "$_WORKER_CWD" rev-parse --path-format=absolute --git-dir --show-toplevel 2>/dev/null) || return 1
|
|
125
|
+
git_dir=${info%%$'\n'*}; top=${info#*$'\n'}
|
|
126
|
+
[ "$top" = "$_WORKER_DIR" ] || return 1
|
|
127
|
+
case $git_dir in "$project/.git/worktrees/$name"*) ;; *) return 1 ;; esac
|
|
128
|
+
suffix=${git_dir#"$project/.git/worktrees/$name"}
|
|
129
|
+
case $suffix in *[!0-9]*) return 1 ;; esac
|
|
130
|
+
_WORKER_EXEMPT=allow
|
|
131
|
+
return 0
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Both exemptions use exactly the same worker, dispatch-path, cwd and GIT_* checks.
|
|
135
|
+
_WORKER_SCOPE=
|
|
136
|
+
_worker_scope() {
|
|
137
|
+
case $_WORKER_SCOPE in allow) return 0 ;; deny) return 1 ;; esac
|
|
138
|
+
_WORKER_SCOPE=deny
|
|
139
|
+
local worktree cwd config_key
|
|
140
|
+
[ "${DOFLOW_SESSION_ROLE:-}" = worker ] || return 1
|
|
141
|
+
[ -z "${GIT_DIR+x}${GIT_WORK_TREE+x}${GIT_INDEX_FILE+x}${GIT_COMMON_DIR+x}${GIT_CONFIG_PARAMETERS+x}${GIT_CONFIG_COUNT+x}" ] || return 1
|
|
142
|
+
for config_key in ${!GIT_CONFIG_KEY_@}; do return 1; done
|
|
143
|
+
case ${DOFLOW_WORKTREE:-} in /*) ;; *) return 1 ;; esac
|
|
144
|
+
[ -d "$DOFLOW_WORKTREE" ] || return 1
|
|
145
|
+
# A sentinel preserves path-ending newlines across command substitution.
|
|
146
|
+
worktree=$(CDPATH= cd -P -- "$DOFLOW_WORKTREE" 2>/dev/null && pwd -P && printf '.') || return 1
|
|
147
|
+
worktree=${worktree%.}; worktree=${worktree%$'\n'}
|
|
148
|
+
local dispatch_re='/\.doflow/state/dispatch-worktrees/d-[0-9a-f]{12}$'
|
|
149
|
+
[[ $worktree =~ $dispatch_re ]] || return 1
|
|
150
|
+
[ -n "${DF_ENV_CWD:-}" ] || return 1
|
|
151
|
+
cwd=$(CDPATH= cd -P -- "$DF_ENV_CWD" 2>/dev/null && pwd -P && printf '.') || return 1
|
|
152
|
+
cwd=${cwd%.}; cwd=${cwd%$'\n'}
|
|
153
|
+
case $cwd in "$worktree"|"$worktree"/*) ;; *) return 1 ;; esac
|
|
154
|
+
_WORKER_DIR=$worktree _WORKER_CWD=$cwd
|
|
155
|
+
_WORKER_SCOPE=allow
|
|
156
|
+
return 0
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# 112: no settings reads here. Re-validate only the launcher's snapshot, then
|
|
160
|
+
# recognise one full bare client invocation and one statement. No shell eval,
|
|
161
|
+
# substitutions, variables, wrappers, redirects, additional args or statements.
|
|
162
|
+
_worker_dropdb_exempt() {
|
|
163
|
+
local list=${DOFLOW_GUARD_DROP_DATABASES:-} list_re='^[a-z][a-z0-9_]{0,62}( [a-z][a-z0-9_]{0,62})*$'
|
|
164
|
+
[ "${#list}" -le 1024 ] && [[ $list =~ $list_re ]] || return 1
|
|
165
|
+
local names=() name rest client quote statement id_re sql_re command=$SHAPE_COMMAND
|
|
166
|
+
IFS=' ' read -r -a names <<< "$list"
|
|
167
|
+
[ "${#names[@]}" -le 32 ] || return 1
|
|
168
|
+
local psql_re='^[[:blank:]]*psql([[:blank:]]+(-[hpUd][[:blank:]]+[A-Za-z0-9_.:-]+|--(host|port|username|dbname)=[A-Za-z0-9_.:-]+|-w))*[[:blank:]]+-c[[:blank:]]+'
|
|
169
|
+
local mysql_re='^[[:blank:]]*mysql([[:blank:]]+(-[hPu][[:blank:]]+[A-Za-z0-9_.:-]+|--(host|port|user)=[A-Za-z0-9_.:-]+))*[[:blank:]]+-e[[:blank:]]+'
|
|
170
|
+
if [[ $command =~ $psql_re ]]; then client=psql
|
|
171
|
+
elif [[ $command =~ $mysql_re ]]; then client=mysql
|
|
172
|
+
else return 1
|
|
173
|
+
fi
|
|
174
|
+
rest=${command:${#BASH_REMATCH[0]}}
|
|
175
|
+
local single_re="^'([^']*)'[[:blank:]]*$" double_re='^"([^"]*)"[[:blank:]]*$'
|
|
176
|
+
if [[ $rest =~ $single_re ]]; then quote=single
|
|
177
|
+
elif [[ $rest =~ $double_re ]]; then quote=double
|
|
178
|
+
else return 1
|
|
179
|
+
fi
|
|
180
|
+
statement=${BASH_REMATCH[1]}
|
|
181
|
+
id_re='[a-z][a-z0-9_]*'
|
|
182
|
+
if [ "$quote" = single ]; then
|
|
183
|
+
if [ "$client" = psql ]; then id_re='([a-z][a-z0-9_]*|"[a-z][a-z0-9_]*")'
|
|
184
|
+
else id_re='([a-z][a-z0-9_]*|`[a-z][a-z0-9_]*`)'
|
|
185
|
+
fi
|
|
186
|
+
fi
|
|
187
|
+
sql_re="^[[:blank:]]*[Dd][Rr][Oo][Pp][[:blank:]]+[Dd][Aa][Tt][Aa][Bb][Aa][Ss][Ee][[:blank:]]+([Ii][Ff][[:blank:]]+[Ee][Xx][Ii][Ss][Tt][Ss][[:blank:]]+)?($id_re)[[:blank:]]*;?[[:blank:]]*$"
|
|
188
|
+
[[ $statement =~ $sql_re ]] || return 1
|
|
189
|
+
name=${BASH_REMATCH[2]}
|
|
190
|
+
case $name in \"*\"|\`*\`) name=${name#?}; name=${name%?} ;; esac
|
|
191
|
+
local listed found=false
|
|
192
|
+
for listed in "${names[@]}"; do
|
|
193
|
+
if [ "$name" = "$listed" ]; then found=true; break; fi
|
|
194
|
+
done
|
|
195
|
+
[ "$found" = true ] || return 1
|
|
196
|
+
_worker_scope
|
|
197
|
+
}
|
|
198
|
+
|
|
69
199
|
# ── Quoted text, comments and heredoc bodies are not commands ────────────────
|
|
70
200
|
# scrub_quotes <text> -> sets SCRUBBED. Anchored shell-command patterns must
|
|
71
201
|
# not fire on text that is merely data (a commit message, an echo, a comment,
|
|
@@ -143,7 +273,7 @@ scrub_quotes() {
|
|
|
143
273
|
*) SCRUBBED=$text; return ;;
|
|
144
274
|
esac
|
|
145
275
|
case $text in
|
|
146
|
-
*rm[[:space:]]*|*git[[:space:]]*|*curl[[:space:]]*|*wget[[:space:]]*|*chmod[[:space:]]*|*dd[[:space:]]*|*find[[:space:]]*|*eval*|*sh[[:space:]]*) ;;
|
|
276
|
+
*rm[[:space:]]*|*git[[:space:]]*|*curl[[:space:]]*|*wget[[:space:]]*|*chmod[[:space:]]*|*dd[[:space:]]*|*find[[:space:]]*|*eval*|*sh[[:space:]]*|*echo[[:space:]]*|*printf[[:space:]]*|*cat[[:space:]]*|*tee[[:space:]]*|*mkdir[[:space:]]*|*cd[[:space:]]*|*true[[:space:]]*|*:[[:space:]]*|*gh[[:space:]]*) ;;
|
|
147
277
|
*) SCRUBBED=$text; return ;;
|
|
148
278
|
esac
|
|
149
279
|
if [ "$SCRUB_DEPTH" -ge 8 ]; then SCRUBBED=$text; return; fi
|
|
@@ -248,12 +378,77 @@ scrub_quotes() {
|
|
|
248
378
|
scrub_quotes "$COMMAND"
|
|
249
379
|
SHELL_TEXT=$SCRUBBED
|
|
250
380
|
|
|
381
|
+
# Positive SQL text-only allow-list, ALWAYS on raw COMMAND, never SHELL_TEXT.
|
|
382
|
+
# Whole-command matches permit only commit messages, echo/printf literals,
|
|
383
|
+
# cat with a single-quoted heredoc, and gh pr/issue create/comment/edit bodies.
|
|
384
|
+
# Double quotes forbid $, backticks and backslashes; file paths have no dot-led
|
|
385
|
+
# segment. Heredoc delimiters are single-quoted identifiers, close exactly once
|
|
386
|
+
# on the final line, and allow one trailing newline. The sole substitution is
|
|
387
|
+
# the exact Claude commit $(cat <<'WORD' ... WORD) idiom. No eval or shell parser:
|
|
388
|
+
# every non-match keeps the original raw SQL verdict, including malformed input.
|
|
389
|
+
_text_only_command() {
|
|
390
|
+
local text=${COMMAND%$'\n'} b='[[:blank:]]' single="'[^']*'" literal path git gh args re header body word line closed=false
|
|
391
|
+
literal="($single|\"[^\"\$\`\\\\]*\")"
|
|
392
|
+
path='/?[A-Za-z0-9_-][A-Za-z0-9_.-]*(/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*'
|
|
393
|
+
git="git${b}+commit(${b}+(-a|-q|--no-verify))*"
|
|
394
|
+
args="(${b}+([A-Za-z0-9_./:=,@%+-]+|$literal))*"
|
|
395
|
+
gh="gh${b}+(pr|issue)${b}+(create|comment|edit)$args"
|
|
396
|
+
re="^${b}*$git(${b}+-m${b}+$literal(${b}+(-a|-q|--no-verify))*)+${b}*$"
|
|
397
|
+
[[ $text =~ $re ]] && return 0
|
|
398
|
+
re="^${b}*(echo|printf)${b}+$literal(${b}*>>?${b}*$path)?${b}*$"
|
|
399
|
+
[[ $text =~ $re ]] && return 0
|
|
400
|
+
re="^${b}*$gh${b}+--body${b}+$single$args${b}*$"
|
|
401
|
+
[[ $text =~ $re ]] && return 0
|
|
402
|
+
|
|
403
|
+
# Split only the first line. The body is inert only if its first delimiter
|
|
404
|
+
# occurrence is also its last line; otherwise a hidden second command runs.
|
|
405
|
+
case $text in *$'\n'*) ;; *) return 1 ;; esac
|
|
406
|
+
header=${text%%$'\n'*}; body=${text#*$'\n'}
|
|
407
|
+
local hd="<<'([A-Za-z_][A-Za-z0-9_]*)'" cat_start='"\$\(cat' cat_end=$'\n)"'
|
|
408
|
+
local redir=">>?${b}*$path" tee_flag="(-a|--append)"
|
|
409
|
+
local re_git="^${b}*($git${b}+-F${b}+-${b}+|$gh${b}+--body-file${b}+-${b}+)${hd}${b}*$"
|
|
410
|
+
local re_cat_before="^${b}*cat(${b}+${redir})?${b}+${hd}${b}*$"
|
|
411
|
+
local re_cat_after="^${b}*cat${b}+${hd}(${b}*${redir})?${b}*$"
|
|
412
|
+
local re_tee_before="^${b}*tee(${b}+${tee_flag})?${b}+${path}${b}+${hd}${b}*$"
|
|
413
|
+
local re_tee_after="^${b}*tee(${b}+${tee_flag})?${b}+${hd}${b}+(${tee_flag}${b}+)?${path}${b}*$"
|
|
414
|
+
if [[ $header =~ $re_git ]] || [[ $header =~ $re_cat_before ]] || [[ $header =~ $re_cat_after ]] || [[ $header =~ $re_tee_before ]] || [[ $header =~ $re_tee_after ]]; then
|
|
415
|
+
# Match the delimiter separately so prefix capture groups cannot change its index.
|
|
416
|
+
[[ $header =~ $hd ]] || return 1
|
|
417
|
+
word=${BASH_REMATCH[1]}
|
|
418
|
+
else
|
|
419
|
+
re="^${b}*$git${b}+-m${b}+$cat_start${b}+${hd}${b}*$"
|
|
420
|
+
[[ $header =~ $re ]] || return 1
|
|
421
|
+
[[ $header =~ $hd ]] || return 1
|
|
422
|
+
word=${BASH_REMATCH[1]}
|
|
423
|
+
[[ $body == *"$cat_end" ]] || return 1
|
|
424
|
+
body=${body%"$cat_end"}
|
|
425
|
+
fi
|
|
426
|
+
while IFS= read -r line; do
|
|
427
|
+
[ "$closed" = false ] || return 1
|
|
428
|
+
[ "$line" != "$word" ] || closed=true
|
|
429
|
+
done <<< "$body"
|
|
430
|
+
[ "$closed" = true ]
|
|
431
|
+
}
|
|
432
|
+
DATA_ONLY=false
|
|
433
|
+
_text_only_command && DATA_ONLY=true
|
|
434
|
+
|
|
435
|
+
# Project-specific unanchored patterns keep their verdicts too: only these
|
|
436
|
+
# three shipped SQL families participate in the text-only exception.
|
|
437
|
+
_sql_pattern() {
|
|
438
|
+
case $1 in
|
|
439
|
+
'DROP[[:space:]]+(TABLE|DATABASE|SCHEMA)[[:space:]]'|\
|
|
440
|
+
'DELETE[[:space:]]+FROM[[:space:]]+[[:alnum:]_]+[[:space:]]*;'|\
|
|
441
|
+
'TRUNCATE[[:space:]]+TABLE') return 0 ;;
|
|
442
|
+
esac
|
|
443
|
+
return 1
|
|
444
|
+
}
|
|
445
|
+
|
|
251
446
|
# Hardcoded floor, used only when blocked-patterns.conf is missing: recursive
|
|
252
447
|
# rm (any flag spelling, flag before or after the target) of a catastrophic
|
|
253
448
|
# target — the same rule as the rm lines in blocked-patterns.conf. Subpaths
|
|
254
449
|
# such as /tmp/x are not blocked.
|
|
255
450
|
_CMDPOS='(^|[;&|(`])[[:space:]]*'
|
|
256
|
-
_WRAP='((sudo([[:space:]]+(-[ugChprtUDR][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|--(user|group|host|prompt|role|type|chdir)[[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|xargs([[:space:]]+(-[nILPsdEa][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|env([[:space:]]+(-[uCS][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|(command|time|nohup|exec|eval|then|do|else)([[:space:]]+(-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*)[[:space:]]+)*'
|
|
451
|
+
_WRAP='((sudo([[:space:]]+(-[ugChprtUDR][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|--(user|group|host|prompt|role|type|chdir)[[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|xargs([[:space:]]+(-[nILPsdEa][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|env([[:space:]]+(-[uCS][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*|(command|time|nohup|exec|eval|then|do|else)([[:space:]]+(-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*)[[:space:]]+)*'
|
|
257
452
|
_PATHRM='(\\|/(usr/)?bin/)?rm'
|
|
258
453
|
_RM_FLAG='(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)'
|
|
259
454
|
_RM_ARGS='([[:space:]]+[^[:space:];&|]+)*'
|
|
@@ -268,17 +463,21 @@ if [ ! -f "$PATTERNS_FILE" ]; then
|
|
|
268
463
|
# The pattern file ships with DoFlow, so a missing one means a broken install: record it on this
|
|
269
464
|
# machine (feature 046, IC-018) and go on exactly as before. Subshell, output discarded: nothing
|
|
270
465
|
# the helper does can reach this policy's options, variables, output or exit status.
|
|
271
|
-
( . "$
|
|
466
|
+
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard patterns-missing ) >/dev/null 2>&1 || true
|
|
467
|
+
doflow_decide error patterns-missing
|
|
272
468
|
if _floor_rm_hits '/+\*{0,2}'; then
|
|
273
469
|
echo "[pre-bash-guard] Catastrophic delete blocked — recursive rm of the root directory (/)" >&2
|
|
470
|
+
doflow_decide deny catastrophic-rm-root
|
|
274
471
|
exit 2
|
|
275
472
|
fi
|
|
276
473
|
if _floor_rm_hits '(~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?'; then
|
|
277
474
|
echo "[pre-bash-guard] Catastrophic delete blocked — recursive rm of the home directory" >&2
|
|
475
|
+
doflow_decide deny catastrophic-rm-home
|
|
278
476
|
exit 2
|
|
279
477
|
fi
|
|
280
478
|
if _floor_rm_hits '/(Users|home|etc|usr|bin|sbin|var|opt|System|Library|Applications|Volumes|private|root|boot|lib|dev|proc)(/\*{0,2})?'; then
|
|
281
479
|
echo "[pre-bash-guard] Catastrophic delete blocked — recursive rm of a system directory" >&2
|
|
480
|
+
doflow_decide deny catastrophic-rm-system
|
|
282
481
|
exit 2
|
|
283
482
|
fi
|
|
284
483
|
# No patterns file beyond the hardcoded floor — allow everything else
|
|
@@ -286,12 +485,54 @@ if [ ! -f "$PATTERNS_FILE" ]; then
|
|
|
286
485
|
exit 0
|
|
287
486
|
fi
|
|
288
487
|
|
|
488
|
+
# One combined ERE cheaply rules out commands that match no live pattern. A
|
|
489
|
+
# grep match or regex error falls through to the original per-line loop, which
|
|
490
|
+
# still owns the reason and optional exclude semantics.
|
|
491
|
+
_anchored_patterns="" _full_patterns="" _has_backreference=false
|
|
492
|
+
_has_worker_marker=false
|
|
493
|
+
while IFS=$'\t' read -r pattern _reason _exclude || [ -n "$pattern" ]; do
|
|
494
|
+
[ -z "$pattern" ] && continue
|
|
495
|
+
case "$pattern" in
|
|
496
|
+
'#@exempt-next worker-worktree') _has_worker_marker=true; continue ;;
|
|
497
|
+
\#*) continue ;;
|
|
498
|
+
esac
|
|
499
|
+
if [ "$DATA_ONLY" = true ] && _sql_pattern "$pattern"; then continue; fi
|
|
500
|
+
if [[ "$pattern" =~ \\[1-9] ]]; then _has_backreference=true; fi
|
|
501
|
+
case "$pattern" in
|
|
502
|
+
'(^|'*) _anchored_patterns="${_anchored_patterns:+$_anchored_patterns|}($pattern)" ;;
|
|
503
|
+
*) _full_patterns="${_full_patterns:+$_full_patterns|}($pattern)" ;;
|
|
504
|
+
esac
|
|
505
|
+
done < "$PATTERNS_FILE"
|
|
506
|
+
_anchored_status=1 _full_status=1
|
|
507
|
+
if [ -n "$_anchored_patterns" ]; then
|
|
508
|
+
grep -qiE -- "$_anchored_patterns" <<<"$SHELL_TEXT" 2>/dev/null
|
|
509
|
+
_anchored_status=$?
|
|
510
|
+
fi
|
|
511
|
+
if [ -n "$_full_patterns" ]; then
|
|
512
|
+
grep -qiE -- "$_full_patterns" <<<"$COMMAND" 2>/dev/null
|
|
513
|
+
_full_status=$?
|
|
514
|
+
fi
|
|
515
|
+
if [ "$_anchored_status" -eq 1 ] && [ "$_full_status" -eq 1 ] && [ "$_has_backreference" != true ]; then
|
|
516
|
+
# Some accepted worker shapes (reset -q --hard, clean -f) already match no
|
|
517
|
+
# deny rule. Give those allows the same scope code without widening a rule.
|
|
518
|
+
if [ "$_has_worker_marker" = true ] && _worker_exempt; then doflow_decide allow worker-worktree; fi
|
|
519
|
+
exit 0
|
|
520
|
+
fi
|
|
521
|
+
|
|
289
522
|
# ── Pattern matching ──────────────────────────────────────────────────────────
|
|
290
523
|
|
|
524
|
+
_exempt_next= _worker_skipped=false
|
|
291
525
|
while IFS=$'\t' read -r pattern reason exclude || [ -n "$pattern" ]; do
|
|
292
526
|
# Skip comments and empty lines
|
|
293
527
|
[ -z "$pattern" ] && continue
|
|
294
|
-
case "$pattern" in
|
|
528
|
+
case "$pattern" in
|
|
529
|
+
'#@exempt-next worker-worktree') _exempt_next=worker-worktree; continue ;;
|
|
530
|
+
'#@exempt-next worker-dropdb') _exempt_next=worker-dropdb; continue ;;
|
|
531
|
+
\#*) continue ;;
|
|
532
|
+
esac
|
|
533
|
+
exemption=$_exempt_next
|
|
534
|
+
_exempt_next=
|
|
535
|
+
if [ "$DATA_ONLY" = true ] && _sql_pattern "$pattern"; then continue; fi
|
|
295
536
|
|
|
296
537
|
# Match pattern against command (case-insensitive, POSIX extended regex: the default macOS
|
|
297
538
|
# filesystem is case-insensitive, so RM and GIT run there).
|
|
@@ -319,10 +560,20 @@ while IFS=$'\t' read -r pattern reason exclude || [ -n "$pattern" ]; do
|
|
|
319
560
|
fi
|
|
320
561
|
|
|
321
562
|
if [ "$matched" = "true" ]; then
|
|
563
|
+
if [ "$exemption" = worker-worktree ] && _worker_exempt; then
|
|
564
|
+
_worker_skipped=worker-worktree
|
|
565
|
+
continue
|
|
566
|
+
fi
|
|
567
|
+
if [ "$exemption" = worker-dropdb ] && _worker_dropdb_exempt; then
|
|
568
|
+
_worker_skipped=worker-dropdb
|
|
569
|
+
continue
|
|
570
|
+
fi
|
|
322
571
|
echo "[pre-bash-guard] ${reason:-Command blocked by pre-bash-guard}" >&2
|
|
572
|
+
doflow_decide deny blocked-pattern
|
|
323
573
|
exit 2
|
|
324
574
|
fi
|
|
325
575
|
done < "$PATTERNS_FILE"
|
|
326
576
|
|
|
327
577
|
# No match — allow
|
|
578
|
+
[ "$_worker_skipped" != false ] && doflow_decide allow "$_worker_skipped"
|
|
328
579
|
exit 0
|