@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
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
// handle<Name>Command(...)` — to cross-check the dispatcher's verb table in both directions. Keep
|
|
19
19
|
// every case in exactly that shape.
|
|
20
20
|
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
21
|
-
const fs = require('node:fs');
|
|
22
21
|
const os = require('node:os');
|
|
23
22
|
const path = require('node:path');
|
|
24
23
|
const {
|
|
25
24
|
handleCapabilitiesCommand, handleReadinessCommand, handleEvidenceCommand,
|
|
25
|
+
handleContextEmitCommand, handleContextGrantCommand,
|
|
26
26
|
} = require('../runtime/cli.js');
|
|
27
27
|
const { loadRegistry } = require('../registry/index.js');
|
|
28
28
|
const { enforcementFor, UnknownEnforcementTarget } = require('../lifecycle/coverage.js');
|
|
@@ -41,37 +41,135 @@ const { handleWorkflowCommand } = require('../runtime/workflow-engine.js');
|
|
|
41
41
|
const { handleOrchestrateCommand } = require('../runtime/workflow-orchestrator.js');
|
|
42
42
|
const { handleResearchRequestCommand } = require('../runtime/research-request.js');
|
|
43
43
|
const { handleTaskAttemptCommand } = require('../runtime/task-attempts.js');
|
|
44
|
+
const { handleWorkerCommand } = require('../runtime/worker/command.js');
|
|
45
|
+
const { handleDispatchCommand } = require('../runtime/dispatch/command.js');
|
|
44
46
|
const { handleRetrieveCommand } = require('../runtime/knowledge/retrieval.js');
|
|
45
47
|
const { handleModelRoleCommand } = require('../runtime/model-router.js');
|
|
46
48
|
const { handleRouteCommand } = require('../runtime/capability-router.js');
|
|
47
49
|
const { handleContextPackCommand } = require('../runtime/context-pack.js');
|
|
48
50
|
const { handleRetrievalPlanCommand } = require('../runtime/retrieval-plan.js');
|
|
49
51
|
const { handleOutcomeCommand } = require('../runtime/outcome.js');
|
|
50
|
-
const { handleVerifyCommand } = require('../runtime/verification/engine.js');
|
|
52
|
+
const { handleVerifyCommand, verifyStateRoot } = require('../runtime/verification/engine.js');
|
|
51
53
|
const { handleLeakScanCommand } = require('../runtime/leak-scan.js');
|
|
52
54
|
const { handleRecoverCommand } = require('../runtime/recovery.js');
|
|
53
55
|
const { handleScaffoldCommand } = require('../runtime/scaffold/generate.js');
|
|
54
|
-
const { handleDecisionCommand } = require('../runtime/decision-register.js');
|
|
56
|
+
const { handleDecisionCommand, isReservedChannel, CHANNEL_RESERVED } = require('../runtime/decision-register.js');
|
|
57
|
+
const { handleIntakeCommand } = require('../runtime/intake/index.js');
|
|
55
58
|
const { handleFollowupCommand, handleLifecycleCommand, handleGoalCommand } = require('../runtime/lifecycle/cli.js');
|
|
56
59
|
const { projectRoot: lifecycleProjectRoot } = require('../runtime/lifecycle/root.js');
|
|
57
60
|
const { upkeepAfterVerb } = require('../runtime/storage/upkeep.js');
|
|
58
61
|
const { handleStorageCommand } = require('../runtime/storage/cli.js');
|
|
62
|
+
const { handleRoadmapCommand, resolveMainRoot } = require('../runtime/roadmap/loop.js');
|
|
63
|
+
const { handlePlanCheckCommand } = require('../runtime/plan-check.js');
|
|
64
|
+
const { handleSlotCommand } = require('../runtime/slot-command.js');
|
|
65
|
+
const { handleReviewCommand } = require('../runtime/review/command.js');
|
|
66
|
+
const { handleProtocolCommand } = require('../runtime/review/protocol-command.js');
|
|
67
|
+
const { handleRulesCommand } = require('../runtime/rules-report.js');
|
|
68
|
+
const { handlePackageCommand } = require('../runtime/packages/command.js');
|
|
69
|
+
const { handleModelsCommand } = require('../runtime/models/command.js');
|
|
70
|
+
const { handleWorktreeCommand } = require('../runtime/roadmap/worktree-cleanup.js');
|
|
71
|
+
const { handleAttendanceCommand } = require('../runtime/roadmap/attendance.js');
|
|
72
|
+
// `plan-check` is read-only (115 IC-001): no upkeep, which would write `.gitignore` and `upkeep-due`.
|
|
73
|
+
// `review` writes only its one telemetry line (095 IC-003).
|
|
74
|
+
// `protocol` only prints the registry and the resolved protocol (119 IC-004), so it has nothing to keep up.
|
|
75
|
+
// `rules` only prints the values the runtime owns, with their sources, and writes nothing.
|
|
76
|
+
// `primary` only prints the resolved main session (120 IC-008) and writes nothing.
|
|
77
|
+
// `fleet` only lists the projects this machine knows from two read-only stores (093 IC-019) and writes nothing.
|
|
78
|
+
// `transcript` only reads agents' transcripts and DoFlow's own records and prints them (093 IC-022, IC-023); it writes nothing.
|
|
79
|
+
// `attendance` is read-only; `worktree --action cleanup` removes a merged feature's worktree under the roadmap lease and writes no DoFlow state, so neither runs upkeep.
|
|
80
|
+
// `package` stays here (122 IC-012): `new` writes only the target folder; `add --plan`, `update --plan` and `remove` write the store and lock and run upkeep (see `runsUpkeep`).
|
|
81
|
+
// `slot` is not here: `run`, `list` and `release` write the slot files and run upkeep; only `slot --action peek` is read-only and skips it (093 IC-018 b, see `runsUpkeep`).
|
|
82
|
+
const NO_UPKEEP = new Set(['storage', 'config', 'plan-check', 'review', 'protocol', 'rules', 'primary', 'package', 'models', 'fleet', 'transcript', 'worktree', 'attendance']);
|
|
83
|
+
const runsUpkeep = (o ) => (!NO_UPKEEP.has(o.cmd) && !(o.cmd === 'slot' && o.actionGiven && o.action === 'peek'))
|
|
84
|
+
|| (o.cmd === 'package' && ((typeof o.planId === 'string' && (o.action === 'add' || o.action === 'update')) || o.action === 'remove'));
|
|
59
85
|
// Required on first use, so a CLI whose failure modules cannot be loaded still runs every other verb.
|
|
60
86
|
function handleFailureCommand(options ) { return require('../runtime/failure/cli.js').handleFailureCommand(options); }
|
|
87
|
+
// The seed validator loads only for `roadmap seed`, and only this file may require it (G54).
|
|
88
|
+
function handleSeedCommand(options ) { return require('../runtime/roadmap/seed.js').handleSeedCommand(options); }
|
|
89
|
+
// maint-thin: `roadmap promote <id...>` lives in seed.ts too, so it stays out of every autopilot module (G54).
|
|
90
|
+
function handlePromoteCommand(options ) { return require('../runtime/roadmap/seed.js').handlePromoteCommand(options); }
|
|
91
|
+
// Settings support is needed only when the config verb runs.
|
|
92
|
+
function handleConfigCommand(options ) { return require('../runtime/settings/cli.js').handleConfigCommand(options); }
|
|
93
|
+
// The primary verb (row 120 A.4) needs the settings resolver only when it runs.
|
|
94
|
+
function handlePrimaryCommand(options ) { return require('../runtime/context/primary-command.js').handlePrimaryCommand(options); }
|
|
95
|
+
// The fleet verb (093 V.3) loads only when it runs.
|
|
96
|
+
function handleFleetCommand(options ) { return require('../runtime/fleet/command.js').handleFleetCommand(options); }
|
|
97
|
+
// The transcript verb (093 V.6) loads only when it runs.
|
|
98
|
+
function handleTranscriptCommand(options ) { return require('../runtime/transcripts/command.js').handleTranscriptCommand(options); }
|
|
61
99
|
const { handleInventoryCommand } = require('../runtime/inventory/index.js');
|
|
62
100
|
const { finishRuntime, usageError } = require('../runtime/cli-result.js');
|
|
63
|
-
const {
|
|
64
|
-
const { listCheckouts } = require('../runtime/checkouts.js');
|
|
101
|
+
const { setRecordSlug, callerFeatureSlug, invalidSlugRefusal, slugNamesNoFeature } = require('../runtime/task-scope.js');
|
|
102
|
+
const { listCheckouts, mayBeLinked } = require('../runtime/checkouts.js');
|
|
103
|
+
const { taskStateRoot, sweepWorktreeRecords } = require('../runtime/state-root.js');
|
|
65
104
|
const { featureSlugFor } = require('../runtime/implementation-gate.js');
|
|
66
105
|
const { handleBriefToolsCommand } = require('../runtime/brief-tools.js');
|
|
67
|
-
|
|
106
|
+
// Advice writers load settings/write.ts, so keep that surface off installer and other verb paths.
|
|
107
|
+
function handleAdviseCommand(options ) { return require('../runtime/advice/cli.js').handleAdviseCommand(options); }
|
|
68
108
|
const { REPO_ROOT, buildAdapterRegistry } = require('./shared.js');
|
|
69
109
|
|
|
70
110
|
/** Where `readiness`/`evidence` read and write per-task state. Mirrors scopeOf()'s rules so these
|
|
71
111
|
* commands are scope-aware like the rest of the CLI, rather than defaulting to the DoFlow install
|
|
72
112
|
* directory — which for an npm install is inside node_modules/. */
|
|
73
113
|
function evidenceRoot(o ) {
|
|
74
|
-
|
|
114
|
+
if (o.global) return os.homedir();
|
|
115
|
+
// `roadmap seed [<project>]` (113 IC-001): the sub-verb takes the first positional slot, so the project root is the one after it.
|
|
116
|
+
if (o.cmd === 'roadmap' && o.positional[0] === 'seed') return path.resolve(o.positional[1] || '.');
|
|
117
|
+
return path.resolve(o.positional[0] || '.');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** The `trace` views that take the first positional slot: `spans` (088 IC-011), `analyze` (091 IC-001), `export` (091 IC-006). */
|
|
121
|
+
const TRACE_VIEWS = new Set(['spans', 'analyze', 'export']);
|
|
122
|
+
|
|
123
|
+
/** `trace spans|analyze|export [<project>]`: the view name takes the first positional slot, so the
|
|
124
|
+
* project root is the one after it. Every other call is `evidenceRoot(o)`. */
|
|
125
|
+
function traceViewRoot(o ) {
|
|
126
|
+
return o.cmd === 'trace' && TRACE_VIEWS.has(o.positional[0]) && !o.global ? path.resolve(o.positional[1] || '.') : evidenceRoot(o);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** `roadmap`: the runner, the `seed` sub-verb (113 IC-001), or the `promote` sub-verb (maint-thin), each taking the
|
|
130
|
+
* first positional slot and setting the exit code itself; `promote` runs on the main checkout of the working directory. */
|
|
131
|
+
function handleRoadmapVerbCommand(o ) {
|
|
132
|
+
const action = o.actionGiven ? o.action : undefined;
|
|
133
|
+
if (o.positional[0] === 'seed') return finishRuntime(handleSeedCommand({ action, draft: o.draft, json: o.json, cwd: process.cwd(), root: resolveMainRoot(evidenceRoot(o)) }));
|
|
134
|
+
if (o.positional[0] === 'promote') return finishRuntime(handlePromoteCommand({ ids: o.positional.slice(1), json: o.json, root: resolveMainRoot(process.cwd()) }));
|
|
135
|
+
// `init-policy --commit` commits the policy onto develop; it lives outside the loop's tree (G53, G54). Any other action with --commit is the loop's exit 2.
|
|
136
|
+
if (o.commit && action === 'init-policy') return require('../runtime/policy-init.js').commitPolicyCommand({ json: o.json, root: resolveMainRoot(evidenceRoot(o)), repoRoot: REPO_ROOT });
|
|
137
|
+
return handleRoadmapCommand({ action, check: o.check, commit: o.commit, json: o.json, run: o.run, row: o.row, cwd: evidenceRoot(o), repoRoot: REPO_ROOT });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Where `trace analyze --emit followups --task-id` reads the task's evidence ledger: the store root
|
|
142
|
+
* and record slug the `evidence` verb writes under (115 IC-004, C-1), so a linked worktree reads the
|
|
143
|
+
* main checkout's namespaced ledger. Read only: no sweep, so a record still left in the worktree's
|
|
144
|
+
* own store is not cited. Undefined when no ledger is read; the handler refuses the flag mix itself.
|
|
145
|
+
*/
|
|
146
|
+
function analyzeLedgerRoot(o ) {
|
|
147
|
+
if (o.emit !== 'followups' || typeof o.taskId !== 'string') return undefined;
|
|
148
|
+
const caller = traceViewRoot(o);
|
|
149
|
+
const checkouts = !o.global && mayBeLinked(caller) ? listCheckouts({ cwd: caller }) : null;
|
|
150
|
+
setRecordSlug(() => o.slug || callerFeatureSlug({ projectRoot: caller, taskId: o.taskId }) || null);
|
|
151
|
+
return taskStateRoot({ global: o.global, positional: [caller] }, checkouts).root;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** `trace`: the ledger trajectory, unchanged, or the `spans`, `analyze` or `export` view, whose modules load
|
|
155
|
+
* only for that view so `trace` and `stats` read nothing new (NFR-010, 091 NFR-009). */
|
|
156
|
+
function handleTraceViewCommand(o ) {
|
|
157
|
+
if (o.positional[0] === 'analyze') {
|
|
158
|
+
return require('../runtime/trace/analyze.js').handleTraceAnalyze({ positional: o.positional.slice(1), run: o.run, json: o.json, global: o.global,
|
|
159
|
+
emit: o.emit, taskId: o.taskId, stateRoot: analyzeLedgerRoot(o) });
|
|
160
|
+
}
|
|
161
|
+
if (o.positional[0] === 'export') {
|
|
162
|
+
return require('../runtime/trace/otlp-export.js').handleTraceExport({
|
|
163
|
+
positional: o.positional.slice(1),
|
|
164
|
+
run: o.run,
|
|
165
|
+
json: o.json,
|
|
166
|
+
global: o.global,
|
|
167
|
+
dryRun: o.dryRun,
|
|
168
|
+
otlpHttp: o.otlpHttp,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
if (o.positional[0] !== 'spans') return handleTraceCommand({ json: o.json, days: o.days, global: o.global, projectRoot: evidenceRoot(o) });
|
|
172
|
+
return require('../runtime/trace/spans.js').handleTraceSpans({ positional: o.positional.slice(1), run: o.run, json: o.json, global: o.global });
|
|
75
173
|
}
|
|
76
174
|
|
|
77
175
|
/**
|
|
@@ -130,33 +228,21 @@ function evidenceItemFromFlags(o ) {
|
|
|
130
228
|
return item;
|
|
131
229
|
}
|
|
132
230
|
|
|
133
|
-
/** Verbs that read or write per-task records, and so accept `--slug` (IC-002).
|
|
134
|
-
|
|
231
|
+
/** Verbs that read or write per-task records, and so accept `--slug` (IC-002). Their records, and
|
|
232
|
+
* `orchestrate`'s run and `context-emit`'s delivery, live in `taskStateRoot` (115 IC-004). */
|
|
233
|
+
const TASK_STORE_VERBS = new Set(['evidence', 'claim', 'readiness', 'context-pack', 'research-request', 'outcome', 'retrieval-plan', 'retrieve']);
|
|
135
234
|
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
235
|
+
/** The checkout a call runs in: `context-emit`'s `--cwd`, else the positional project root. */
|
|
236
|
+
function callerRoot(o ) {
|
|
237
|
+
return o.cmd === 'context-emit' && typeof o.cwd === 'string' && o.cwd !== '' ? path.resolve(o.cwd) : evidenceRoot(o);
|
|
238
|
+
}
|
|
139
239
|
|
|
140
|
-
/**
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
*/
|
|
147
|
-
function featureStoreRoot(o , checkouts ) {
|
|
148
|
-
if (!FEATURE_STORE_VERBS.has(o.cmd) || o.global) return null;
|
|
149
|
-
if (!checkouts.isLinked) return null;
|
|
150
|
-
let slug = o.slug || null;
|
|
151
|
-
if (!slug) {
|
|
152
|
-
try {
|
|
153
|
-
const feature = resolveFeature({ projectRoot: checkouts.current });
|
|
154
|
-
slug = !feature.error && feature.paths ? feature.paths.feature_slug : null;
|
|
155
|
-
} catch { /* a failed branch lookup cannot route state to a guessed feature */ }
|
|
156
|
-
}
|
|
157
|
-
const folder = (root ) => path.join(root, 'agent-docs', 'doflow', slug || '');
|
|
158
|
-
if (!slug || fs.existsSync(folder(checkouts.current)) || !fs.existsSync(folder(checkouts.main))) return null;
|
|
159
|
-
return { root: checkouts.main, slug };
|
|
240
|
+
/** The store conflicts a sweep found, one line each (IC-006). */
|
|
241
|
+
function conflictText(o , sweep ) {
|
|
242
|
+
const lines = sweep.conflicts.map((c ) => (c.reason === 'link' ? ` ${c.worktree} -> ${c.main}: a link on the way, nothing is moved through it`
|
|
243
|
+
: c.reason === 'same-file' ? ` ${c.worktree} and ${c.main} are one file` : ` ${c.worktree} differs from ${c.main}`));
|
|
244
|
+
return `doflow ${o.cmd}: store-conflict: ${sweep.conflicts.length} record(s) in this worktree could not be moved to the main checkout; `
|
|
245
|
+
+ `files already moved stay moved. Keep one copy of each pair and remove the other, then re-run.\n${lines.join('\n')}`;
|
|
160
246
|
}
|
|
161
247
|
|
|
162
248
|
/**
|
|
@@ -166,6 +252,14 @@ function featureStoreRoot(o , checkouts )
|
|
|
166
252
|
* to the engine module each case names.
|
|
167
253
|
*/
|
|
168
254
|
function dispatchRuntimeCommandInner(o , moment ) {
|
|
255
|
+
// IC-005: no caller names a decider. orchestrate takes no --by, and the channel `policy` (decided
|
|
256
|
+
// by autopilot) is refused on every verb, before any state is read or written.
|
|
257
|
+
if (o.cmd === 'orchestrate' && o.by !== undefined) {
|
|
258
|
+
return usageError('orchestrate', '--by is not accepted; the runtime derives the gate decider', o.json);
|
|
259
|
+
}
|
|
260
|
+
if (isReservedChannel(o.channel)) {
|
|
261
|
+
return usageError(o.cmd, CHANNEL_RESERVED, o.json);
|
|
262
|
+
}
|
|
169
263
|
// A slug becomes a directory name and a state key, so one that could name a path is refused
|
|
170
264
|
// here, once, for every verb that reads `--slug`, before any of them reads or writes state
|
|
171
265
|
// (FR-013, IC-009). A well-formed slug that names no feature is the verbs' own business.
|
|
@@ -179,32 +273,69 @@ function dispatchRuntimeCommandInner(o , moment ) {
|
|
|
179
273
|
// here so the verbs whose handlers build their own ledger (readiness, evidence) route the same
|
|
180
274
|
// way as the ones that take `slug` directly. The orchestration journal is keyed by slug already.
|
|
181
275
|
// Reset on every dispatch, so one invocation's slug can never carry into the next in-process call.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const
|
|
276
|
+
// `retrieve` is a task-store verb only as bound code retrieval (--scope code with --task-id or --slug):
|
|
277
|
+
// guidance retrieval and unbound code retrieval record nothing in a feature store, so they keep the
|
|
278
|
+
// pre-079 dispatch (no checkout listing, no feature resolver, no store note).
|
|
279
|
+
const storeVerb = (verbs ) => verbs.has(o.cmd) && (o.cmd !== 'retrieve' || (o.scope === 'code' && Boolean(o.taskId || o.slug)));
|
|
280
|
+
const recordVerb = storeVerb(TASK_STORE_VERBS) || o.cmd === 'orchestrate' || o.cmd === 'context-emit';
|
|
281
|
+
const caller = callerRoot(o);
|
|
282
|
+
// `evidence` always lists: its attempt lookup reuses the main checkout from this one listing.
|
|
283
|
+
const checkouts = recordVerb && !o.global && (o.cmd === 'evidence' || mayBeLinked(caller))
|
|
284
|
+
? listCheckouts({ cwd: caller }) : null;
|
|
285
|
+
// 115 IC-004: a linked, non-sandbox worktree keeps every per-task record in the main checkout.
|
|
286
|
+
const { root: storeRoot, redirected } = recordVerb ? taskStateRoot(o, checkouts) : { root: evidenceRoot(o), redirected: false };
|
|
186
287
|
const attemptRoot = checkouts?.ok && !checkouts.sandbox ? (checkouts.main || checkouts.current || null) : null;
|
|
187
288
|
// Use the same root resolver as the handler: task redirection, the nearest run ledger,
|
|
188
289
|
// and lifecycle's shared main-worktree store are deliberately different scopes.
|
|
189
290
|
try {
|
|
190
291
|
if (['trace', 'stats', 'discover'].includes(o.cmd)) {
|
|
191
|
-
moment.projectRoot = path.dirname(resolveRunsLocation({ start:
|
|
192
|
-
} else if (['followup', 'lifecycle', 'goal', 'task-attempt'].includes(o.cmd)) {
|
|
292
|
+
moment.projectRoot = path.dirname(resolveRunsLocation({ start: traceViewRoot(o), global: o.global }).configDir);
|
|
293
|
+
} else if (['followup', 'lifecycle', 'goal', 'task-attempt', 'worker', 'dispatch'].includes(o.cmd)) {
|
|
193
294
|
moment.projectRoot = lifecycleProjectRoot(evidenceRoot(o));
|
|
295
|
+
} else if (o.cmd === 'plan-check' || o.cmd === 'slot') {
|
|
296
|
+
moment.projectRoot = process.cwd(); // the first positional of plan-check is a file, never a project root
|
|
297
|
+
} else if (o.cmd === 'verify') {
|
|
298
|
+
moment.projectRoot = verifyStateRoot({ start: evidenceRoot(o) }).projectRoot; // the store verify writes, never a cwd fragment
|
|
194
299
|
} else {
|
|
195
300
|
moment.projectRoot = storeRoot;
|
|
196
301
|
}
|
|
197
302
|
} catch { /* a failed upkeep lookup must not change the verb's answer */ }
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
303
|
+
// 115 C-1: one record slug per call, `--slug`, else the feature of the checkout the verb runs in,
|
|
304
|
+
// used by every store the call touches (task-scope.ts). It is looked up on first use, so a
|
|
305
|
+
// `context-emit` event that compiles no pack spawns no resolver. Reset on every dispatch, so one
|
|
306
|
+
// invocation's slug can never carry into the next in-process call. `retrieve` is a task-store verb
|
|
307
|
+
// only as bound code retrieval (--scope code with --task-id or --slug).
|
|
308
|
+
let slugMemo ;
|
|
309
|
+
const recordSlug = () => {
|
|
310
|
+
if (slugMemo === undefined) {
|
|
311
|
+
try { slugMemo = o.slug || callerFeatureSlug({ projectRoot: caller, taskId: o.taskId }) || null; } catch { slugMemo = null; }
|
|
312
|
+
}
|
|
313
|
+
return slugMemo ;
|
|
314
|
+
};
|
|
315
|
+
setRecordSlug(recordVerb ? recordSlug : undefined);
|
|
316
|
+
const storeSlug = recordVerb && o.cmd !== 'context-emit' ? recordSlug() : undefined;
|
|
317
|
+
if (redirected && o.cmd !== 'context-emit') {
|
|
318
|
+
console.error(`doflow ${o.cmd}: note: records are kept in the main checkout ${storeRoot}`);
|
|
202
319
|
}
|
|
203
|
-
// A well-formed slug that names no feature
|
|
204
|
-
//
|
|
205
|
-
if (
|
|
206
|
-
&& slugNamesNoFeature({
|
|
207
|
-
console.error(`doflow ${o.cmd}: note: --slug '${o.slug}' names no feature;
|
|
320
|
+
// A well-formed slug that names no feature folder still names the records' namespace, but the
|
|
321
|
+
// caller typed it expecting a feature, so say so once, on stderr only.
|
|
322
|
+
if (storeVerb(TASK_STORE_VERBS) && typeof o.slug === 'string' && o.slug !== ''
|
|
323
|
+
&& slugNamesNoFeature({ projectRoots: redirected ? [caller, storeRoot] : [caller], slug: o.slug })) {
|
|
324
|
+
console.error(`doflow ${o.cmd}: note: --slug '${o.slug}' names no feature folder; its records are kept under that slug`);
|
|
325
|
+
}
|
|
326
|
+
// 115 IC-006: every record left in the worktree's own store moves to the main checkout first, in one
|
|
327
|
+
// locked sweep; a record held in both with different bytes refuses the call before the verb runs.
|
|
328
|
+
// 092 IC-001, 093 IC-012: the orchestrate reads (list, status, timeline) write nothing, so they never sweep: they read the
|
|
329
|
+
// main checkout's store and see a record still left in this worktree as another checkout's
|
|
330
|
+
// (`orchestrationRuns`, `findRunFile`). The next write verb from here sweeps it as before.
|
|
331
|
+
const orchestrateRead = o.cmd === 'orchestrate' && (o.action === 'list' || o.action === 'status' || o.action === 'timeline');
|
|
332
|
+
if (redirected && !orchestrateRead) {
|
|
333
|
+
const sweep = sweepWorktreeRecords({ mainRoot: storeRoot, worktreeRoot: checkouts.current, recordSlug });
|
|
334
|
+
if (!sweep.ok) {
|
|
335
|
+
if (o.json) console.log(JSON.stringify(sweep, null, 2));
|
|
336
|
+
else console.error(conflictText(o, sweep));
|
|
337
|
+
return finishRuntime(2);
|
|
338
|
+
}
|
|
208
339
|
}
|
|
209
340
|
switch (o.cmd) {
|
|
210
341
|
// REPO_ROOT locates the capability registry; projectRoot is the tree whose index freshness
|
|
@@ -226,13 +357,13 @@ function dispatchRuntimeCommandInner(o , moment ) {
|
|
|
226
357
|
// all this does: the handler names them back under `callerAsserted` so a stated input is
|
|
227
358
|
// never mistaken for a measured one.
|
|
228
359
|
case 'readiness': return handleReadinessCommand({ taskClass: requireTaskClass(o), taskId: requireTaskId(o), verificationPlan: o.verificationPlan, scopeClear: o.scope, invariants: o.invariants, userDecisionPending: o.userDecisionPending, mode: o.mode, slug: storeSlug, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, sourceRoot: evidenceRoot(o) });
|
|
229
|
-
case 'evidence': return handleEvidenceCommand({ taskId: requireTaskId(o), action: o.action, item: evidenceItemFromFlags(o), batchPath: o.batchPath, evidenceId: o.evidenceId, replacedBy: o.replacedBy, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, slug: storeSlug, sourceRoot: evidenceRoot(o), attemptRoot });
|
|
360
|
+
case 'evidence': return handleEvidenceCommand({ taskId: requireTaskId(o), action: o.action, item: evidenceItemFromFlags(o), batchPath: o.batchPath, evidenceId: o.evidenceId, replacedBy: o.replacedBy, stale: o.stale, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, slug: storeSlug, sourceRoot: evidenceRoot(o), attemptRoot });
|
|
230
361
|
// Run-ledger views. They resolve their own ledger the way the dispatcher does (nearest
|
|
231
362
|
// `.doflow` walking up, or the global one) rather than assuming cwd is the project root, so
|
|
232
363
|
// a view invoked from a subdirectory reads the runs that were actually recorded.
|
|
233
364
|
// Exit codes follow design §4.2 and are set by the handler itself: 0 = answered, 1 = a
|
|
234
365
|
// finding the caller must act on.
|
|
235
|
-
case 'trace': return
|
|
366
|
+
case 'trace': return handleTraceViewCommand(o);
|
|
236
367
|
case 'stats': return handleStatsCommand({ json: o.json, days: o.days, global: o.global, projectRoot: evidenceRoot(o) });
|
|
237
368
|
case 'indicators': return handleIndicatorsCommand({ json: o.json, projectRoot: evidenceRoot(o) });
|
|
238
369
|
case 'discover': return handleDiscoverCommand({ json: o.json, days: o.days, global: o.global, projectRoot: evidenceRoot(o) });
|
|
@@ -243,6 +374,7 @@ function dispatchRuntimeCommandInner(o , moment ) {
|
|
|
243
374
|
// the process home directory inside the lifecycle view (design R7) and is not an argument.
|
|
244
375
|
case 'inventory': return handleInventoryCommand({ json: o.json, global: o.global, targets: o.targets, repoRoot: REPO_ROOT, projectRoot: path.resolve(o.positional[0] || '.') });
|
|
245
376
|
case 'storage': return handleStorageCommand({ action: o.actionGiven ? o.action : 'report', json: o.json, global: o.global, projectRoot: evidenceRoot(o) });
|
|
377
|
+
case 'config': return handleConfigCommand({ json: o.json, global: o.global, showOrigin: o.showOrigin, positional: o.positional, layer: o.layer, preparedRun: o.preparedRun, repoRoot: REPO_ROOT });
|
|
246
378
|
// No REPO_ROOT: the scaffold's repo root is the *caller's* repo, reported by the resolver,
|
|
247
379
|
// because the plan's `files:` paths are relative to it. Passing the DoFlow install here
|
|
248
380
|
// would detect the wrong language and mirror the wrong tree.
|
|
@@ -250,10 +382,12 @@ function dispatchRuntimeCommandInner(o , moment ) {
|
|
|
250
382
|
// The feature is resolved from the working directory (or --slug) by the same resolver
|
|
251
383
|
// `scaffold` uses; the flags are the caller's own statements, validated by the register module.
|
|
252
384
|
case 'decision': return handleDecisionCommand({ action: o.action, projectRoot: evidenceRoot(o), slug: o.slug, json: o.json, flags: { topic: o.topic, statement: o.statement, channel: o.channel, stage: o.stage, rationale: o.rationale, supersedes: o.supersedes, refs: o.refs, source: o.source, batch: o.batchPath, all: o.all } });
|
|
385
|
+
// 136: the feature is resolved the way `decision` resolves it; the engine moves files only inside its additional-context folder.
|
|
386
|
+
case 'intake': return handleIntakeCommand({ action: o.action, projectRoot: evidenceRoot(o), slug: o.slug, json: o.json, flags: { runId: o.runId, stdin: o.stdin, file: o.file, stage: o.stage } });
|
|
253
387
|
// Feature 046: the project's follow-up store lives at the repository root (never `-g`, which
|
|
254
388
|
// the handlers refuse), so the working directory is the starting point, not a scope switch.
|
|
255
|
-
case 'followup': return handleFollowupCommand({ action: o.actionGiven ? o.action : undefined, cwd: evidenceRoot(o), global: o.global, slug: o.slug, json: o.json, flags: { statement: o.statement, stage: o.stage, source: o.source, taskClass: o.taskClass, taskId: o.taskId, release: o.release, batch: o.batchPath, channel: o.channel, state: o.state, ids: o.ids, as: o.as, reason: o.reason, evidence: o.evidence, title: o.title, file: o.file, stdin: o.stdin, text: o.text, feature: o.feature, tag: o.tag, confirm: o.confirm, exclude: o.exclude } });
|
|
256
|
-
case 'lifecycle': return handleLifecycleCommand({ action: o.actionGiven ? o.action : undefined, cwd: evidenceRoot(o), global: o.global, slug: o.slug, json: o.json, flags: { take: o.take, intent: o.intent, goal: o.goal, maintain: o.maintain, since: o.since, tag: o.tag, confirm: o.confirm, feature: o.feature, exclude: o.exclude, reason: o.reason, channel: o.channel } });
|
|
389
|
+
case 'followup': return handleFollowupCommand({ action: o.actionGiven ? o.action : undefined, cwd: evidenceRoot(o), global: o.global, slug: o.slug, json: o.json, flags: { statement: o.statement, stage: o.stage, source: o.source, taskClass: o.taskClass, taskId: o.taskId, release: o.release, batch: o.batchPath, channel: o.channel, state: o.state, ids: o.ids, view: o.view, cursor: o.cursor, limit: o.limit, as: o.as, reason: o.reason, evidence: o.evidence, title: o.title, file: o.file, stdin: o.stdin, text: o.text, feature: o.feature, tag: o.tag, confirm: o.confirm, exclude: o.exclude } });
|
|
390
|
+
case 'lifecycle': return handleLifecycleCommand({ action: o.actionGiven ? o.action : undefined, cwd: evidenceRoot(o), global: o.global, slug: o.slug, json: o.json, flags: { view: o.view, take: o.take, intent: o.intent, goal: o.goal, maintain: o.maintain, since: o.since, tag: o.tag, confirm: o.confirm, feature: o.feature, exclude: o.exclude, reason: o.reason, channel: o.channel } });
|
|
257
391
|
case 'goal': return handleGoalCommand({ action: o.actionGiven ? o.action : undefined, cwd: evidenceRoot(o), global: o.global, slug: o.slug, json: o.json, flags: { goal: o.goal, statement: o.statement, item: o.item, text: o.text, evidence: o.evidence, unmet: o.unmet, replace: o.replace, reason: o.reason, channel: o.channel } });
|
|
258
392
|
// The failure store is per machine, so `-g` changes nothing and the working directory only matters
|
|
259
393
|
// to `settle --as imported`, which looks for the DoFlow repository from there.
|
|
@@ -261,25 +395,51 @@ function dispatchRuntimeCommandInner(o , moment ) {
|
|
|
261
395
|
// The rest of design §4.2's Node arm. REPO_ROOT locates the registries that ship with the
|
|
262
396
|
// package (workflows, capabilities, verification); evidenceRoot(o) locates the caller's own
|
|
263
397
|
// state and source tree, following the same scope rules as every other command.
|
|
264
|
-
case 'classify': return handleClassifyCommand({ taskClass: o.taskClass, rationale: o.rationale, proposedBy: o.proposedBy, callingSkill: o.callingSkill, request: o.request, requestFile: o.requestFile, taskId: o.taskId, projectRoot: evidenceRoot(o), json: o.json });
|
|
398
|
+
case 'classify': return handleClassifyCommand({ taskClass: o.taskClass, rationale: o.rationale, proposedBy: o.proposedBy, callingSkill: o.callingSkill, view: o.view, request: o.request, requestFile: o.requestFile, taskId: o.taskId, projectRoot: evidenceRoot(o), json: o.json });
|
|
265
399
|
case 'workflow': return handleWorkflowCommand({ taskClass: o.taskClass, json: o.json });
|
|
266
|
-
case 'orchestrate': return handleOrchestrateCommand({ action: o.action, taskId: o.taskId, taskClass: o.taskClass, stage: o.stage, gate: o.gate, node: o.node, decision: o.decision, note: o.note, reason: o.reason, forced: o.forced, verificationPlan: o.verificationPlan, scope: o.scope, invariants: o.invariants, result: o.result, mcpOutcome: o.mcpOutcome, callingSkill: o.callingSkill, slug: o.slug, json: o.json, repoRoot: REPO_ROOT, stateRoot: evidenceRoot(o), buildAdapters: buildAdapterRegistry });
|
|
267
|
-
case 'research-request': return handleResearchRequestCommand({ slug:
|
|
400
|
+
case 'orchestrate': return handleOrchestrateCommand({ action: o.action, taskId: o.taskId, taskClass: o.taskClass, stage: o.stage, gate: o.gate, node: o.node, decision: o.decision, policy: o.policy, note: o.note, reason: o.reason, forced: o.forced, verificationPlan: o.verificationPlan, scope: o.scope, invariants: o.invariants, result: o.result, mcpOutcome: o.mcpOutcome, callingSkill: o.callingSkill, slug: o.slug, recordSlug: storeSlug, dryRun: o.dryRun, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, sourceRoot: evidenceRoot(o), buildAdapters: buildAdapterRegistry });
|
|
401
|
+
case 'research-request': return handleResearchRequestCommand({ slug: storeSlug, action: o.action === 'status' ? 'list' : o.action, taskId: requireTaskId(o), stageId: o.stageId, question: o.question, reason: o.reason, blocking: o.blocking === undefined ? undefined : o.blocking === 'true' ? true : o.blocking === 'false' ? false : o.blocking, requestId: o.requestId, outcome: o.researchOutcome, claimId: o.claimId, evidenceIds: o.evidenceIds, gap: o.gap, json: o.json, projectRoot: storeRoot, sourceRoot: evidenceRoot(o) });
|
|
268
402
|
// The store is shared by every linked worktree of the clone (lifecycle's main-worktree root); the
|
|
269
403
|
// feature is `--slug`, else the branch's, resolved the way decision and scaffold resolve it.
|
|
270
|
-
case 'task-attempt': return handleTaskAttemptCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, task: o.task, owner: o.owner, mode: o.mode, token: o.token, result: o.result, evidenceId: o.evidenceId, reason: o.reason, json: o.json, cwd: evidenceRoot(o), resolveSlug: (cwd ) => featureSlugFor({ projectRoot: cwd }) });
|
|
271
|
-
|
|
404
|
+
case 'task-attempt': return handleTaskAttemptCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, task: o.task, owner: o.owner, mode: o.mode, token: o.token, result: o.result, evidenceId: o.evidenceId, reason: o.reason, ownerOverride: o.ownerOverride, epoch: o.epoch, reserveTokens: o.reserveTokens, execWorktree: o.execWorktree, tokens: o.tokens, tokensBasis: o.tokensBasis, budgetAttempts: o.budgetAttempts, budgetTokens: o.budgetTokens, by: o.by, ack: o.ack, adoptUnowned: Boolean(o.adoptUnowned), json: o.json, cwd: evidenceRoot(o), resolveSlug: (cwd ) => featureSlugFor({ projectRoot: cwd }) });
|
|
405
|
+
// 081 IC-026: the worker adapter reads and writes the same main-worktree store as task-attempt.
|
|
406
|
+
case 'worker': return handleWorkerCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, harness: o.harness, need: o.need, modelCheck: o.modelCheck, budgetTokens: o.budgetTokens, task: o.task, token: o.token, promptFile: o.promptFile, timeoutSeconds: o.timeoutSeconds, wait: Boolean(o.wait), edit: Boolean(o.edit), childOf: o.childOf, request: o.request, execWorktree: o.execWorktree, workerRun: o.workerRun, checks: o.checks, out: o.out, by: o.by, reason: o.reason, json: o.json, env: process.env, cwd: evidenceRoot(o), resolveSlug: (cwd ) => featureSlugFor({ projectRoot: cwd }) });
|
|
407
|
+
// 082 IC-001, IC-038: the dispatch loop shares the main-worktree store root with task-attempt.
|
|
408
|
+
// `--status` is parsed under `attemptStatus` (retrieval-plan's key), so it is renamed here.
|
|
409
|
+
case 'dispatch': return handleDispatchCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, by: o.by, reason: o.reason, concurrency: o.concurrency, mode: o.mode, billingCap: o.billingCap, verifyArgv: o.verifyArgv, verifySeconds: o.verifySeconds, attemptSeconds: o.attemptSeconds, reserveTokens: o.reserveTokens, budgetAttempts: o.budgetAttempts, budgetTokens: o.budgetTokens, spawnGrant: o.spawnGrant, harness: o.harness, need: o.need, maxSeconds: o.maxSeconds, dispatch: o.dispatch, status: o.attemptStatus, summary: o.summary, blocker: o.blocker, tokens: o.tokens, tokensBasis: o.tokensBasis, promptFile: o.promptFile, requestId: o.requestId, task: o.task, ack: o.ack, fallback: o.fallback, ladder: o.ladder, json: o.json, env: process.env, cwd: evidenceRoot(o), resolveSlug: (cwd ) => featureSlugFor({ projectRoot: cwd }) });
|
|
410
|
+
// Code scope keeps two roots: the search root is --root or cwd (the invoking checkout), the state root is
|
|
411
|
+
// the feature store above. Guidance gets no stateRoot, exactly as before 079, so it resolves from cwd.
|
|
412
|
+
case 'retrieve': return handleRetrieveCommand({ query: o.query, top: o.top, json: o.json, scope: o.scope,
|
|
413
|
+
profile: o.profile, root: o.root, indexAction: o.indexAction, modelPath: o.modelPath,
|
|
414
|
+
taskId: o.taskId, need: o.need, slug: storeSlug, stateRoot: o.scope === 'code' ? storeRoot : undefined, repoRoot: REPO_ROOT });
|
|
272
415
|
case 'brief-tools': return handleBriefToolsCommand({ owner: o.owner, tier: o.tier, harness: o.harness, slug: o.slug, headingLevel: o.headingLevel, tasks: o.tasks, json: o.json, repoRoot: REPO_ROOT, projectRoot: storeRoot, buildAdapters: buildAdapterRegistry });
|
|
273
416
|
case 'advise': return handleAdviseCommand({ action: o.action, actionGiven: o.actionGiven, kind: o.kind, server: o.server, state: o.state, stateFile: o.stateFile, staticAnswer: o.staticAnswer, questionsFile: o.questionsFile, taskId: o.taskId, pickId: o.pickId, actual: o.actual, model: o.model, endpoint: o.endpoint, off: o.off, project: o.project, force: o.force, global: o.global, json: o.json, projectRoot: evidenceRoot(o) });
|
|
274
|
-
case 'model-role': return handleModelRoleCommand({ role: o.role, exclude: o.exclude, json: o.json, repoRoot: REPO_ROOT });
|
|
417
|
+
case 'model-role': return handleModelRoleCommand({ role: o.role, exclude: o.exclude, excludeFamilies: o.excludeFamily, json: o.json, repoRoot: REPO_ROOT });
|
|
275
418
|
case 'route': return handleRouteCommand({ intent: o.intent, query: o.query, check: o.check, json: o.json, projectRoot: evidenceRoot(o) });
|
|
276
419
|
case 'claim': return handleClaimCommand({ slug: storeSlug, taskId: requireTaskId(o), action: o.action, statement: o.statement, claimId: o.claimId, evidenceId: o.evidenceId, replacedBy: o.replacedBy, relation: o.relation, role: o.role, json: o.json, stateRoot: storeRoot });
|
|
277
|
-
case 'context-pack': return handleContextPackCommand({ taskId: requireTaskId(o), taskClass: o.taskClass, objective: o.objective, json: o.json, stateRoot: evidenceRoot(o), slug: o.slug, mandatoryFile: o.mandatoryFile, harness: o.harness, maxBytes: o.maxBytes, bare: o.bare, noRecord: o.noRecord, reason: o.reason, since: o.since, expand: o.expand });
|
|
420
|
+
case 'context-pack': return handleContextPackCommand({ taskId: requireTaskId(o), taskClass: o.taskClass, objective: o.objective, json: o.json, stateRoot: storeRoot, sourceRoot: evidenceRoot(o), slug: storeSlug, explicitSlug: o.slug || null, mandatoryFile: o.mandatoryFile, harness: o.harness, maxBytes: o.maxBytes, bare: o.bare, noRecord: o.noRecord, reason: o.reason, since: o.since, expand: o.expand });
|
|
421
|
+
// 078 IC-005 and IC-013: identity is the process environment's alone, never a flag.
|
|
422
|
+
case 'context-emit': return handleContextEmitCommand({ event: o.event, cwd: o.cwd, session: o.session, harness: o.harness, nudge: o.nudge, maxBytes: o.maxBytes, taskId: o.taskId || undefined, slug: o.slug || undefined, stateRoot: redirected ? storeRoot : undefined, peek: o.peek, json: o.json });
|
|
423
|
+
case 'context-grant': return handleContextGrantCommand({ summary: o.summary, toRun: o.toRun, toLineage: o.toLineage, fromWorktree: o.fromWorktree, fromRun: o.fromRun, fromLineage: o.fromLineage, maxBytes: o.maxBytes, json: o.json });
|
|
278
424
|
case 'retrieval-plan': return handleRetrievalPlanCommand({ slug: storeSlug, taskId: requireTaskId(o), action: o.action, need: o.need, stage: o.stage, provider: o.provider, attemptStatus: o.attemptStatus, reason: o.reason, note: o.note, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, sourceRoot: evidenceRoot(o) });
|
|
279
|
-
case 'outcome': return handleOutcomeCommand({ slug:
|
|
425
|
+
case 'outcome': return handleOutcomeCommand({ slug: storeSlug, taskId: requireTaskId(o), action: o.action, state: o.state, taskClass: o.taskClass, stage: o.stage, readiness: o.readiness, verification: o.verification, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot });
|
|
280
426
|
case 'verify': return handleVerifyCommand({ slug: o.slug, taskId: requireTaskId(o), action: o.action, risk: o.risk, planPath: o.planPath, scope: o.scope, verificationInput: o.verificationInput, verificationPhase: o.verificationPhase, baselineRef: o.baselineRef, json: o.json, projectRoot: evidenceRoot(o) });
|
|
281
427
|
case 'leak-scan': return handleLeakScanCommand({ paths: o.paths, exclude: o.exclude, json: o.json, repoRoot: evidenceRoot(o) });
|
|
282
428
|
case 'recover': return handleRecoverCommand({ errorMessage: o.errorMessage, failedChecks: o.failedChecks, iteration: o.iteration, agent: o.agent, json: o.json });
|
|
429
|
+
case 'roadmap': return handleRoadmapVerbCommand(o);
|
|
430
|
+
case 'plan-check': return handlePlanCheckCommand({ positional: o.positional, extraFlags: o.extraFlags, json: o.json, cwd: process.cwd() });
|
|
431
|
+
// One --path only: a second occurrence reaches the handler as a list, which it refuses as usage.
|
|
432
|
+
case 'review': return handleReviewCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, path: o.paths?.length === 1 ? o.paths[0] : o.paths, base: o.base, preset: o.preset, json: o.json, cwd: process.cwd(), env: process.env });
|
|
433
|
+
case 'protocol': return handleProtocolCommand({ action: o.actionGiven ? o.action : undefined, kind: o.kind, taskClass: o.taskClass, risk: o.risk, preset: o.preset, positional: o.positional, json: o.json, cwd: process.cwd() });
|
|
434
|
+
case 'rules': return handleRulesCommand({ taskClass: o.taskClass, json: o.json, global: o.global, positional: o.positional, env: process.env, cwd: process.cwd() });
|
|
435
|
+
case 'primary': return handlePrimaryCommand({ action: o.actionGiven ? o.action : undefined, json: o.json, flags: o.flagsGiven, env: process.env, cwd: process.cwd() });
|
|
436
|
+
case 'package': return handlePackageCommand({ action: o.actionGiven ? o.action : undefined, path: o.paths?.length === 1 ? o.paths[0] : o.paths, id: o.id, source: o.source, index: o.index, packageVersion: o.packageVersion, plan: o.planId, repair: o.repair, points: o.points, dir: o.dir, json: o.json });
|
|
437
|
+
case 'slot': return handleSlotCommand({ action: o.actionGiven ? o.action : undefined, name: o.name, label: o.label, timeout: o.timeout, noWait: Boolean(o.noWait), command: o.slotCommand, by: o.by, reason: o.reason, positional: o.positional, extraFlags: o.extraFlags, json: o.json, env: process.env, cwd: process.cwd() });
|
|
438
|
+
case 'fleet': return handleFleetCommand({ action: o.actionGiven ? o.action : undefined, json: o.json, flags: o.flagsGiven, env: process.env, cwd: process.cwd() });
|
|
439
|
+
case 'transcript': return handleTranscriptCommand({ action: o.actionGiven ? o.action : undefined, agent: o.agent, cursor: o.cursor, limit: o.limit, window: o.window, json: o.json, flags: o.flagsGiven, env: process.env, cwd: process.cwd() });
|
|
440
|
+
case 'models': return handleModelsCommand({ action: o.actionGiven ? o.action : (o.positional?.[0] || 'list'), positional: o.positional, harness: o.harness, model: o.model, json: o.json, projectRoot: evidenceRoot(o) });
|
|
441
|
+
case 'worktree': return handleWorktreeCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, json: o.json, flags: o.flagsGiven, env: process.env, cwd: process.cwd() });
|
|
442
|
+
case 'attendance': return handleAttendanceCommand({ taskId: o.taskId, run: o.run, json: o.json, flags: o.flagsGiven, env: process.env, cwd: process.cwd() });
|
|
283
443
|
default: console.error(`doflow: unknown command '${o.cmd}'`); process.exit(1);
|
|
284
444
|
}
|
|
285
445
|
}
|
|
@@ -288,7 +448,7 @@ function dispatchRuntimeCommandInner(o , moment ) {
|
|
|
288
448
|
async function dispatchRuntimeCommand(o ) {
|
|
289
449
|
const moment = {};
|
|
290
450
|
const result = await dispatchRuntimeCommandInner(o, moment);
|
|
291
|
-
if (o
|
|
451
|
+
if (runsUpkeep(o)) upkeepAfterVerb({ projectRoot: moment.projectRoot });
|
|
292
452
|
return result;
|
|
293
453
|
}
|
|
294
454
|
|
package/src/cli/shared.js
CHANGED
|
@@ -20,7 +20,6 @@ const { createAdapterRegistry } = require('../adapters/index.js');
|
|
|
20
20
|
const { declaredHarnessPaths } = require('../helper/harness-paths.js');
|
|
21
21
|
const claudeAdapter = require('../adapters/claude/index.js');
|
|
22
22
|
const codexAdapter = require('../adapters/codex/index.js');
|
|
23
|
-
const { createGeminiAdapter } = require('../adapters/gemini/index.js');
|
|
24
23
|
const { createOpenCodeAdapter } = require('../adapters/opencode/index.js');
|
|
25
24
|
const { createPiAdapter } = require('../adapters/pi/index.js');
|
|
26
25
|
const { createCopilotAdapter } = require('../adapters/copilot/index.js');
|
|
@@ -55,7 +54,6 @@ function buildAdapterRegistry() {
|
|
|
55
54
|
return createAdapterRegistry({
|
|
56
55
|
claude: claudeAdapter.createClaudeAdapter({ declaredPaths: declared.claude }),
|
|
57
56
|
codex: codexAdapter.createCodexAdapter({ declaredPaths: declared.codex }),
|
|
58
|
-
gemini: createGeminiAdapter({ declaredPaths: declared.gemini }),
|
|
59
57
|
opencode: createOpenCodeAdapter({ declaredPaths: declared.opencode }),
|
|
60
58
|
pi: createPiAdapter({ declaredPaths: declared.pi }),
|
|
61
59
|
copilot: createCopilotAdapter({ declaredPaths: declared.copilot }),
|
package/src/helper/git.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
//
|
|
6
6
|
// First module of the TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md). Authored as `.ts` and
|
|
7
7
|
// run directly by Node's native type-stripping (process.features.typescript === 'strip', Node
|
|
8
|
-
//
|
|
8
|
+
// >=24.22.1), so no build step and no runtime dependency are added. The body stays CommonJS
|
|
9
9
|
// (`module.exports`) so a `require('../helper/git.js')` from a `.js` caller keeps working while the
|
|
10
10
|
// rest of the tree is still `.js`; the explicit `.ts` extension on those requires is what the
|
|
11
11
|
// CommonJS resolver needs to find this file.
|
package/src/helper/guardrails.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// the inner command glob is what every other harness wants.
|
|
11
11
|
//
|
|
12
12
|
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): authored as `.ts`, run directly by Node
|
|
13
|
-
// native type-stripping (process.features.typescript === 'strip', Node
|
|
13
|
+
// native type-stripping (process.features.typescript === 'strip', Node >=24.22.1) — no build step and
|
|
14
14
|
// no runtime dependency. The body stays CommonJS so a `.js` caller's `require('../helper/guardrails.js')`
|
|
15
15
|
// keeps working while the rest of the tree is still `.js`; the explicit `.ts` extension is what the
|
|
16
16
|
// CommonJS resolver needs to find this file.
|
|
@@ -16,9 +16,12 @@ const MARKER_END = '<!-- doflow:end -->';
|
|
|
16
16
|
/**
|
|
17
17
|
* Merge `srcAbs`'s content into `dstAbs` inside a doflow-owned marker span,
|
|
18
18
|
* preserving any of `dstAbs`'s own content outside that span byte-for-byte.
|
|
19
|
+
* With `content`, that text is merged instead of the file `srcAbs` names.
|
|
19
20
|
*/
|
|
20
|
-
function mergeMarkedSection(srcAbs , dstAbs , { dryRun = false }
|
|
21
|
-
|
|
21
|
+
function mergeMarkedSection(srcAbs , dstAbs , { dryRun = false, content } = {}) {
|
|
22
|
+
// `content` is already-rendered text (a pointer with its per-scope path filled in); it replaces
|
|
23
|
+
// reading `srcAbs`, so a caller never has to stage a temporary source file.
|
|
24
|
+
const srcContent = (content !== undefined ? content : fs.readFileSync(srcAbs, 'utf8')).replace(/\s+$/, '');
|
|
22
25
|
const section = `${MARKER_START}\n${srcContent}\n${MARKER_END}\n`;
|
|
23
26
|
|
|
24
27
|
// Read once, reused both for parsing and for the final no-op comparison below.
|
|
@@ -81,28 +84,43 @@ function mergeMarkedSection(srcAbs , dstAbs , { dryRun = false }
|
|
|
81
84
|
return { changed: true };
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Where `text`'s doflow span is: the first of `startMarkers`, the first MARKER_END after it, and no
|
|
89
|
+
* start marker after that end (a second span is `malformed`). `after` is past the end marker and the
|
|
90
|
+
* one '\n' that follows it.
|
|
91
|
+
*/
|
|
92
|
+
function markedSpan(text , startMarkers = [MARKER_START]) {
|
|
93
|
+
const found = startMarkers.map((marker) => ({ at: text.indexOf(marker), length: marker.length })).filter((item) => item.at !== -1);
|
|
94
|
+
if (!found.length) return { state: 'none' };
|
|
95
|
+
const first = found.reduce((a, b) => (b.at < a.at ? b : a));
|
|
96
|
+
const end = text.indexOf(MARKER_END, first.at + first.length);
|
|
97
|
+
if (end === -1) return { state: 'malformed' };
|
|
98
|
+
let after = end + MARKER_END.length;
|
|
99
|
+
if (startMarkers.some((marker) => text.indexOf(marker, after) !== -1)) return { state: 'malformed' };
|
|
100
|
+
if (text[after] === '\n') after += 1;
|
|
101
|
+
return { state: 'ok', start: first.at, after };
|
|
102
|
+
}
|
|
103
|
+
|
|
84
104
|
/**
|
|
85
105
|
* Strip only the doflow-managed span from `file`, leaving any surrounding content (before/after
|
|
86
106
|
* the markers) byte-for-byte untouched. Companion to `mergeMarkedSection` — shared by the Claude
|
|
87
107
|
* and Codex adapters' `remove()`, which had each carried an identical private copy of this.
|
|
88
108
|
* A file that held nothing but the span is DoFlow's own and is deleted; any other file is written
|
|
89
|
-
* back, even when only whitespace remains.
|
|
109
|
+
* back, even when only whitespace remains. `startMarkers` (default: MARKER_START alone) lets a
|
|
110
|
+
* caller also accept an older start marker; the retirement sweep is the only one that does.
|
|
90
111
|
* @returns whether a managed span was found and stripped (false if the file doesn't
|
|
91
112
|
* exist or has no doflow markers — both are no-ops, not errors)
|
|
92
113
|
*/
|
|
93
|
-
function removeMarkedSection(file ) {
|
|
114
|
+
function removeMarkedSection(file , { startMarkers = [MARKER_START] } = {}) {
|
|
94
115
|
if (!fs.existsSync(file)) return false;
|
|
95
116
|
const existing = fs.readFileSync(file, 'utf8');
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
if (end === -1 || existing.indexOf(MARKER_START, end + MARKER_END.length) !== -1) {
|
|
117
|
+
const span = markedSpan(existing, startMarkers);
|
|
118
|
+
if (span.state === 'none') return false;
|
|
119
|
+
if (span.state === 'malformed') {
|
|
100
120
|
throw new Error(`Refusing to remove malformed DoFlow markers in ${file}`);
|
|
101
121
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const before = existing.slice(0, start);
|
|
105
|
-
const rest = existing.slice(after);
|
|
122
|
+
const before = existing.slice(0, span.start);
|
|
123
|
+
const rest = existing.slice(span.after);
|
|
106
124
|
if (before === '' && rest === '') {
|
|
107
125
|
fs.unlinkSync(file);
|
|
108
126
|
return true;
|
|
@@ -113,4 +131,4 @@ function removeMarkedSection(file ) {
|
|
|
113
131
|
return true;
|
|
114
132
|
}
|
|
115
133
|
|
|
116
|
-
module.exports = { mergeMarkedSection, removeMarkedSection, MARKER_START, MARKER_END };
|
|
134
|
+
module.exports = { mergeMarkedSection, removeMarkedSection, markedSpan, MARKER_START, MARKER_END };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Package, local, qualified and projected identifiers (122 IC-003, PN-3). Pure and dependency-free so
|
|
4
|
+
// `src/registry/` (row 120's worker ids) and `src/runtime/` import the one definition.
|
|
5
|
+
|
|
6
|
+
const PACKAGE_ID = /^[a-z][a-z0-9-]{0,14}[a-z0-9]$/;
|
|
7
|
+
const LOCAL_ID = /^[a-z][a-z0-9-]{0,13}[a-z0-9]$/;
|
|
8
|
+
const QUALIFIED_MAX = 32;
|
|
9
|
+
// Refused as a package id (reserved-id); `doflow` is usable only by the bundled first-party package.
|
|
10
|
+
const RESERVED = ['doflow', 'do', 'core', 'user', 'project', 'local', 'env', 'auto', 'package', 'packages'];
|
|
11
|
+
|
|
12
|
+
const isPackageId = (value ) => typeof value === 'string' && PACKAGE_ID.test(value) && !value.includes('--');
|
|
13
|
+
const isLocalId = (value ) => typeof value === 'string' && LOCAL_ID.test(value) && !value.includes('--');
|
|
14
|
+
|
|
15
|
+
/** True for a package id the grammar accepts but IC-003 reserves: the listed names and any `do-` or `doflow-` prefix. */
|
|
16
|
+
function isReservedPackageId(value ) {
|
|
17
|
+
return typeof value === 'string' && (RESERVED.includes(value) || value.startsWith('do-') || value.startsWith('doflow-'));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isQualifiedId(value ) {
|
|
21
|
+
if (typeof value !== 'string' || value.length > QUALIFIED_MAX) return false;
|
|
22
|
+
const parts = value.split('.');
|
|
23
|
+
return parts.length === 2 && isPackageId(parts[0]) && isLocalId(parts[1]);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** `<package id>.<local id>`, or null when either part breaks its grammar. */
|
|
27
|
+
function qualifiedId(packageId , localId ) {
|
|
28
|
+
const joined = `${packageId}.${localId}`;
|
|
29
|
+
return isPackageId(packageId) && isLocalId(localId) && joined.length <= QUALIFIED_MAX ? joined : null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The harness-file name of a qualified id, `<package id>-<local id>`; null when the input is not a qualified id. */
|
|
33
|
+
function projectedName(qualified ) {
|
|
34
|
+
return isQualifiedId(qualified) ? qualified.replace('.', '-') : null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = { isPackageId, isLocalId, isQualifiedId, isReservedPackageId, qualifiedId, projectedName };
|