@khoavu882/doflow 2.0.0-beta.5 → 2.0.1
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 +16 -16
- package/bin/doflow.js +22 -12
- package/core/.antigravity-plugin/plugin.json +1 -2
- 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 +4 -1
- 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-compact.sh +23 -27
- package/core/harnesses/claude/hooks/pre-implement-gate.sh +4 -1
- package/core/harnesses/claude/hooks/session-end.sh +23 -10
- package/core/harnesses/claude/hooks/skill-config-audit.sh +3 -0
- package/core/harnesses/claude/settings/settings.json +26 -9
- 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/hooks.json +0 -10
- package/core/harnesses/codex/hooks/lib.sh +44 -25
- package/core/harnesses/codex/hooks/mcp-tool-guard.sh +4 -1
- package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +3 -1
- package/core/harnesses/codex/hooks/pre-compact.impl.sh +29 -26
- package/core/harnesses/codex/hooks/pre-implement-gate.sh +4 -1
- package/core/harnesses/codex/hooks/session-end.impl.sh +23 -10
- package/core/harnesses/codex/hooks/subagent-audit.sh +1 -0
- package/core/harnesses/copilot/hooks/doflow-lib.sh +94 -0
- package/core/harnesses/copilot/hooks/doflow-mcp-tool-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 +51 -0
- package/core/harnesses/kiro/agents/doflow.json +1 -11
- package/core/harnesses/kiro/hooks/doflow.json +0 -10
- package/core/harnesses/kiro/hooks/lib.sh +26 -6
- package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +8 -3
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +8 -3
- package/core/harnesses/kiro/hooks/session-start.sh +1 -0
- package/core/harnesses/kiro/hooks/stop-check.sh +1 -0
- package/core/harnesses/pi/extensions/doflow-guard.js +11 -2
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +1 -2
- package/core/harnesses/shared/hooks/adapters/antigravity.js +1 -1
- package/core/harnesses/shared/hooks/bridge/bridge.sh +126 -23
- package/core/harnesses/shared/hooks/bridge/envelope.jq +87 -18
- package/core/harnesses/shared/hooks/bridge/observe-model.sh +75 -0
- package/core/harnesses/shared/hooks/bridge/respond.sh +16 -2
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +49 -16
- package/core/harnesses/shared/hooks/policies/compact-text.sh +46 -0
- package/core/harnesses/shared/hooks/policies/contract.sh +3 -0
- package/core/harnesses/shared/hooks/policies/deny-json.sh +20 -7
- 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 +63 -40
- package/core/harnesses/shared/hooks/policies/mcp-policy.conf +1 -1
- package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +7 -8
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +132 -57
- package/core/harnesses/shared/hooks/policies/session-context.sh +30 -1
- package/core/harnesses/shared/hooks/policies/stop-check.sh +27 -15
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +6 -3
- package/core/harnesses/shared/hooks/policies/summary-store.sh +347 -0
- package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +60 -155
- package/core/harnesses/shared/hooks/stream-hook-runner.js +58 -20
- package/core/harnesses/shared/locator/doflow-run +2 -3
- package/core/registry/advice.json +3 -3
- package/core/registry/assets.json +55 -82
- package/core/registry/capabilities.json +12 -0
- package/core/registry/contracts.json +58 -31
- package/core/registry/contribution-points.json +35 -0
- package/core/registry/gates.json +32 -0
- package/core/registry/guidance-caps.json +40 -0
- package/core/registry/harnesses.json +1445 -366
- package/core/registry/intake.json +53 -0
- package/core/registry/lifecycle.json +599 -996
- 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/intake-category/files/category.json +8 -0
- package/core/registry/package-templates/intake-category/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 +272 -0
- package/core/registry/storage.json +687 -31
- package/core/registry/telemetry.json +236 -0
- package/core/registry/transcripts.json +142 -0
- package/core/registry/verification.json +76 -6
- 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 +3 -2
- package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +19 -1
- 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 +49 -5
- package/core/shared/scripts/doflow/bin/doflow-run +152 -34
- package/core/shared/skills/do/SKILL.md +14 -12
- 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 +45 -97
- package/core/shared/skills/do-brainstorm/references/handoff_branches.md +36 -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 +48 -148
- 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 +23 -20
- package/core/shared/skills/do-diagnose/SKILL.md +18 -6
- package/core/shared/skills/do-document/SKILL.md +12 -1
- package/core/shared/skills/do-document/references/deep_research.md +1 -2
- package/core/shared/skills/do-document/references/embedded-research.md +19 -7
- package/core/shared/skills/do-document/references/implementation-flow.md +5 -6
- package/core/shared/skills/do-execute-plan/SKILL.md +19 -60
- 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 +26 -1
- package/core/shared/skills/do-execute-plan/references/run_position.md +16 -2
- 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 +10 -11
- package/core/shared/skills/do-flow/references/task_classes.md +5 -5
- package/core/shared/skills/do-git/SKILL.md +4 -0
- package/core/shared/skills/do-implement/SKILL.md +13 -14
- package/core/shared/skills/do-plan/SKILL.md +34 -20
- 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/shared/workflows/do-flow-chain.md +2 -0
- 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 +143 -66
- package/src/adapters/claude/index.js +46 -5
- package/src/adapters/codex/agents.js +25 -15
- package/src/adapters/codex/hooks.js +39 -3
- package/src/adapters/codex/index.js +61 -13
- package/src/adapters/codex/native-projection.js +6 -2
- package/src/adapters/copilot/index.js +58 -23
- package/src/adapters/copy-tree.js +291 -46
- 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 +23 -12
- package/src/adapters/opencode/index.js +8 -8
- package/src/adapters/pi/hooks.js +2 -1
- package/src/adapters/pi/index.js +14 -7
- package/src/adapters/resolve-source.js +26 -2
- package/src/cli/commands/install.js +2 -1
- 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 +22 -3
- package/src/cli/commands/ui.js +99 -0
- package/src/cli/commands/update.js +2 -1
- package/src/cli/index.js +337 -32
- package/src/cli/runtime-commands.js +220 -60
- 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 +4 -16
- package/src/lifecycle/hook-tier.js +160 -0
- package/src/lifecycle/index.js +412 -78
- package/src/lifecycle/retired-harnesses.js +318 -0
- package/src/lifecycle/view.js +35 -15
- package/src/registry/index.js +551 -26
- package/src/registry/worker-ids.js +45 -0
- package/src/release/build-package.js +0 -3
- package/src/release/docs-blocks.js +472 -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 +20 -11
- 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 +13 -7
- package/src/runtime/cli.js +196 -19
- package/src/runtime/config-home.js +42 -0
- package/src/runtime/context/arbitrate.js +767 -0
- package/src/runtime/context/delivery-store.js +4 -6
- package/src/runtime/context/emission-rules.js +118 -0
- package/src/runtime/context/identity.js +227 -0
- package/src/runtime/context/pointer.js +67 -12
- 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 +158 -79
- 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-ledger.js +52 -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 +33 -3
- package/src/runtime/git-memo.js +46 -0
- package/src/runtime/guidance/ablation.js +427 -0
- package/src/runtime/health.js +624 -18
- package/src/runtime/history-compactor.js +13 -3
- package/src/runtime/implementation-gate.js +281 -26
- package/src/runtime/intake/engine.js +677 -0
- package/src/runtime/intake/index.js +136 -0
- package/src/runtime/intake/manifest.js +140 -0
- package/src/runtime/intake/taxonomy.js +206 -0
- 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 +88 -10
- package/src/runtime/lifecycle/event-store.js +8 -6
- package/src/runtime/lifecycle/followup.js +38 -7
- package/src/runtime/lifecycle/overview.js +26 -2
- 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 +2 -2
- 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 +487 -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 +46 -5
- package/src/runtime/research-request.js +50 -25
- package/src/runtime/retrieval-plan.js +10 -30
- package/src/runtime/retrieval-record.js +75 -5
- 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/attendance.js +137 -0
- package/src/runtime/roadmap/facts.js +479 -0
- package/src/runtime/roadmap/gates.js +273 -0
- package/src/runtime/roadmap/loop.js +1719 -0
- package/src/runtime/roadmap/merge.js +390 -0
- package/src/runtime/roadmap/rows.js +1122 -0
- package/src/runtime/roadmap/seed.js +1063 -0
- package/src/runtime/roadmap/worktree-cleanup.js +147 -0
- package/src/runtime/rules-report.js +336 -0
- package/src/runtime/scaffold/artifacts.js +60 -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 +1 -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 +85 -14
- package/src/runtime/task-graph.js +373 -0
- package/src/runtime/task-run.js +778 -0
- package/src/runtime/task-scope.js +176 -55
- package/src/runtime/task-sources.js +147 -0
- package/src/runtime/task-state.js +373 -64
- 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/verb-view.js +267 -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 -54
- 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 +256 -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 +610 -67
- 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/harnesses/claude/hooks/pre-bash-guard.sh +0 -10
- package/core/harnesses/codex/hooks/pre-bash-guard.sh +0 -10
- 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 -10
- package/core/harnesses/gemini/hooks/post-edit-lint.sh +0 -39
- package/core/harnesses/gemini/hooks/pre-bash-guard.sh +0 -10
- package/core/harnesses/gemini/hooks/pre-compact.sh +0 -38
- package/core/harnesses/gemini/hooks/pre-implement-gate.sh +0 -10
- 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 -7
- package/core/harnesses/gemini/settings/adapter-defaults.json +0 -4
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +0 -24
- package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +0 -91
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +0 -378
- 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 -251
- package/src/adapters/gemini/index.js +0 -429
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# blocked-patterns.conf — Dangerous command patterns for pre-bash-guard.sh
|
|
2
|
-
#
|
|
3
|
-
# Format (TAB-separated):
|
|
4
|
-
# regex<TAB>reason shown to the harness<TAB>exclude_regex (optional)
|
|
5
|
-
#
|
|
6
|
-
# Rules:
|
|
7
|
-
# - Lines beginning with # are comments (skipped)
|
|
8
|
-
# - Empty lines are skipped
|
|
9
|
-
# - Regex is POSIX Extended Regular Expression (ERE, as used by `grep -E`),
|
|
10
|
-
# matched case-insensitively against the full command string (RM and GIT run
|
|
11
|
-
# on a case-insensitive filesystem such as the macOS default), which
|
|
12
|
-
# includes any expanded heredocs or -m "..." arguments. Git and rm
|
|
13
|
-
# patterns use a command-context anchor:
|
|
14
|
-
# (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)
|
|
15
|
-
# so they only fire when the dangerous text is an actual invocation,
|
|
16
|
-
# not when it appears as text inside a commit message or other argument.
|
|
17
|
-
# - Anchored patterns (those beginning with "(^|") are matched against the
|
|
18
|
-
# command with quoted text blanked out (pre-bash-guard.sh scrub_quotes),
|
|
19
|
-
# so echo "x && rm -rf /" or git commit -m "git reset --hard" is not a
|
|
20
|
-
# command. The argument of sh -c, bash -c, zsh -c and eval is NOT blanked
|
|
21
|
-
# (it executes). Every other pattern is matched against the full text.
|
|
22
|
-
# - The rm lines use a wider command position than the others: start of a
|
|
23
|
-
# line or after ; & | ( or a backtick, then optional sudo/command/time/
|
|
24
|
-
# nohup/exec/env (with options, VAR=x and, per wrapper, the options that take
|
|
25
|
-
# a separate argument: sudo -u/-g/-C/-h/-p/-r/-t/-U/-D/-R and --user/--group
|
|
26
|
-
# root, xargs -n/-I/-L/-P/-s/-d/-E/-a, env -u/-C/-S)/xargs/eval/then/do/else, then rm,
|
|
27
|
-
# \rm, /bin/rm or /usr/bin/rm. "git rm" and "echo rm -rf /" are therefore
|
|
28
|
-
# not matched. pre-bash-guard.sh's hardcoded floor uses the same rule.
|
|
29
|
-
# Matching is case-insensitive, so an uppercase flag-only option that shares a
|
|
30
|
-
# letter with a value-taking one (sudo -H beside -h, xargs -p beside -P) is
|
|
31
|
-
# treated as value-taking: a false deny, the fail-safe direction.
|
|
32
|
-
# - The git patterns accept git's global options before the subcommand
|
|
33
|
-
# (git -C dir push, git -c k=v push). The force-push rules block -f (also
|
|
34
|
-
# inside a flag cluster such as -uf), --force and a +refspec; the
|
|
35
|
-
# --force-with-lease form stays allowed, as the reason text advises, but a
|
|
36
|
-
# +refspec still blocks next to a lease (git push --force-with-lease origin +main).
|
|
37
|
-
# - The find rule blocks -delete, and -exec rm, off the root, a home directory
|
|
38
|
-
# or a system directory (among other start paths, find or \find or
|
|
39
|
-
# /usr/bin/find) when only -type, -maxdepth/-mindepth N, -mount, -xdev,
|
|
40
|
-
# -depth, -noleaf, -follow or -ignore_readdir_race follow the path: none of
|
|
41
|
-
# those narrows what is deleted. Any other predicate (-name, -path, -newer,
|
|
42
|
-
# -mtime, -size, -user, -empty ...) counts as scoping, so
|
|
43
|
-
# find ~ -name '*.pyc' -delete is allowed.
|
|
44
|
-
# - SQL patterns are intentionally NOT anchored — DROP/DELETE/TRUNCATE
|
|
45
|
-
# inside heredoc-to-psql pipelines are real execution and must be caught.
|
|
46
|
-
# - The optional third column is an exclude_regex: when present and the
|
|
47
|
-
# command ALSO matches it, the pattern line is skipped (not blocked).
|
|
48
|
-
# This is how negative-lookahead behavior (unsupported in POSIX ERE) is
|
|
49
|
-
# approximated — e.g. "git push --force" blocks force pushes, but the
|
|
50
|
-
# exclude_regex "--force-with-lease" lets that safer variant through.
|
|
51
|
-
# - First matching pattern wins — order matters
|
|
52
|
-
# - A malformed regex on any line is skipped (guard continues safely)
|
|
53
|
-
#
|
|
54
|
-
# Add project-specific patterns at the bottom of this file.
|
|
55
|
-
|
|
56
|
-
# ── Dangerous git operations ──────────────────────────────────────────────────
|
|
57
|
-
(^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+push([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(--force|-[a-zA-Z]*f[a-zA-Z]*)([^-[:alnum:]]|$) Force push blocked — use --force-with-lease or confirm with user first
|
|
58
|
-
(^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+push([[:space:]]+[^[:space:];&|]+)*[[:space:]]+\+[^[:space:];&|]+ Force push blocked — use --force-with-lease or confirm with user first
|
|
59
|
-
(^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+reset --hard Destructive reset blocked — commit or stash changes before resetting
|
|
60
|
-
(^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+clean -fd Irreversible clean blocked — use --dry-run to preview what would be deleted
|
|
61
|
-
|
|
62
|
-
# ── Filesystem catastrophes ───────────────────────────────────────────────────
|
|
63
|
-
(^|[;&|(`])[[:space:]]*((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:]]+)*(\\|/(usr/)?bin/)?rm([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(/+\*{0,2})([[:space:];&|)`]|$)|(/+\*{0,2})([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:];&|)`]|$)) Catastrophic delete blocked — recursive rm of the root directory (/)
|
|
64
|
-
(^|[;&|(`])[[:space:]]*((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:]]+)*(\\|/(usr/)?bin/)?rm([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?)([[:space:];&|)`]|$)|((~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:];&|)`]|$)) Catastrophic delete blocked — recursive rm of the home directory
|
|
65
|
-
(^|[;&|(`])[[:space:]]*((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:]]+)*(\\|/(usr/)?bin/)?rm([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(/(Users|home|etc|usr|bin|sbin|var|opt|System|Library|Applications|Volumes|private|root|boot|lib|dev|proc)(/\*{0,2})?)([[:space:];&|)`]|$)|(/(Users|home|etc|usr|bin|sbin|var|opt|System|Library|Applications|Volumes|private|root|boot|lib|dev|proc)(/\*{0,2})?)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:];&|)`]|$)) Catastrophic delete blocked — recursive rm of a system directory
|
|
66
|
-
(^|[;&|(`])[[:space:]]*((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:]]+)*(\\|/(usr/)?bin/)?find([[:space:]]+-[HLP])*([[:space:]]+[^-[:space:];&|][^[:space:];&|]*)*[[:space:]]+(/+\*{0,2}|(~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?|/(Users|home|etc|usr|bin|sbin|var|opt|System|Library|Applications|Volumes|private|root|boot|lib|dev|proc)(/\*{0,2})?)([[:space:]]+([^-[:space:];&|][^[:space:];&|]*|-(mount|xdev|depth|noleaf|follow|ignore_readdir_race)|-(type|maxdepth|mindepth)[[:space:]]+[^[:space:];&|]+))*[[:space:]]+(-delete([[:space:];&|)`]|$)|-exec(dir)?[[:space:]]+(\\|/(usr/)?bin/)?rm([[:space:];&|)`]|$)) Catastrophic delete blocked — find -delete or -exec rm from the root, home or a system directory with no name, path or time predicate to scope it
|
|
67
|
-
|
|
68
|
-
# ── SQL destructive statements (no anchor — must catch inside psql heredocs) ──
|
|
69
|
-
DROP[[:space:]]+(TABLE|DATABASE|SCHEMA)[[:space:]] Destructive DDL blocked — confirm with user before dropping
|
|
70
|
-
DELETE[[:space:]]+FROM[[:space:]]+[[:alnum:]_]+[[:space:]]*; Unscoped DELETE blocked — this would affect all rows, add a WHERE clause
|
|
71
|
-
TRUNCATE[[:space:]]+TABLE Irreversible truncate blocked — confirm with user before truncating
|
|
72
|
-
|
|
73
|
-
# ── Code execution from untrusted network sources ─────────────────────────────
|
|
74
|
-
(^|[[:space:]]*(&&|\|\||;)[[:space:]]*)(curl|wget)[[:space:]]+[^[:space:]]+.*\|[[:space:]]*(ba)?sh Pipe-to-shell blocked — download and review the script before executing
|
|
75
|
-
|
|
76
|
-
# ── Broad permission grants ───────────────────────────────────────────────────
|
|
77
|
-
(^|[[:space:]]*(&&|\|\||;)[[:space:]]*)chmod[[:space:]]+-R[[:space:]]+777 chmod -R 777 blocked — grants world-write access recursively; use targeted permissions (e.g. chmod 755) instead
|
|
78
|
-
|
|
79
|
-
# ── Disk device operations ────────────────────────────────────────────────────
|
|
80
|
-
(^|[[:space:]]*(&&|\|\||;)[[:space:]]*)dd[[:space:]]+if=/dev/ dd from block device blocked — can wipe or clone disks; confirm with user before any raw device operation
|
|
81
|
-
|
|
82
|
-
# ── Known limitation (not a pattern — comment only) ──────────────────────────
|
|
83
|
-
# eval-based indirection (e.g. CMD="git push --force"; eval "$CMD") bypasses all
|
|
84
|
-
# static pattern matching above. This is an inherent limitation of text-based
|
|
85
|
-
# guards. For high-security environments, supplement with branch protection
|
|
86
|
-
# rules and code review rather than relying solely on this guard.
|
|
87
|
-
#
|
|
88
|
-
# Variables other than HOME ($B, "$DIR") are not blocked: an empty or unset
|
|
89
|
-
# variable cannot be known statically, so rm -rf "$B"/ is allowed. Only the
|
|
90
|
-
# literal targets in the rm rule above are judged (root, home, and the system
|
|
91
|
-
# directories listed; subpaths such as /tmp/x or /Users/kai/x are allowed).
|
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
case $0 in */*) _DOFLOW_POLDIR=${0%/*} ;; *) _DOFLOW_POLDIR=. ;; esac
|
|
3
|
-
# pre-bash-guard.sh — Canonical Policy Library: PreToolUse(shell-command) hook
|
|
4
|
-
#
|
|
5
|
-
# Intercepts every shell-command tool call and blocks dangerous commands by
|
|
6
|
-
# matching against POSIX ERE patterns in blocked-patterns.conf (grep -E).
|
|
7
|
-
#
|
|
8
|
-
# Multi-session safe: stateless — reads only the conf file, no shared state.
|
|
9
|
-
# Must complete in <50ms.
|
|
10
|
-
#
|
|
11
|
-
# Canonical Policy Script Contract (design.md §4):
|
|
12
|
-
# env DOFLOW_PROJECT_DIR, DOFLOW_AGENT (both optional; not required to
|
|
13
|
-
# evaluate this policy)
|
|
14
|
-
# stdin a native payload with envelope v1 under doflow_event; only the
|
|
15
|
-
# envelope's operation, tool and command fields are used.
|
|
16
|
-
# exit exit 2 + doflow_decide deny = deny; other faults per IC-011.
|
|
17
|
-
#
|
|
18
|
-
# Reconciliation note (022-normalize-hooks, Phase A / D1): this also absorbs
|
|
19
|
-
# stream-hook-runner.js's inline DESTRUCTIVE_COMMAND_PATTERN
|
|
20
|
-
# (`\brm\s+-rf\s+[/~]`, since narrowed to the recursive-rm-of-catastrophic-target
|
|
21
|
-
# rule below), which was the only pre-bash-guard protection Gemini
|
|
22
|
-
# and Antigravity sessions routed through that runner actually had — it
|
|
23
|
-
# duplicated, rather than delegated to, this policy's fuller
|
|
24
|
-
# blocked-patterns.conf coverage (git force-push, git reset --hard, git clean
|
|
25
|
-
# -fd, SQL DROP/DELETE/TRUNCATE, curl|wget-pipe-to-shell, chmod -R 777, dd
|
|
26
|
-
# from a block device). That pattern is kept here as a hardcoded floor for
|
|
27
|
-
# the case blocked-patterns.conf itself is missing, so a harness that had
|
|
28
|
-
# only the hardcoded regex before this change does not lose even that
|
|
29
|
-
# minimum floor of protection; once blocked-patterns.conf is present (the
|
|
30
|
-
# normal case), the full config-driven pattern list applies as it already
|
|
31
|
-
# does for claude/gemini/codex today, which is a real, intended widening of
|
|
32
|
-
# coverage for Gemini/Antigravity once B.5 wires this policy for them (see
|
|
33
|
-
# design.md R2/R3), not a silent side effect.
|
|
34
|
-
|
|
35
|
-
set -uo pipefail
|
|
36
|
-
|
|
37
|
-
INPUT=$(cat)
|
|
38
|
-
if [ -f "$_DOFLOW_POLDIR/contract.sh" ]; then
|
|
39
|
-
. "$_DOFLOW_POLDIR/contract.sh"
|
|
40
|
-
else
|
|
41
|
-
doflow_decision_init() { :; }
|
|
42
|
-
doflow_decide() { :; }
|
|
43
|
-
doflow_read_envelope() { DF_ENV_CLASS=missing; DF_ENV_CODE=contract-missing; }
|
|
44
|
-
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard contract-missing ) >/dev/null 2>&1 || true
|
|
45
|
-
if [[ "${DOFLOW_AGENT:-}" =~ ^[a-z]+$ ]]; then
|
|
46
|
-
printf '[pre-bash-guard] DoFlow hooks out of step; run: doflow update -t %s\n' "$DOFLOW_AGENT" >&2
|
|
47
|
-
else
|
|
48
|
-
printf '[pre-bash-guard] DoFlow hooks out of step; run: doflow update\n' >&2
|
|
49
|
-
fi
|
|
50
|
-
doflow_decide deny contract-missing
|
|
51
|
-
exit 2
|
|
52
|
-
fi
|
|
53
|
-
doflow_decision_init pre-bash-guard 1
|
|
54
|
-
command -v jq >/dev/null 2>&1 || {
|
|
55
|
-
doflow_decide error dependency-missing:jq
|
|
56
|
-
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard dependency-missing:jq ) >/dev/null 2>&1 || true
|
|
57
|
-
exit 0
|
|
58
|
-
}
|
|
59
|
-
DF_ENV_CLASS=missing DF_ENV_CODE=envelope-missing
|
|
60
|
-
doflow_read_envelope || true
|
|
61
|
-
|
|
62
|
-
TOOL_NAME=""
|
|
63
|
-
COMMAND=""
|
|
64
|
-
if [ "$DF_ENV_CLASS" = v1 ]; then
|
|
65
|
-
[ "$DF_ENV_OP" = command ] || exit 0
|
|
66
|
-
TOOL_NAME=$DF_ENV_TOOL
|
|
67
|
-
COMMAND=$DF_ENV_COMMAND
|
|
68
|
-
elif [ "$DF_ENV_CLASS" = unsupported ]; then
|
|
69
|
-
doflow_decide unsupported envelope-version
|
|
70
|
-
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard unsupported:envelope-version ) >/dev/null 2>&1 || true
|
|
71
|
-
exit 0
|
|
72
|
-
else
|
|
73
|
-
if [ "${DF_ENV_CODE:-envelope-missing}" != contract-missing ]; then
|
|
74
|
-
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard envelope-missing ) >/dev/null 2>&1 || true
|
|
75
|
-
fi
|
|
76
|
-
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
|
|
77
|
-
doflow_decide deny "${DF_ENV_CODE:-envelope-missing}"
|
|
78
|
-
exit 2
|
|
79
|
-
fi
|
|
80
|
-
|
|
81
|
-
# Nothing to check if command is empty
|
|
82
|
-
[ -z "$COMMAND" ] && exit 0
|
|
83
|
-
|
|
84
|
-
PATTERNS_FILE="$_DOFLOW_POLDIR/blocked-patterns.conf"
|
|
85
|
-
|
|
86
|
-
# ASCII-only patterns: the C locale keeps bash's substring/pattern operations
|
|
87
|
-
# byte-wise (much faster than multibyte-aware in a UTF-8 locale).
|
|
88
|
-
export LC_ALL=C
|
|
89
|
-
|
|
90
|
-
# ── Quoted text, comments and heredoc bodies are not commands ────────────────
|
|
91
|
-
# scrub_quotes <text> -> sets SCRUBBED. Anchored shell-command patterns must
|
|
92
|
-
# not fire on text that is merely data (a commit message, an echo, a comment,
|
|
93
|
-
# a heredoc body). One linear pass, line by line, pure bash, no forks:
|
|
94
|
-
# - quoted text containing whitespace or ; & | is blanked to "" (it could
|
|
95
|
-
# otherwise fake a command position, e.g. echo "done && rm -rf /x");
|
|
96
|
-
# a quoted word with none of those ("/", "$HOME", $'/') is kept, unquoted,
|
|
97
|
-
# so rm -rf "/" is still seen as a target
|
|
98
|
-
# - the argument of sh|bash|zsh -c, eval and a here-string fed to a shell IS executed: it is kept and put
|
|
99
|
-
# in command position (wrapped in ";"), scrubbed again inside
|
|
100
|
-
# - inside double quotes, $( ... ) and `...` bodies also run: kept the same way
|
|
101
|
-
# - a # that starts a word comments out the rest of the line
|
|
102
|
-
# - a heredoc body (<<WORD, <<-WORD, quoted or not) is data and is dropped,
|
|
103
|
-
# except when the heredoc feeds a shell (bash <<EOF), whose body runs
|
|
104
|
-
# - a backslash-newline joins the two lines (outside a heredoc body)
|
|
105
|
-
# - a backslash-escaped character is literal; an unterminated quote keeps the
|
|
106
|
-
# rest of the text as is (errs toward blocking)
|
|
107
|
-
# Nesting depth is capped; beyond the cap the raw text is used (errs toward
|
|
108
|
-
# blocking). Text with no quote, # or << (or no command word at all) is
|
|
109
|
-
# returned unchanged without scanning.
|
|
110
|
-
_EXEC_CTX='(^|[[:space:];&|(])((([^[:space:]]*/)?(ba|z|da|k)?sh[[:space:]]+(-[[:alnum:]]+[[:space:]]+)*-[[:alnum:]]*c|eval)[[:space:]]+|([^[:space:]]*/)?(ba|z|da|k)?sh([[:space:]]+-[-[:alnum:]]*)*[[:space:]]*[0-9]*<<<[[:space:]]*)$'
|
|
111
|
-
_SH_HERE='(^|[[:space:];&|(])([^[:space:]]*/)?(ba|z|da|k)?sh([[:space:]]+-[[:alnum:]]+)*[[:space:]]*$'
|
|
112
|
-
_HD_WORD="^(-?)[[:space:]]*[\"']?\\\\?([A-Za-z_][A-Za-z0-9_.-]*)"
|
|
113
|
-
SCRUB_DEPTH=0
|
|
114
|
-
|
|
115
|
-
# Closes the quote scrub_quotes just read (uses its locals: out qc qin qexec).
|
|
116
|
-
_scrub_close_quote() {
|
|
117
|
-
local rest pre body acc depth ch
|
|
118
|
-
if [ "$qexec" = 1 ]; then
|
|
119
|
-
[ "$qc" = '"' ] && qin=${qin//\\\"/\"} # \" inside "..." is a quote of the inner command
|
|
120
|
-
scrub_quotes "$qin"; cur+="; $SCRUBBED ; "
|
|
121
|
-
return
|
|
122
|
-
fi
|
|
123
|
-
case $qin in
|
|
124
|
-
*[[:space:]\;\&\|]*) ;;
|
|
125
|
-
*) cur+=$qin; return ;;
|
|
126
|
-
esac
|
|
127
|
-
cur+=$qc$qc
|
|
128
|
-
[ "$qc" = '"' ] || return
|
|
129
|
-
case $qin in *'$('*|*\`*) ;; *) return ;; esac
|
|
130
|
-
rest=$qin
|
|
131
|
-
while :; do
|
|
132
|
-
pre=${rest%%[\`\$\\]*}
|
|
133
|
-
[ "$pre" = "$rest" ] && break
|
|
134
|
-
rest=${rest#"$pre"}
|
|
135
|
-
case ${rest:0:1} in
|
|
136
|
-
'\') rest=${rest:2} ;;
|
|
137
|
-
'`')
|
|
138
|
-
body=${rest:1}
|
|
139
|
-
case $body in *\`*) acc=${body%%\`*}; rest=${body#*\`} ;; *) acc=$body; rest="" ;; esac
|
|
140
|
-
scrub_quotes "$acc"; cur+="; $SCRUBBED ; " ;;
|
|
141
|
-
*)
|
|
142
|
-
if [ "${rest:1:1}" = "(" ]; then
|
|
143
|
-
body=${rest:2}; acc=""; depth=1
|
|
144
|
-
while [ -n "$body" ]; do
|
|
145
|
-
pre=${body%%[()]*}
|
|
146
|
-
if [ "$pre" = "$body" ]; then acc+=$body; body=""; break; fi
|
|
147
|
-
acc+=$pre; ch=${body:${#pre}:1}; body=${body:$((${#pre} + 1))}
|
|
148
|
-
if [ "$ch" = "(" ]; then depth=$((depth + 1)); acc+=$ch
|
|
149
|
-
else depth=$((depth - 1)); [ "$depth" -eq 0 ] && break; acc+=$ch; fi
|
|
150
|
-
done
|
|
151
|
-
rest=$body
|
|
152
|
-
scrub_quotes "$acc"; cur+="; $SCRUBBED ; "
|
|
153
|
-
else
|
|
154
|
-
rest=${rest:1}
|
|
155
|
-
fi ;;
|
|
156
|
-
esac
|
|
157
|
-
done
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
scrub_quotes() {
|
|
161
|
-
local text=$1
|
|
162
|
-
case $text in
|
|
163
|
-
*[\'\"#]*|*'<<'*|*'\'$'\n'*) ;;
|
|
164
|
-
*) SCRUBBED=$text; return ;;
|
|
165
|
-
esac
|
|
166
|
-
case $text in
|
|
167
|
-
*rm[[:space:]]*|*git[[:space:]]*|*curl[[:space:]]*|*wget[[:space:]]*|*chmod[[:space:]]*|*dd[[:space:]]*|*find[[:space:]]*|*eval*|*sh[[:space:]]*) ;;
|
|
168
|
-
*) SCRUBBED=$text; return ;;
|
|
169
|
-
esac
|
|
170
|
-
if [ "$SCRUB_DEPTH" -ge 8 ]; then SCRUBBED=$text; return; fi
|
|
171
|
-
SCRUB_DEPTH=$((SCRUB_DEPTH + 1))
|
|
172
|
-
|
|
173
|
-
local out="" cur="" line L first=1 qc="" qin="" qexec=0 qansi=0 hd_word="" hd_dash=0
|
|
174
|
-
local pre c tail w d
|
|
175
|
-
while IFS= read -r line; do
|
|
176
|
-
if [ -z "$hd_word" ]; then # backslash-newline joins lines
|
|
177
|
-
while [[ $line == *[!\\]'\' || $line == '\' ]] && IFS= read -r w; do line="${line%?} $w"; done
|
|
178
|
-
fi
|
|
179
|
-
L=$line
|
|
180
|
-
if [ -n "$qc" ]; then
|
|
181
|
-
qin+=$'\n'
|
|
182
|
-
else
|
|
183
|
-
[ "$first" = 1 ] || cur+=$'\n'
|
|
184
|
-
if [ -n "$hd_word" ]; then # inside a heredoc body: skip the line
|
|
185
|
-
if [ "$hd_dash" = 1 ]; then while [ "${L:0:1}" = $'\t' ]; do L=${L:1}; done; fi
|
|
186
|
-
[ "$L" = "$hd_word" ] && hd_word=""
|
|
187
|
-
first=0; continue
|
|
188
|
-
fi
|
|
189
|
-
fi
|
|
190
|
-
first=0
|
|
191
|
-
# A very long line is scanned in ~1 KB segments (quote state carries over),
|
|
192
|
-
# so the per-token slicing below never copies a huge remainder: stays linear.
|
|
193
|
-
while [ -n "$line" ]; do
|
|
194
|
-
if [ ${#line} -gt 2048 ]; then
|
|
195
|
-
L=${line:0:1024}; line=${line:1024}
|
|
196
|
-
while [[ $L == *'\' || $L == *'<' ]] && [ -n "$line" ]; do L+=${line:0:1}; line=${line:1}; done
|
|
197
|
-
else
|
|
198
|
-
L=$line; line=""
|
|
199
|
-
fi
|
|
200
|
-
while [ -n "$L" ]; do
|
|
201
|
-
if [ ${#cur} -gt 512 ]; then # keep the tail buffer small
|
|
202
|
-
out+=${cur:0:$((${#cur} - 128))}; cur=${cur: -128}
|
|
203
|
-
fi
|
|
204
|
-
if [ -n "$qc" ]; then # inside a quote: look for the close
|
|
205
|
-
if [ "$qc" = "'" ] && [ "$qansi" = 0 ]; then
|
|
206
|
-
case $L in
|
|
207
|
-
*\'*) qin+=${L%%\'*}; L=${L#*\'}; _scrub_close_quote; qc="" ;;
|
|
208
|
-
*) qin+=$L; L="" ;;
|
|
209
|
-
esac
|
|
210
|
-
else
|
|
211
|
-
if [ "$qc" = '"' ]; then pre=${L%%[\"\\]*}; else pre=${L%%[\'\\]*}; fi
|
|
212
|
-
if [ "$pre" = "$L" ]; then
|
|
213
|
-
qin+=$L; L=""
|
|
214
|
-
else
|
|
215
|
-
qin+=$pre; L=${L#"$pre"}
|
|
216
|
-
if [ "${L:0:1}" = '\' ]; then
|
|
217
|
-
qin+=${L:0:2}; L=${L:2}
|
|
218
|
-
else
|
|
219
|
-
L=${L:1}; _scrub_close_quote; qc=""
|
|
220
|
-
fi
|
|
221
|
-
fi
|
|
222
|
-
fi
|
|
223
|
-
continue
|
|
224
|
-
fi
|
|
225
|
-
pre=${L%%[\'\"\\#<]*}
|
|
226
|
-
if [ "$pre" = "$L" ]; then cur+=$L; L=""; break; fi
|
|
227
|
-
cur+=$pre; L=${L#"$pre"}
|
|
228
|
-
c=${L:0:1}
|
|
229
|
-
case $c in
|
|
230
|
-
'\') cur+=${L:0:2}; L=${L:2} ;;
|
|
231
|
-
'#')
|
|
232
|
-
case ${cur: -1} in
|
|
233
|
-
""|[[:space:]\;\&\|\(]) L="" ;;
|
|
234
|
-
*) cur+=$c; L=${L:1} ;;
|
|
235
|
-
esac ;;
|
|
236
|
-
'<')
|
|
237
|
-
if [ "${L:0:3}" = '<<<' ]; then
|
|
238
|
-
cur+='<<<'; L=${L:3}
|
|
239
|
-
elif [ "${L:0:2}" = '<<' ]; then
|
|
240
|
-
cur+='<<'; L=${L:2}
|
|
241
|
-
case $out$cur in
|
|
242
|
-
*'(('*) ;;
|
|
243
|
-
*)
|
|
244
|
-
if [[ $L =~ $_HD_WORD ]]; then
|
|
245
|
-
d=${BASH_REMATCH[1]}; w=${BASH_REMATCH[2]}
|
|
246
|
-
if [ ${#cur} -gt 122 ]; then tail=${cur: -122}; else tail=$cur; fi
|
|
247
|
-
tail=${tail%??}
|
|
248
|
-
[[ $tail =~ $_SH_HERE ]] || { hd_word=$w; [ -n "$d" ] && hd_dash=1 || hd_dash=0; }
|
|
249
|
-
fi ;;
|
|
250
|
-
esac
|
|
251
|
-
else
|
|
252
|
-
cur+='<'; L=${L:1}
|
|
253
|
-
fi ;;
|
|
254
|
-
*) # opening quote
|
|
255
|
-
qc=$c; qin=""; qexec=0; qansi=0; L=${L:1}
|
|
256
|
-
if [ "$c" = "'" ] && [ "${cur: -1}" = '$' ]; then
|
|
257
|
-
cur=${cur%?}; qansi=1
|
|
258
|
-
fi
|
|
259
|
-
if [ ${#cur} -gt 100 ]; then tail=${cur: -100}; else tail=$cur; fi
|
|
260
|
-
[[ $tail =~ $_EXEC_CTX ]] && qexec=1 ;;
|
|
261
|
-
esac
|
|
262
|
-
done
|
|
263
|
-
done
|
|
264
|
-
done <<< "$text"
|
|
265
|
-
[ -n "$qc" ] && cur+=$qc$qin # unterminated quote: keep as is
|
|
266
|
-
SCRUB_DEPTH=$((SCRUB_DEPTH - 1))
|
|
267
|
-
SCRUBBED=$out$cur
|
|
268
|
-
}
|
|
269
|
-
scrub_quotes "$COMMAND"
|
|
270
|
-
SHELL_TEXT=$SCRUBBED
|
|
271
|
-
|
|
272
|
-
# Hardcoded floor, used only when blocked-patterns.conf is missing: recursive
|
|
273
|
-
# rm (any flag spelling, flag before or after the target) of a catastrophic
|
|
274
|
-
# target — the same rule as the rm lines in blocked-patterns.conf. Subpaths
|
|
275
|
-
# such as /tmp/x are not blocked.
|
|
276
|
-
_CMDPOS='(^|[;&|(`])[[:space:]]*'
|
|
277
|
-
_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:]]+)*'
|
|
278
|
-
_PATHRM='(\\|/(usr/)?bin/)?rm'
|
|
279
|
-
_RM_FLAG='(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)'
|
|
280
|
-
_RM_ARGS='([[:space:]]+[^[:space:];&|]+)*'
|
|
281
|
-
_END='([[:space:];&|)`]|$)'
|
|
282
|
-
_RM_PREFIX="${_CMDPOS}${_WRAP}${_PATHRM}${_RM_ARGS}[[:space:]]+"
|
|
283
|
-
# _floor_rm_hits <target-regex> : does the scrubbed command recursively rm it?
|
|
284
|
-
_floor_rm_hits() {
|
|
285
|
-
grep -qiE -- "${_RM_PREFIX}(${_RM_FLAG}${_RM_ARGS}[[:space:]]+($1)${_END}|($1)${_RM_ARGS}[[:space:]]+${_RM_FLAG}${_END})" <<<"$SHELL_TEXT" 2>/dev/null
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if [ ! -f "$PATTERNS_FILE" ]; then
|
|
289
|
-
# The pattern file ships with DoFlow, so a missing one means a broken install: record it on this
|
|
290
|
-
# machine (feature 046, IC-018) and go on exactly as before. Subshell, output discarded: nothing
|
|
291
|
-
# the helper does can reach this policy's options, variables, output or exit status.
|
|
292
|
-
( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-bash-guard patterns-missing ) >/dev/null 2>&1 || true
|
|
293
|
-
doflow_decide error patterns-missing
|
|
294
|
-
if _floor_rm_hits '/+\*{0,2}'; then
|
|
295
|
-
echo "[pre-bash-guard] Catastrophic delete blocked — recursive rm of the root directory (/)" >&2
|
|
296
|
-
doflow_decide deny catastrophic-rm-root
|
|
297
|
-
exit 2
|
|
298
|
-
fi
|
|
299
|
-
if _floor_rm_hits '(~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?'; then
|
|
300
|
-
echo "[pre-bash-guard] Catastrophic delete blocked — recursive rm of the home directory" >&2
|
|
301
|
-
doflow_decide deny catastrophic-rm-home
|
|
302
|
-
exit 2
|
|
303
|
-
fi
|
|
304
|
-
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
|
|
305
|
-
echo "[pre-bash-guard] Catastrophic delete blocked — recursive rm of a system directory" >&2
|
|
306
|
-
doflow_decide deny catastrophic-rm-system
|
|
307
|
-
exit 2
|
|
308
|
-
fi
|
|
309
|
-
# No patterns file beyond the hardcoded floor — allow everything else
|
|
310
|
-
# (fail open — don't block the agent).
|
|
311
|
-
exit 0
|
|
312
|
-
fi
|
|
313
|
-
|
|
314
|
-
# One combined ERE cheaply rules out commands that match no live pattern. A
|
|
315
|
-
# grep match or regex error falls through to the original per-line loop, which
|
|
316
|
-
# still owns the reason and optional exclude semantics.
|
|
317
|
-
_anchored_patterns="" _full_patterns="" _has_backreference=false
|
|
318
|
-
while IFS=$'\t' read -r pattern _reason _exclude || [ -n "$pattern" ]; do
|
|
319
|
-
[ -z "$pattern" ] && continue
|
|
320
|
-
case "$pattern" in \#*) continue ;; esac
|
|
321
|
-
if [[ "$pattern" =~ \\[1-9] ]]; then _has_backreference=true; fi
|
|
322
|
-
case "$pattern" in
|
|
323
|
-
'(^|'*) _anchored_patterns="${_anchored_patterns:+$_anchored_patterns|}($pattern)" ;;
|
|
324
|
-
*) _full_patterns="${_full_patterns:+$_full_patterns|}($pattern)" ;;
|
|
325
|
-
esac
|
|
326
|
-
done < "$PATTERNS_FILE"
|
|
327
|
-
_anchored_status=1 _full_status=1
|
|
328
|
-
if [ -n "$_anchored_patterns" ]; then
|
|
329
|
-
grep -qiE -- "$_anchored_patterns" <<<"$SHELL_TEXT" 2>/dev/null
|
|
330
|
-
_anchored_status=$?
|
|
331
|
-
fi
|
|
332
|
-
if [ -n "$_full_patterns" ]; then
|
|
333
|
-
grep -qiE -- "$_full_patterns" <<<"$COMMAND" 2>/dev/null
|
|
334
|
-
_full_status=$?
|
|
335
|
-
fi
|
|
336
|
-
if [ "$_anchored_status" -eq 1 ] && [ "$_full_status" -eq 1 ] && [ "$_has_backreference" != true ]; then exit 0; fi
|
|
337
|
-
|
|
338
|
-
# ── Pattern matching ──────────────────────────────────────────────────────────
|
|
339
|
-
|
|
340
|
-
while IFS=$'\t' read -r pattern reason exclude || [ -n "$pattern" ]; do
|
|
341
|
-
# Skip comments and empty lines
|
|
342
|
-
[ -z "$pattern" ] && continue
|
|
343
|
-
case "$pattern" in \#*) continue ;; esac
|
|
344
|
-
|
|
345
|
-
# Match pattern against command (case-insensitive, POSIX extended regex: the default macOS
|
|
346
|
-
# filesystem is case-insensitive, so RM and GIT run there).
|
|
347
|
-
# A bad regex makes grep exit 2, which "if" reads as no match (fail open).
|
|
348
|
-
# "--" stops grep from treating a pattern beginning with '-' (e.g. an
|
|
349
|
-
# exclude pattern like "--force-with-lease") as an option flag.
|
|
350
|
-
# Anchored shell-command patterns (they begin with the "(^|" command-position
|
|
351
|
-
# anchor) match the scrubbed text; every other pattern (the SQL ones)
|
|
352
|
-
# matches the full text, so statements inside quoted psql -c / heredocs are
|
|
353
|
-
# still caught.
|
|
354
|
-
case "$pattern" in '(^|'*) target=$SHELL_TEXT ;; *) target=$COMMAND ;; esac
|
|
355
|
-
matched=false
|
|
356
|
-
if grep -qiE -- "$pattern" <<<"$target" 2>/dev/null; then
|
|
357
|
-
matched=true
|
|
358
|
-
fi
|
|
359
|
-
|
|
360
|
-
# Optional third column: if the command also matches the exclude pattern,
|
|
361
|
-
# this pattern line is skipped entirely (approximates negative lookahead,
|
|
362
|
-
# which POSIX ERE cannot express — e.g. "--force-with-lease" excludes the
|
|
363
|
-
# "git push --force" block).
|
|
364
|
-
if [ "$matched" = "true" ] && [ -n "$exclude" ]; then
|
|
365
|
-
if grep -qiE -- "$exclude" <<<"$target" 2>/dev/null; then
|
|
366
|
-
matched=false
|
|
367
|
-
fi
|
|
368
|
-
fi
|
|
369
|
-
|
|
370
|
-
if [ "$matched" = "true" ]; then
|
|
371
|
-
echo "[pre-bash-guard] ${reason:-Command blocked by pre-bash-guard}" >&2
|
|
372
|
-
doflow_decide deny blocked-pattern
|
|
373
|
-
exit 2
|
|
374
|
-
fi
|
|
375
|
-
done < "$PATTERNS_FILE"
|
|
376
|
-
|
|
377
|
-
# No match — allow
|
|
378
|
-
exit 0
|
|
@@ -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>
|