@khoavu882/doflow 2.0.0-beta.5 → 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 -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/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/session-end.sh +23 -10
- package/core/harnesses/claude/hooks/skill-config-audit.sh +3 -0
- 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/post-edit-lint.impl.sh +3 -1
- package/core/harnesses/codex/hooks/pre-compact.impl.sh +29 -26
- 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 +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 +1 -0
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +1 -0
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +1 -0
- 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 +8 -0
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +0 -1
- package/core/harnesses/shared/hooks/bridge/bridge.sh +102 -9
- 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 +10 -2
- package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +28 -14
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +48 -15
- 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 +2 -11
- 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-tool-guard.sh +3 -2
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +213 -12
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +114 -38
- package/core/harnesses/shared/hooks/policies/session-context.sh +30 -1
- package/core/harnesses/shared/hooks/policies/stop-check.sh +20 -9
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +5 -2
- 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 +47 -8
- 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 +32 -0
- package/core/registry/gates.json +32 -0
- package/core/registry/guidance-caps.json +40 -0
- package/core/registry/harnesses.json +1442 -363
- package/core/registry/lifecycle.json +485 -304
- 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 +679 -31
- 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 +149 -34
- 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 +18 -17
- 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 +15 -58
- 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 +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 +4 -7
- package/core/shared/skills/do-plan/SKILL.md +26 -15
- 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 +143 -66
- package/src/adapters/claude/index.js +24 -4
- package/src/adapters/codex/agents.js +25 -15
- package/src/adapters/codex/index.js +48 -13
- package/src/adapters/codex/native-projection.js +6 -2
- package/src/adapters/copilot/index.js +58 -23
- package/src/adapters/copy-tree.js +290 -44
- 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 +21 -2
- package/src/cli/commands/ui.js +99 -0
- package/src/cli/commands/update.js +2 -1
- package/src/cli/index.js +322 -29
- package/src/cli/runtime-commands.js +209 -57
- 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 +20 -3
- 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 +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 +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/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 +154 -78
- 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 +34 -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 +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 +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 +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 +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/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 +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 +47 -11
- 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 +374 -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/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/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/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
|
@@ -0,0 +1,383 @@
|
|
|
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
|
+
# emission.sh — Canonical Policy Library: the hook emission adapter and the emission ledger
|
|
4
|
+
# (feature 078, IC-004, IC-015; DEC-015, DEC-016, DEC-017).
|
|
5
|
+
#
|
|
6
|
+
# The prompt path's emission, from the state bits to the response bytes. arbitrate() in
|
|
7
|
+
# src/runtime/context/arbitrate.js is the reference for the rules; this file reads the compiled
|
|
8
|
+
# table (emission-rules.sh), claims through summary-store.sh and renders with one jq process running
|
|
9
|
+
# emission.jq. It starts no Node or doflow-run process.
|
|
10
|
+
#
|
|
11
|
+
# Sourcing this file defines functions only: no option, no variable, no trap, no output. bash 3.2
|
|
12
|
+
# safe and safe under the caller's `set -euo pipefail`. The caller has sourced lib.sh (which sources
|
|
13
|
+
# identity.sh), summary-store.sh and emission-rules.sh; a missing one is a fault.
|
|
14
|
+
#
|
|
15
|
+
# Store, under SESSION_DIR (lib.sh; session-env/sessions; empty with no config home, which prints
|
|
16
|
+
# the silent response with reason silent:no-home):
|
|
17
|
+
# <unitId>/injected one-shot bootstrap slot, created exclusively (set -C) by the first caller
|
|
18
|
+
# <unitId>/emitted the IC-015 ledger: <ISO-8601 UTC>\t<kind>\t<key>\t<outcome>\t<caller>, one
|
|
19
|
+
# line per (kind, key, outcome), appended only when that triple is absent
|
|
20
|
+
#
|
|
21
|
+
# Faults: any claim or render failure prints the silent response ({} and a newline) and records
|
|
22
|
+
# `doflow_capture_failure user-prompt-submit emission-<point>`, point one of deps, unit, slot,
|
|
23
|
+
# summary, grant, warning, render; a failed ledger append records emission-ledger and keeps the
|
|
24
|
+
# rendered response. A fault after the slot claim releases the slot this call created, so the next
|
|
25
|
+
# prompt bootstraps again (DEC-038); a fault in a later claim renames the summary, grant and warning
|
|
26
|
+
# already claimed back into place (`mv -n`, never over a newer file). A claim that fails because its
|
|
27
|
+
# source vanished (another caller won it) is no fault: that segment counts as absent and the
|
|
28
|
+
# bootstrap continues. A claimed summary or grant whose render fails is not restored.
|
|
29
|
+
#
|
|
30
|
+
# Ledger outcomes besides refused:mandatory-over-budget: `optional-dropped <key> over-budget`, one
|
|
31
|
+
# per optional segment the budget dropped (key: the summary id for summary, else the segment name;
|
|
32
|
+
# DEC-041). A dropped nudge leaves the session unmarked, so a later prompt can nudge.
|
|
33
|
+
|
|
34
|
+
# _doflow_em_capture <point>: one failure-capture line, never on stdout or stderr.
|
|
35
|
+
_doflow_em_capture() {
|
|
36
|
+
local dir
|
|
37
|
+
_DOFLOW_SRC=${BASH_SOURCE[0]//\\//}; case $_DOFLOW_SRC in */*) dir=${_DOFLOW_SRC%/*} ;; *) dir=. ;; esac
|
|
38
|
+
if declare -F doflow_capture_failure >/dev/null 2>&1; then
|
|
39
|
+
( doflow_capture_failure user-prompt-submit "emission-$1" ) >/dev/null 2>&1 || true
|
|
40
|
+
else
|
|
41
|
+
( . "$dir/capture-failure.sh" && doflow_capture_failure user-prompt-submit "emission-$1" ) >/dev/null 2>&1 || true
|
|
42
|
+
fi
|
|
43
|
+
return 0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# _doflow_em_restore <claimed> <original>: rename a claimed file back unless a newer one took its
|
|
47
|
+
# place, in which case the claimed copy is the older and is removed.
|
|
48
|
+
_doflow_em_restore() {
|
|
49
|
+
[ -n "$1" ] && [ -e "$1" ] || return 0
|
|
50
|
+
mv -n "$1" "$2" 2>/dev/null || true
|
|
51
|
+
[ ! -e "$1" ] || rm -f "$1" 2>/dev/null || true
|
|
52
|
+
return 0
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# _doflow_em_release: undo this call's claims before a fault response, from the caller's locals
|
|
56
|
+
# (made, dir, sumfile, sumsrc, claimed_grant, grantsrc, warnclaimed, warnfile). The slot goes last.
|
|
57
|
+
_doflow_em_release() {
|
|
58
|
+
[ "$sumfile" = /dev/null ] || _doflow_em_restore "$sumfile" "$sumsrc"
|
|
59
|
+
[ -z "$claimed_grant" ] || _doflow_em_restore "$claimed_grant" "$grantsrc"
|
|
60
|
+
[ -z "$warnclaimed" ] || _doflow_em_restore "$warnclaimed" "$warnfile"
|
|
61
|
+
sumfile=/dev/null claimed_grant="" warnclaimed=""
|
|
62
|
+
if [ "$made" = 1 ]; then rm -f "$dir/injected" 2>/dev/null || true; made=0; fi
|
|
63
|
+
return 0
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# _doflow_em_measure <response> <digest>: for the response printed as `printf '%s\n'`, DF_EMIT_BYTES
|
|
67
|
+
# (its byte length under LC_ALL=C, newline included) and DF_EMIT_DIGEST (the renderer's digest
|
|
68
|
+
# header line when it is 8 lowercase hex, else empty). Rider R1 (091): metadata for the hook line
|
|
69
|
+
# only; builtins only, no response byte leaves this function, and nothing reaches stdout.
|
|
70
|
+
_doflow_em_measure() {
|
|
71
|
+
local LC_ALL=C
|
|
72
|
+
DF_EMIT_BYTES=$(( ${#1} + 1 ))
|
|
73
|
+
DF_EMIT_DIGEST=""
|
|
74
|
+
case "${2:-}" in
|
|
75
|
+
[0123456789abcdef][0123456789abcdef][0123456789abcdef][0123456789abcdef][0123456789abcdef][0123456789abcdef][0123456789abcdef][0123456789abcdef]) DF_EMIT_DIGEST=$2 ;;
|
|
76
|
+
esac
|
|
77
|
+
return 0
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# _doflow_em_silent <point>: the fault response.
|
|
81
|
+
_doflow_em_silent() {
|
|
82
|
+
_doflow_em_capture "$1"
|
|
83
|
+
DF_EMIT_REASON="fault:$1"
|
|
84
|
+
printf '{}\n'
|
|
85
|
+
return 0
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# _doflow_em_seen <ledger file> <kind> <key> <outcome>: 0 when the triple is already recorded.
|
|
89
|
+
_doflow_em_seen() {
|
|
90
|
+
local ts kind key outcome caller
|
|
91
|
+
[ -f "$1" ] || return 1
|
|
92
|
+
{
|
|
93
|
+
while IFS=$'\t' read -r ts kind key outcome caller || [ -n "$ts" ]; do
|
|
94
|
+
if [ "$kind" = "$2" ] && [ "$key" = "$3" ] && [ "$outcome" = "$4" ]; then return 0; fi
|
|
95
|
+
ts=""
|
|
96
|
+
done
|
|
97
|
+
} 2>/dev/null <"$1"
|
|
98
|
+
return 1
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# _doflow_em_ledger_add <unit dir> <kind> <key> <outcome> <caller>: append one IC-015 line unless
|
|
102
|
+
# (kind, key, outcome) is already recorded. Returns 1 when the line could not be written.
|
|
103
|
+
_doflow_em_ledger_add() {
|
|
104
|
+
local file="$1/emitted" ts
|
|
105
|
+
if _doflow_em_seen "$file" "$2" "$3" "$4"; then return 0; fi
|
|
106
|
+
mkdir -p "$1" 2>/dev/null || return 1
|
|
107
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null) || return 1
|
|
108
|
+
printf '%s\t%s\t%s\t%s\t%s\n' "$ts" "$2" "$3" "$4" "$5" >>"$file" 2>/dev/null || return 1
|
|
109
|
+
return 0
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# _doflow_em_rule <event.segment> <vector>: prints nothing; sets DF_ACTION (skip on any failure).
|
|
113
|
+
_doflow_em_rule() {
|
|
114
|
+
DF_ACTION=skip
|
|
115
|
+
doflow_emission_rule "$1" "$2" || DF_ACTION=skip
|
|
116
|
+
return 0
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# _doflow_em_actions: the prompt segments' actions from the caller's state locals (role, kind,
|
|
120
|
+
# bootstrapped, subagent, own, grant, refused, warning, nudge_state), vectors in IC-002 order.
|
|
121
|
+
_doflow_em_actions() {
|
|
122
|
+
_doflow_em_rule prompt.slot "$bootstrapped"; a_slot=$DF_ACTION
|
|
123
|
+
_doflow_em_rule prompt.git "$role:$bootstrapped"; a_git=$DF_ACTION
|
|
124
|
+
_doflow_em_rule prompt.summary "$role:$kind:$subagent:$bootstrapped:$own"; a_summary=$DF_ACTION
|
|
125
|
+
_doflow_em_rule prompt.warning "$role:$subagent:$bootstrapped:$warning"; a_warning=$DF_ACTION
|
|
126
|
+
_doflow_em_rule prompt.grant "$subagent:$grant:$refused"; a_grant=$DF_ACTION
|
|
127
|
+
_doflow_em_rule prompt.nudge "$role:$nudge_state"; a_nudge=$DF_ACTION
|
|
128
|
+
return 0
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# doflow_emit_prompt <session_id> <cwd> <payload_title> <subagent> <nudge_text>
|
|
132
|
+
# IC-004 steps 2 to 8 for one UserPromptSubmit event; prints the response on stdout and returns 0.
|
|
133
|
+
# session_id the payload session_id; empty prints nothing (the 0fcd973 early exit)
|
|
134
|
+
# cwd the payload cwd
|
|
135
|
+
# payload_title the payload session_title; non-empty suppresses sessionTitle
|
|
136
|
+
# subagent non-empty when the payload is a native subagent prompt (agent_id or agent_type)
|
|
137
|
+
# nudge_text the nudge message when the classifier earned it, else empty; the session is
|
|
138
|
+
# marked nudged here, only once the nudge rendered (DEC-041)
|
|
139
|
+
# Reads DOFLOW_AGENT (harness; sessionTitle on every harness but codex, DEC-030),
|
|
140
|
+
# DOFLOW_CONTEXT_MAX_BYTES (budget, default DF_RULES_MAX_BYTES_DEFAULT or 16384), SESSION_DIR and the
|
|
141
|
+
# launcher variables through doflow_identity. Sets DF_ID_* (doflow_identity), DF_EMIT_REASON (emit,
|
|
142
|
+
# refused:mandatory-over-budget, silent:already-bootstrapped, silent:unchanged, silent:no-home or
|
|
143
|
+
# fault:<point>), DF_EMIT_BYTES and DF_EMIT_DIGEST (_doflow_em_measure for emit and refused:*, else 0
|
|
144
|
+
# and empty) and DF_EMIT_NUDGE (rendered or empty); when the nudge was rendered it calls
|
|
145
|
+
# `nudge_mark <session> nudged` and, when contract.sh is loaded, `doflow_decide advisory prompt-nudge`.
|
|
146
|
+
doflow_emit_prompt() {
|
|
147
|
+
local session="${1:-}" cwd="${2:-}" payload_title="${3:-}" nudge="${5:-}"
|
|
148
|
+
local subagent=false nudge_state=none role kind bootstrapped=false own=none grant=none refused=false
|
|
149
|
+
local warning=false legacy=false a_slot a_git a_summary a_warning a_grant a_nudge
|
|
150
|
+
local sessions dir unit max harness here renderer project="" warnfile="" warntext="" had_c=0 made=0
|
|
151
|
+
local gitfile sumfile=/dev/null grantfile=/dev/null claimed_grant="" absent="" plan out
|
|
152
|
+
local refusal=refused:mandatory-over-budget title=false sumsrc="" sumid="" grantsrc="" warnclaimed=""
|
|
153
|
+
local dropped rest seg key digest=false
|
|
154
|
+
DF_EMIT_REASON=""
|
|
155
|
+
DF_EMIT_BYTES=0
|
|
156
|
+
DF_EMIT_DIGEST=""
|
|
157
|
+
DF_EMIT_NUDGE=""
|
|
158
|
+
[ -n "$session" ] || return 0
|
|
159
|
+
[ -z "${4:-}" ] || subagent=true
|
|
160
|
+
[ -z "$nudge" ] || nudge_state=nudge
|
|
161
|
+
if ! declare -F doflow_identity doflow_emission_rule doflow_summary_peek doflow_summary_claim \
|
|
162
|
+
doflow_grant_peek doflow_grant_claim doflow_summary_adopt_legacy doflow_summary_legacy_present ensure_project_dir >/dev/null 2>&1; then
|
|
163
|
+
_doflow_em_silent deps
|
|
164
|
+
return 0
|
|
165
|
+
fi
|
|
166
|
+
_DOFLOW_SRC=${BASH_SOURCE[0]//\\//}; case $_DOFLOW_SRC in */*) here=${_DOFLOW_SRC%/*} ;; *) here=. ;; esac
|
|
167
|
+
# The renderer beside the entry policy when it set _DOFLOW_POLDIR, else beside this file.
|
|
168
|
+
renderer=$here/emission.jq
|
|
169
|
+
[ -z "${_DOFLOW_POLDIR:-}" ] || [ ! -f "$_DOFLOW_POLDIR/emission.jq" ] || renderer=$_DOFLOW_POLDIR/emission.jq
|
|
170
|
+
|
|
171
|
+
# Step 2: identity, and the unit whose slot and ledger this event uses. The session id names
|
|
172
|
+
# git-context.json's directory for every lineage kind, so it is a path segment or a fault (DEC-042).
|
|
173
|
+
if ! [[ $session =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]]; then
|
|
174
|
+
_doflow_em_silent unit
|
|
175
|
+
return 0
|
|
176
|
+
fi
|
|
177
|
+
doflow_identity "$session" "$cwd"
|
|
178
|
+
role=$DF_ID_ROLE
|
|
179
|
+
kind=$DF_ID_KIND
|
|
180
|
+
unit=$DF_ID_UNIT
|
|
181
|
+
if ! [[ $unit =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]]; then
|
|
182
|
+
_doflow_em_silent unit
|
|
183
|
+
return 0
|
|
184
|
+
fi
|
|
185
|
+
# IC-010: lib.sh's SESSION_DIR is empty with no config home; there is no store, so nothing is
|
|
186
|
+
# claimed, rendered or recorded (src/runtime/context/arbitrate.js answers silent:no-home too).
|
|
187
|
+
sessions="${SESSION_DIR:-}"
|
|
188
|
+
if [ -z "$sessions" ]; then
|
|
189
|
+
DF_EMIT_REASON=silent:no-home
|
|
190
|
+
printf '{}\n'
|
|
191
|
+
return 0
|
|
192
|
+
fi
|
|
193
|
+
dir="$sessions/$unit"
|
|
194
|
+
max="${DOFLOW_CONTEXT_MAX_BYTES:-}"
|
|
195
|
+
[[ $max =~ ^[1-9][0-9]{0,9}$ ]] || max="${DF_RULES_MAX_BYTES_DEFAULT:-16384}"
|
|
196
|
+
harness="${DOFLOW_AGENT:-}"
|
|
197
|
+
[[ $harness =~ ^[A-Za-z0-9._-]{0,40}$ ]] || harness=unknown
|
|
198
|
+
|
|
199
|
+
# Step 3: state bits. The project directory, the legacy file, the warning and the owner summary
|
|
200
|
+
# only matter before the bootstrap, so a later prompt reads none of them.
|
|
201
|
+
if [ -e "$dir/injected" ] || [ -L "$dir/injected" ]; then bootstrapped=true; fi
|
|
202
|
+
if [ "$bootstrapped" = false ]; then
|
|
203
|
+
if [ -n "$cwd" ]; then project=$(ensure_project_dir "$cwd" 2>/dev/null) || project=""; fi
|
|
204
|
+
if [ -n "$project" ]; then
|
|
205
|
+
if doflow_summary_legacy_present "$cwd"; then legacy=true; fi
|
|
206
|
+
warnfile="$project/uncommitted-warning.txt"
|
|
207
|
+
if [ -f "$warnfile" ]; then warning=true; fi
|
|
208
|
+
fi
|
|
209
|
+
doflow_summary_peek "$DF_ID_WORKTREE" "$DF_ID_RUN" "$DF_ID_LINEAGE" "$session"
|
|
210
|
+
own=$DF_SUMMARY_OWN
|
|
211
|
+
fi
|
|
212
|
+
# Grants are addressed to launched units only: local, solo and main lineages are shared by
|
|
213
|
+
# unrelated sessions (DEC-039).
|
|
214
|
+
if [ "$kind" = launched ]; then
|
|
215
|
+
doflow_grant_peek "$DF_ID_RUN" "$DF_ID_LINEAGE" "$max"
|
|
216
|
+
grant=$DF_GRANT
|
|
217
|
+
fi
|
|
218
|
+
if [ "$grant" = over ] && _doflow_em_seen "$dir/emitted" grant "$DF_GRANT_ID" "$refusal"; then refused=true; fi
|
|
219
|
+
|
|
220
|
+
# Step 4: the legacy adoption, then the owner summary bit again.
|
|
221
|
+
_doflow_em_rule legacy-adopt.legacy "$role:$kind:$subagent:$bootstrapped:$legacy"
|
|
222
|
+
if [ "$DF_ACTION" = adopt ]; then
|
|
223
|
+
doflow_summary_adopt_legacy "$cwd" "$DF_ID_WORKTREE" || true
|
|
224
|
+
doflow_summary_peek "$DF_ID_WORKTREE" "$DF_ID_RUN" "$DF_ID_LINEAGE" "$session"
|
|
225
|
+
own=$DF_SUMMARY_OWN
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
# Step 5: one lookup per segment.
|
|
229
|
+
_doflow_em_actions
|
|
230
|
+
|
|
231
|
+
# Step 6: claims in the order slot, summary, grant, warning. EEXIST on the slot means another
|
|
232
|
+
# caller bootstrapped this unit: the segments are looked up again as bootstrapped, which makes
|
|
233
|
+
# every bootstrap-only one skip.
|
|
234
|
+
if [ "$a_slot" = claim ]; then
|
|
235
|
+
if ! mkdir -p "$dir" 2>/dev/null; then
|
|
236
|
+
_doflow_em_silent slot
|
|
237
|
+
return 0
|
|
238
|
+
fi
|
|
239
|
+
case $- in *C*) had_c=1 ;; esac
|
|
240
|
+
set -C
|
|
241
|
+
{ : >"$dir/injected"; } 2>/dev/null && made=1
|
|
242
|
+
[ "$had_c" = 1 ] || set +C
|
|
243
|
+
if [ "$made" = 0 ]; then
|
|
244
|
+
if [ -e "$dir/injected" ] || [ -L "$dir/injected" ]; then
|
|
245
|
+
bootstrapped=true
|
|
246
|
+
_doflow_em_actions
|
|
247
|
+
else
|
|
248
|
+
_doflow_em_silent slot
|
|
249
|
+
return 0
|
|
250
|
+
fi
|
|
251
|
+
fi
|
|
252
|
+
fi
|
|
253
|
+
# A lost claim (the source gone, or no longer a pending summary) makes that segment absent and the
|
|
254
|
+
# segments are looked up again; only a failure with the source still in place is a fault.
|
|
255
|
+
if [ "$a_summary" = truncate ]; then
|
|
256
|
+
if doflow_summary_claim "$DF_ID_WORKTREE" "$DF_ID_RUN" "$DF_ID_LINEAGE" "$unit" "$session"; then
|
|
257
|
+
sumfile=$DF_SUMMARY_CLAIMED
|
|
258
|
+
sumsrc=$DF_SUMMARY_SCOPE/summary.md
|
|
259
|
+
sumid=$DF_SUMMARY_SID
|
|
260
|
+
else
|
|
261
|
+
doflow_summary_peek "$DF_ID_WORKTREE" "$DF_ID_RUN" "$DF_ID_LINEAGE" "$session"
|
|
262
|
+
if [ "$DF_SUMMARY_OWN" = pending ]; then
|
|
263
|
+
_doflow_em_release
|
|
264
|
+
_doflow_em_silent summary
|
|
265
|
+
return 0
|
|
266
|
+
fi
|
|
267
|
+
own=none
|
|
268
|
+
_doflow_em_actions
|
|
269
|
+
fi
|
|
270
|
+
fi
|
|
271
|
+
if [ "$a_grant" = whole ]; then
|
|
272
|
+
grantsrc=$DF_GRANT_FILE
|
|
273
|
+
if doflow_grant_claim "$DF_ID_RUN" "$DF_ID_LINEAGE" "$unit" "$max"; then
|
|
274
|
+
grantfile=$DF_GRANT_CLAIMED
|
|
275
|
+
claimed_grant=$grantfile
|
|
276
|
+
grantsrc=$DF_GRANT_FILE
|
|
277
|
+
elif [ -n "$grantsrc" ] && [ -f "$grantsrc" ]; then
|
|
278
|
+
_doflow_em_release
|
|
279
|
+
_doflow_em_silent grant
|
|
280
|
+
return 0
|
|
281
|
+
else
|
|
282
|
+
grant=none
|
|
283
|
+
_doflow_em_actions
|
|
284
|
+
fi
|
|
285
|
+
elif [ "$a_grant" = pointer ]; then
|
|
286
|
+
# An over-budget grant is never claimed: it renders as its pointer from where it lies.
|
|
287
|
+
grantfile=$DF_GRANT_FILE
|
|
288
|
+
fi
|
|
289
|
+
# The warning is claimed by rename, so two first prompts deliver it once (DEC-040); read -d ''
|
|
290
|
+
# returns non-zero at EOF, which is accepted only once the claimed file is known to be readable.
|
|
291
|
+
if [ "$a_warning" = include ]; then
|
|
292
|
+
if mv "$warnfile" "$warnfile.claimed.$unit" 2>/dev/null; then
|
|
293
|
+
warnclaimed=$warnfile.claimed.$unit
|
|
294
|
+
if [ -r "$warnclaimed" ] && [ -f "$warnclaimed" ]; then
|
|
295
|
+
IFS= read -r -d '' warntext 2>/dev/null <"$warnclaimed" || true
|
|
296
|
+
else
|
|
297
|
+
_doflow_em_release
|
|
298
|
+
_doflow_em_silent warning
|
|
299
|
+
return 0
|
|
300
|
+
fi
|
|
301
|
+
elif [ -e "$warnfile" ] || [ -L "$warnfile" ]; then
|
|
302
|
+
_doflow_em_release
|
|
303
|
+
_doflow_em_silent warning
|
|
304
|
+
return 0
|
|
305
|
+
else
|
|
306
|
+
warning=false
|
|
307
|
+
_doflow_em_actions
|
|
308
|
+
fi
|
|
309
|
+
fi
|
|
310
|
+
|
|
311
|
+
# Nothing that renders: silence without a jq process.
|
|
312
|
+
case "$a_git $a_summary $a_warning $a_grant $a_nudge" in
|
|
313
|
+
*include* | *truncate* | *whole* | *pointer*) ;;
|
|
314
|
+
*)
|
|
315
|
+
if [ "$bootstrapped" = true ]; then DF_EMIT_REASON=silent:already-bootstrapped; else DF_EMIT_REASON=silent:unchanged; fi
|
|
316
|
+
printf '{}\n'
|
|
317
|
+
return 0
|
|
318
|
+
;;
|
|
319
|
+
esac
|
|
320
|
+
|
|
321
|
+
# Step 7: one jq process. A missing file is /dev/null and named in plan.absent.
|
|
322
|
+
gitfile="$sessions/$session/git-context.json"
|
|
323
|
+
if [ ! -f "$gitfile" ]; then gitfile=/dev/null; absent='"git"'; fi
|
|
324
|
+
[ "$sumfile" != /dev/null ] || absent="${absent:+$absent,}\"summary\""
|
|
325
|
+
[ "$grantfile" != /dev/null ] || absent="${absent:+$absent,}\"grant\""
|
|
326
|
+
[ "$a_warning" = include ] || absent="${absent:+$absent,}\"warning\""
|
|
327
|
+
[ -n "$payload_title" ] || title=true
|
|
328
|
+
plan="{\"actions\":{\"git\":\"$a_git\",\"summary\":\"$a_summary\",\"warning\":\"$a_warning\",\"grant\":\"$a_grant\",\"nudge\":\"$a_nudge\"},\"maxBytes\":$max,\"harness\":\"$harness\",\"title\":$title,\"absent\":[$absent]"
|
|
329
|
+
[ "$sumfile" = /dev/null ] || plan="$plan,\"summaryBytes\":${DF_SUMMARY_BYTES:-0}"
|
|
330
|
+
# Rider R1: the renderer hashes the response only when the bridge will write it (telemetry on, fd set).
|
|
331
|
+
[ "${DOFLOW_TELEMETRY:-}" = off ] || [ -z "${DOFLOW_DECISION_FD:-}" ] || digest=true
|
|
332
|
+
plan="$plan,\"digest\":$digest,\"mode\":\"hook\"}"
|
|
333
|
+
# Hook mode: the first line is the dropped segment names, tab-joined (possibly empty); the second
|
|
334
|
+
# is the response digest (empty unless plan.digest).
|
|
335
|
+
out=$(jq -n -r -f "$renderer" --argjson plan "$plan" --rawfile git "$gitfile" \
|
|
336
|
+
--rawfile summary "$sumfile" --rawfile grant "$grantfile" --arg warning "$warntext" \
|
|
337
|
+
--arg nudge "$nudge" 2>/dev/null) || out=""
|
|
338
|
+
[ "$sumfile" = /dev/null ] || rm -f "$sumfile" 2>/dev/null || true
|
|
339
|
+
[ -z "$claimed_grant" ] || rm -f "$claimed_grant" 2>/dev/null || true
|
|
340
|
+
[ -z "$warnclaimed" ] || rm -f "$warnclaimed" 2>/dev/null || true
|
|
341
|
+
sumfile=/dev/null claimed_grant="" warnclaimed=""
|
|
342
|
+
case "$out" in *$'\n'*$'\n'?*) ;; *) out="" ;; esac
|
|
343
|
+
if [ -z "$out" ]; then
|
|
344
|
+
_doflow_em_release
|
|
345
|
+
_doflow_em_silent render
|
|
346
|
+
return 0
|
|
347
|
+
fi
|
|
348
|
+
dropped=${out%%$'\n'*}
|
|
349
|
+
out=${out#*$'\n'}
|
|
350
|
+
digest=${out%%$'\n'*}
|
|
351
|
+
out=${out#*$'\n'}
|
|
352
|
+
|
|
353
|
+
# Step 8: the refusal ledger line (key: the grant's summary id), one optional-dropped line per
|
|
354
|
+
# dropped segment, then the nudge record.
|
|
355
|
+
DF_EMIT_REASON=emit
|
|
356
|
+
if [ "$a_grant" = pointer ]; then
|
|
357
|
+
DF_EMIT_REASON=$refusal
|
|
358
|
+
_doflow_em_ledger_add "$dir" grant "$DF_GRANT_ID" "$refusal" hook || _doflow_em_capture ledger
|
|
359
|
+
fi
|
|
360
|
+
rest=$dropped
|
|
361
|
+
while [ -n "$rest" ]; do
|
|
362
|
+
seg=${rest%%$'\t'*}
|
|
363
|
+
case "$rest" in *$'\t'*) rest=${rest#*$'\t'} ;; *) rest="" ;; esac
|
|
364
|
+
[ -n "$seg" ] || continue
|
|
365
|
+
key=$seg
|
|
366
|
+
[ "$seg" != summary ] || [ -z "$sumid" ] || key=$sumid
|
|
367
|
+
[ "$seg" != grant ] || [ -z "${DF_GRANT_ID:-}" ] || key=$DF_GRANT_ID
|
|
368
|
+
_doflow_em_ledger_add "$dir" optional-dropped "$key" over-budget hook || _doflow_em_capture ledger
|
|
369
|
+
done
|
|
370
|
+
if [ "$a_nudge" = include ]; then
|
|
371
|
+
case $'\t'"$dropped"$'\t' in
|
|
372
|
+
*$'\t'nudge$'\t'*) ;;
|
|
373
|
+
*)
|
|
374
|
+
DF_EMIT_NUDGE=rendered
|
|
375
|
+
if declare -F nudge_mark >/dev/null 2>&1; then nudge_mark "$session" nudged || true; fi
|
|
376
|
+
if declare -F doflow_decide >/dev/null 2>&1; then doflow_decide advisory prompt-nudge || true; fi
|
|
377
|
+
;;
|
|
378
|
+
esac
|
|
379
|
+
fi
|
|
380
|
+
_doflow_em_measure "$out" "$digest"
|
|
381
|
+
printf '%s\n' "$out"
|
|
382
|
+
return 0
|
|
383
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# identity.sh — Canonical Policy Library: session role and identity (feature 078, IC-007, IC-009)
|
|
3
|
+
#
|
|
4
|
+
# The only definition of doflow_session_role and doflow_identity (DEC-011). policies/lib.sh sources
|
|
5
|
+
# it from its own directory; the Claude and Codex hooks/lib.sh copies source it through
|
|
6
|
+
# ../../.doflow/shared/hooks/policies/identity.sh.
|
|
7
|
+
#
|
|
8
|
+
# Sourcing this file defines functions only: it sets no shell option, no variable and no trap, and
|
|
9
|
+
# prints nothing. Every function is bash 3.2 safe (no ${var,,}, no associative arrays) and safe
|
|
10
|
+
# under the caller's `set -euo pipefail`.
|
|
11
|
+
|
|
12
|
+
# Sets _DF_ROLE to `main` or `worker` from DOFLOW_SESSION_ROLE, matched case-insensitively, without
|
|
13
|
+
# a subshell. Unset or empty is `main`; any other value is `worker` and writes one stderr line, once
|
|
14
|
+
# per process (a call inside $(...) cannot mark the parent, so each such call still warns).
|
|
15
|
+
_doflow_role_resolve() {
|
|
16
|
+
case "${DOFLOW_SESSION_ROLE:-}" in
|
|
17
|
+
""|[Mm][Aa][Ii][Nn]) _DF_ROLE=main ;;
|
|
18
|
+
[Ww][Oo][Rr][Kk][Ee][Rr]) _DF_ROLE=worker ;;
|
|
19
|
+
*)
|
|
20
|
+
_DF_ROLE=worker
|
|
21
|
+
if [ -z "${_DF_ROLE_WARNED:-}" ]; then
|
|
22
|
+
echo "[doflow] unknown DOFLOW_SESSION_ROLE; treating session as worker" >&2
|
|
23
|
+
_DF_ROLE_WARNED=1
|
|
24
|
+
fi
|
|
25
|
+
;;
|
|
26
|
+
esac
|
|
27
|
+
return 0
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# Print `main` or `worker` for this session, read from DOFLOW_SESSION_ROLE (matched
|
|
31
|
+
# case-insensitively). Unset or empty is `main`; a value that is neither `main` nor
|
|
32
|
+
# `worker` is `worker` and writes one line to stderr. A worker never writes or claims the
|
|
33
|
+
# project's compact summary or warning. Always returns 0. bash 3.2 safe (no ${var,,}).
|
|
34
|
+
doflow_session_role() {
|
|
35
|
+
_doflow_role_resolve
|
|
36
|
+
printf '%s\n' "$_DF_ROLE"
|
|
37
|
+
return 0
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Record one failure-capture point for the calling policy, never on stdout or stderr. The policy
|
|
41
|
+
# name is the running script's name without `.sh` or `.impl.sh`; capture-failure.sh replaces a name
|
|
42
|
+
# outside its pattern with `unknown`.
|
|
43
|
+
_doflow_identity_capture() {
|
|
44
|
+
local point="$1" policy="${0##*/}" dir
|
|
45
|
+
policy="${policy%.sh}"
|
|
46
|
+
policy="${policy%.impl}"
|
|
47
|
+
# Inside a function, BASH_SOURCE[0] is the file that defined it: this file's directory.
|
|
48
|
+
_DOFLOW_SRC=${BASH_SOURCE[0]//\\//}; case $_DOFLOW_SRC in */*) dir=${_DOFLOW_SRC%/*} ;; *) dir=. ;; esac
|
|
49
|
+
if declare -F doflow_capture_failure >/dev/null 2>&1; then
|
|
50
|
+
( doflow_capture_failure "$policy" "$point" ) >/dev/null 2>&1 || true
|
|
51
|
+
else
|
|
52
|
+
( . "$dir/capture-failure.sh" && doflow_capture_failure "$policy" "$point" ) >/dev/null 2>&1 || true
|
|
53
|
+
fi
|
|
54
|
+
return 0
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# doflow_identity <session_id> <cwd>
|
|
58
|
+
# Sets DF_ID_RUN, DF_ID_ATTEMPT, DF_ID_LINEAGE, DF_ID_ROLE, DF_ID_WORKTREE, DF_ID_KIND and
|
|
59
|
+
# DF_ID_UNIT per IC-007. Reads only the launcher variables, the payload session_id and cwd; never
|
|
60
|
+
# git or the harness's idea of a main session. Built-ins only, except `pwd -P` in a `cd` subshell
|
|
61
|
+
# when DOFLOW_WORKTREE is set and `mkdir -p` when a launched unit binds. An invalid run or lineage
|
|
62
|
+
# is captured as `identity-invalid` and never reaches a path. Always returns 0.
|
|
63
|
+
doflow_identity() {
|
|
64
|
+
local session_id="${1:-}" cwd="${2:-}" LC_ALL=C
|
|
65
|
+
local run="${DOFLOW_RUN_ID:-}" attempt="${DOFLOW_ATTEMPT:-}" lineage="${DOFLOW_LINEAGE_ID:-}"
|
|
66
|
+
local worktree="${DOFLOW_WORKTREE:-}" invalid=0 run_ok=0 lineage_ok=0 attempt_ok=0
|
|
67
|
+
local sessions dir bound="" had_c=0 mine=0 tries
|
|
68
|
+
|
|
69
|
+
_doflow_role_resolve
|
|
70
|
+
DF_ID_ROLE=$_DF_ROLE
|
|
71
|
+
|
|
72
|
+
# run: id pattern and not `local`; unset is `local`; invalid is unlaunched with lineage solo.
|
|
73
|
+
if [ -z "$run" ]; then
|
|
74
|
+
DF_ID_RUN=local
|
|
75
|
+
elif [ "$run" != local ] && [[ $run =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,55}$ ]]; then
|
|
76
|
+
DF_ID_RUN=$run
|
|
77
|
+
run_ok=1
|
|
78
|
+
else
|
|
79
|
+
DF_ID_RUN=local
|
|
80
|
+
invalid=1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# attempt: integer 1 to 9999; invalid is as unset.
|
|
84
|
+
DF_ID_ATTEMPT=""
|
|
85
|
+
if [[ $attempt =~ ^[1-9][0-9]{0,3}$ ]]; then
|
|
86
|
+
DF_ID_ATTEMPT=$attempt
|
|
87
|
+
attempt_ok=1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# lineage: id pattern; unset is `main` for main and `solo` for worker; invalid is `solo`.
|
|
91
|
+
if [ -z "$lineage" ]; then
|
|
92
|
+
if [ "$DF_ID_ROLE" = main ]; then DF_ID_LINEAGE=main; else DF_ID_LINEAGE=solo; fi
|
|
93
|
+
elif [[ $lineage =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,55}$ ]]; then
|
|
94
|
+
DF_ID_LINEAGE=$lineage
|
|
95
|
+
lineage_ok=1
|
|
96
|
+
else
|
|
97
|
+
DF_ID_LINEAGE=solo
|
|
98
|
+
invalid=1
|
|
99
|
+
fi
|
|
100
|
+
if [ -n "$run" ] && [ "$run_ok" = 0 ]; then
|
|
101
|
+
DF_ID_LINEAGE=solo
|
|
102
|
+
lineage_ok=0
|
|
103
|
+
fi
|
|
104
|
+
[ "$invalid" = 0 ] || _doflow_identity_capture identity-invalid
|
|
105
|
+
|
|
106
|
+
# worktree: an absolute path to an existing directory, canonicalised; otherwise the payload cwd.
|
|
107
|
+
DF_ID_WORKTREE=$cwd
|
|
108
|
+
case "$worktree" in
|
|
109
|
+
/*)
|
|
110
|
+
if [ -d "$worktree" ]; then
|
|
111
|
+
worktree=$(CDPATH= cd -P -- "$worktree" 2>/dev/null && pwd -P) || worktree=""
|
|
112
|
+
[ -z "$worktree" ] || DF_ID_WORKTREE=$worktree
|
|
113
|
+
fi
|
|
114
|
+
;;
|
|
115
|
+
esac
|
|
116
|
+
|
|
117
|
+
if [ "$run_ok" = 1 ] && [ "$lineage_ok" = 1 ] && [ "$attempt_ok" = 1 ]; then
|
|
118
|
+
DF_ID_KIND=launched
|
|
119
|
+
DF_ID_UNIT="L.$DF_ID_RUN.$DF_ID_LINEAGE.$DF_ID_ATTEMPT"
|
|
120
|
+
elif [ "$DF_ID_RUN" = local ] && [ "$DF_ID_LINEAGE" = main ]; then
|
|
121
|
+
# default-main: run unset and lineage main, whether main was defaulted or set explicitly.
|
|
122
|
+
DF_ID_KIND=default-main
|
|
123
|
+
DF_ID_UNIT=$session_id
|
|
124
|
+
else
|
|
125
|
+
DF_ID_KIND=solo
|
|
126
|
+
DF_ID_UNIT=$session_id
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
# Binding (DEC-008, DEC-044): the first session to present a launched unit creates `bound`
|
|
130
|
+
# exclusively; a session whose id differs from the bound one is inherited and gets its own solo
|
|
131
|
+
# unit. A unit that cannot be bound with a session id (store unwritable, `bound` a symlink, which is
|
|
132
|
+
# never followed, or `bound` still empty after one retry) is inherited too. With no session id the
|
|
133
|
+
# unit is solo with an empty unit id and no capture.
|
|
134
|
+
if [ "$DF_ID_KIND" = launched ]; then
|
|
135
|
+
# The store is lib.sh's SESSION_DIR. Sourced without lib.sh, the config-home rule of
|
|
136
|
+
# src/runtime/config-home.js is applied inline (an absolute XDG_CONFIG_HOME, else an absolute
|
|
137
|
+
# HOME + /.config); with no config home there is no store and the unit is not bound (086 IC-010).
|
|
138
|
+
sessions="${SESSION_DIR:-}"
|
|
139
|
+
# doflow-config-home v1 inline copy: no marked block here, identity.sh defines only its four functions (086 B.2).
|
|
140
|
+
if [ -z "$sessions" ]; then
|
|
141
|
+
case "${XDG_CONFIG_HOME:-}" in
|
|
142
|
+
/*) sessions="$XDG_CONFIG_HOME/doflow/session-env/sessions" ;;
|
|
143
|
+
[A-Za-z]:[\\/]*) case "${OSTYPE:-}" in msys*|cygwin*|win32*) sessions="$XDG_CONFIG_HOME/doflow/session-env/sessions" ;; esac ;;
|
|
144
|
+
esac
|
|
145
|
+
case "${HOME:-}" in
|
|
146
|
+
/*) [ -n "$sessions" ] || sessions="$HOME/.config/doflow/session-env/sessions" ;;
|
|
147
|
+
[A-Za-z]:[\\/]*) case "${OSTYPE:-}" in msys*|cygwin*|win32*) [ -n "$sessions" ] || sessions="$HOME/.config/doflow/session-env/sessions" ;; esac ;;
|
|
148
|
+
esac
|
|
149
|
+
fi
|
|
150
|
+
dir="${sessions:+$sessions/$DF_ID_UNIT}"
|
|
151
|
+
if [ -n "$session_id" ] && [ -n "$dir" ] && mkdir -p "$dir" 2>/dev/null; then
|
|
152
|
+
case $- in *C*) had_c=1 ;; esac
|
|
153
|
+
set -C
|
|
154
|
+
{ printf '%s\n' "$session_id" >"$dir/bound"; } 2>/dev/null && mine=1
|
|
155
|
+
[ "$had_c" = 1 ] || set +C
|
|
156
|
+
if [ "$mine" = 0 ]; then
|
|
157
|
+
# An empty first line may be a concurrent binder between its create and its write.
|
|
158
|
+
for tries in 1 2; do
|
|
159
|
+
[ -f "$dir/bound" ] && [ ! -L "$dir/bound" ] || break
|
|
160
|
+
IFS= read -r bound 2>/dev/null <"$dir/bound" || true
|
|
161
|
+
[ -z "$bound" ] || break
|
|
162
|
+
done
|
|
163
|
+
[ -z "$bound" ] || [ "$bound" != "$session_id" ] || mine=1
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
if [ "$mine" = 0 ]; then
|
|
167
|
+
DF_ID_KIND=solo
|
|
168
|
+
DF_ID_LINEAGE=solo
|
|
169
|
+
DF_ID_UNIT=$session_id
|
|
170
|
+
if [ -n "$session_id" ] && [ -z "${_DF_ID_INHERITED_CAPTURED:-}" ]; then
|
|
171
|
+
_doflow_identity_capture identity-inherited
|
|
172
|
+
_DF_ID_INHERITED_CAPTURED=1
|
|
173
|
+
fi
|
|
174
|
+
fi
|
|
175
|
+
fi
|
|
176
|
+
return 0
|
|
177
|
+
}
|