@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,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The roadmap autopilot kill switch (feature 108 IC-011, FR-016; decisions C9, C4, C20). It lives
|
|
5
|
+
* with the settings it reads, so the orchestrator and the roadmap loop share one reader without the
|
|
6
|
+
* orchestrator importing the loop.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('node:fs');
|
|
10
|
+
const path = require('node:path');
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/** `<config home>/autopilot/off`, or null with no config home (which already reads as off). */
|
|
15
|
+
function sentinelFile(env ) {
|
|
16
|
+
const { configHome } = require('../config-home.js');
|
|
17
|
+
const home = configHome(env).dir;
|
|
18
|
+
return home ? path.join(home, 'autopilot', 'off') : null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Read fresh on every call (never memoised: a copied env defeats the resolver cache), so a switch
|
|
23
|
+
* set between two boundaries stops the next one. Any layer saying off wins and is named, in the
|
|
24
|
+
* order env (DOFLOW_AUTOPILOT_ENABLED), the `autopilot/off` sentinel, the settings file. The
|
|
25
|
+
* sentinel is stat'ed here: any error but ENOENT (EACCES, ENOTDIR) reads as present, because the
|
|
26
|
+
* resolver reads every stat error as absent. Absent, invalid or unreadable settings read as off.
|
|
27
|
+
*/
|
|
28
|
+
function readKillSwitch(env = process.env, fsImpl = fs) {
|
|
29
|
+
const off = (layer ) => ({ enabled: false, switch: layer });
|
|
30
|
+
try {
|
|
31
|
+
const { loadSettings } = require('./resolve.js');
|
|
32
|
+
const resolution = loadSettings({ global: true, env: { ...env } }).get('autopilot.enabled', 'global');
|
|
33
|
+
if (resolution.candidates.some((c ) => c.layer === 'env' && c.value === 'off')) return off('env');
|
|
34
|
+
const file = sentinelFile(env);
|
|
35
|
+
if (file) {
|
|
36
|
+
try { fsImpl.statSync(file); return off('sentinel'); }
|
|
37
|
+
catch (error ) { if (error?.code !== 'ENOENT') return off('sentinel'); }
|
|
38
|
+
}
|
|
39
|
+
if (resolution.candidates.some((c ) => c.legacy && c.value === 'off')) return off('sentinel');
|
|
40
|
+
return resolution.value === 'on' ? { enabled: true, switch: null } : off('setting');
|
|
41
|
+
} catch {
|
|
42
|
+
return off('setting');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Seed writes require an independently verified durable off, so uncertainty refuses the write. */
|
|
47
|
+
function readSeedSwitch(env = process.env, fsImpl = fs) {
|
|
48
|
+
const refuse = () => ({ enabled: true, switch: null });
|
|
49
|
+
const off = (layer ) => ({ enabled: false, switch: layer });
|
|
50
|
+
try {
|
|
51
|
+
const { configHome } = require('../config-home.js');
|
|
52
|
+
const home = configHome(env).dir;
|
|
53
|
+
if (!home) return refuse();
|
|
54
|
+
|
|
55
|
+
const settingsEnv = { ...env };
|
|
56
|
+
delete settingsEnv.DOFLOW_AUTOPILOT_ENABLED;
|
|
57
|
+
const { loadSettings } = require('./resolve.js');
|
|
58
|
+
const settings = loadSettings({ global: true, env: settingsEnv, fsImpl });
|
|
59
|
+
const resolution = settings.get('autopilot.enabled', 'global');
|
|
60
|
+
if (resolution.state === 'invalid' || resolution.candidates.some((candidate ) => candidate.status === 'invalid')) {
|
|
61
|
+
return refuse();
|
|
62
|
+
}
|
|
63
|
+
if (settings.errors.some((entry ) => entry.key === 'autopilot.enabled' || entry.key === null)) {
|
|
64
|
+
return refuse();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const file = path.join(home, 'autopilot', 'off');
|
|
68
|
+
try {
|
|
69
|
+
fsImpl.statSync(file);
|
|
70
|
+
return off('sentinel');
|
|
71
|
+
} catch (error ) {
|
|
72
|
+
if (error?.code !== 'ENOENT') return off('sentinel');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const legacyOff = resolution.candidates.some((candidate ) => candidate.legacy && candidate.value === 'off');
|
|
76
|
+
if (resolution.value === 'off' || legacyOff) return off('setting');
|
|
77
|
+
return refuse();
|
|
78
|
+
} catch {
|
|
79
|
+
return refuse();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* maint-thin: whether a review is unattended, so the class seat floor binds. Fail closed: only a verifiably off
|
|
85
|
+
* switch (the seed reader: a resolved config home whose setting or sentinel says off) reads as attended. An uncertain
|
|
86
|
+
* switch, unreadable settings or no config home count as unattended. The one other attended case is an explicit,
|
|
87
|
+
* process-local `DOFLOW_AUTOPILOT_ENABLED=off`: a caller can always lower its own run that way, and that costs nothing,
|
|
88
|
+
* because roadmap gate-b judges the recorded seats against the class floor itself and denies too few.
|
|
89
|
+
*/
|
|
90
|
+
function reviewUnattended(env = process.env, fsImpl = fs) {
|
|
91
|
+
if (env?.DOFLOW_AUTOPILOT_ENABLED === 'off') return false;
|
|
92
|
+
return readSeedSwitch(env, fsImpl).enabled !== false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Tripwire (narrowing only): writes the kill-switch sentinel; only a person removes it. */
|
|
96
|
+
function tripSentinel(env , line , fsImpl = fs) {
|
|
97
|
+
const file = sentinelFile(env);
|
|
98
|
+
// No config home already reads as off (needsConfigHome), so there is nothing to narrow.
|
|
99
|
+
if (!file) return false;
|
|
100
|
+
fsImpl.mkdirSync(path.dirname(file), { recursive: true });
|
|
101
|
+
try { fsImpl.writeFileSync(file, `${line}\n`, { flag: 'wx', mode: 0o600 }); }
|
|
102
|
+
catch (error ) { if (error.code !== 'EEXIST') throw error; }
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { readKillSwitch, readSeedSwitch, reviewUnattended, tripSentinel };
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
|
|
4
|
+
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
const fs = require('node:fs');
|
|
7
|
+
const { configHome } = require('../config-home.js');
|
|
8
|
+
const { finishRuntime, usageError } = require('../cli-result.js');
|
|
9
|
+
const { REPO_ROOT } = require('../../helper/repo-root.js');
|
|
10
|
+
const { loadSettingsRegistry, REGISTRY_FILE } = require('./registry.js');
|
|
11
|
+
const { loadSettings } = require('./resolve.js');
|
|
12
|
+
const { maskUrl } = require('./shared.js');
|
|
13
|
+
|
|
14
|
+
function safeValue(value , meta ) {
|
|
15
|
+
return meta?.type === 'url' && typeof value === 'string' ? maskUrl(value) : value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function safeResolution(resolution ) {
|
|
19
|
+
const meta = resolution?.meta || {};
|
|
20
|
+
return {
|
|
21
|
+
...resolution,
|
|
22
|
+
value: safeValue(resolution.value, meta),
|
|
23
|
+
origin: resolution.origin ? { ...resolution.origin } : resolution.origin,
|
|
24
|
+
candidates: (resolution.candidates || []).map((candidate ) => ({
|
|
25
|
+
...candidate,
|
|
26
|
+
value: safeValue(candidate.value, meta),
|
|
27
|
+
display: meta.type === 'url' && typeof candidate.display === 'string'
|
|
28
|
+
? maskUrl(candidate.display) : candidate.display,
|
|
29
|
+
})),
|
|
30
|
+
meta: { ...meta, default: safeValue(meta.default, meta) },
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function safeReport(report ) {
|
|
35
|
+
const keys = {};
|
|
36
|
+
for (const [key, value] of Object.entries(report.keys || {})) {
|
|
37
|
+
if (value && typeof value === 'object' && !('key' in value)
|
|
38
|
+
&& 'project' in value && 'global' in value) {
|
|
39
|
+
keys[key] = { project: safeResolution((value ).project), global: safeResolution((value ).global) };
|
|
40
|
+
} else {
|
|
41
|
+
keys[key] = safeResolution(value);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { ...report, keys };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The settings-only part of doctor output; values are omitted, while present files and faults remain. */
|
|
48
|
+
function settingsReport(view ) {
|
|
49
|
+
const report = view.report();
|
|
50
|
+
return {
|
|
51
|
+
schema: 1,
|
|
52
|
+
scope: report.scope,
|
|
53
|
+
configHome: report.configHome,
|
|
54
|
+
project: report.project,
|
|
55
|
+
files: report.files,
|
|
56
|
+
errors: report.errors,
|
|
57
|
+
notes: report.notes,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function buildSettingsReport({ repoRoot = REPO_ROOT, projectRoot = process.cwd(), global = false,
|
|
62
|
+
env = process.env, fsImpl = fs } = {}) {
|
|
63
|
+
const loaded = loadSettingsRegistry({ repoRoot, fsImpl });
|
|
64
|
+
if (!loaded.ok) {
|
|
65
|
+
const home = configHome(env);
|
|
66
|
+
return {
|
|
67
|
+
schema: 1,
|
|
68
|
+
scope: global ? 'global' : 'project',
|
|
69
|
+
configHome: { dir: home.dir, ignored: [...home.ignored] },
|
|
70
|
+
project: { root: global ? null : path.resolve(projectRoot), layersFrom: null, checkout: null },
|
|
71
|
+
files: [],
|
|
72
|
+
errors: [{ key: null, layer: 'default', source: path.join(repoRoot, REGISTRY_FILE), legacy: false,
|
|
73
|
+
code: 'settings-registry-invalid', reason: loaded.detail, offset: null }],
|
|
74
|
+
notes: [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const view = loadSettings({ projectRoot, global, env, fsImpl, registry: loaded.registry });
|
|
79
|
+
return settingsReport(view);
|
|
80
|
+
} catch (error ) {
|
|
81
|
+
const home = configHome(env);
|
|
82
|
+
return {
|
|
83
|
+
schema: 1,
|
|
84
|
+
scope: global ? 'global' : 'project',
|
|
85
|
+
configHome: { dir: home.dir, ignored: [...home.ignored] },
|
|
86
|
+
project: { root: global ? null : path.resolve(projectRoot), layersFrom: null, checkout: null },
|
|
87
|
+
files: [],
|
|
88
|
+
errors: [{ key: null, layer: 'default', source: path.join(repoRoot, REGISTRY_FILE), legacy: false,
|
|
89
|
+
code: 'settings-unavailable', reason: error?.message || String(error), offset: null }],
|
|
90
|
+
notes: [],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function settingValue(value , meta ) {
|
|
96
|
+
const safe = safeValue(value, meta);
|
|
97
|
+
if (safe === null || safe === undefined) return '(none)';
|
|
98
|
+
if (typeof safe === 'string') return JSON.stringify(safe);
|
|
99
|
+
return JSON.stringify(safe);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function originLabel(resolution ) {
|
|
103
|
+
const { origin } = resolution;
|
|
104
|
+
const source = origin.source || (origin.via === 'no-config-home' ? 'no config home' : REGISTRY_FILE);
|
|
105
|
+
return `${origin.layer}: ${source}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function printResolution(key , resolution , showOrigin , suffix = '') {
|
|
109
|
+
if (resolution.meta?.needsConfigHome && resolution.origin?.via === 'no-config-home') {
|
|
110
|
+
console.log(`${key}${suffix} = ${settingValue(resolution.value, resolution.meta)} (no config home: capture skipped)`);
|
|
111
|
+
} else {
|
|
112
|
+
const origin = showOrigin ? ` (${originLabel(resolution)})` : '';
|
|
113
|
+
console.log(`${key}${suffix} = ${settingValue(resolution.value, resolution.meta)}${origin}`);
|
|
114
|
+
}
|
|
115
|
+
if (!showOrigin) return;
|
|
116
|
+
for (const candidate of resolution.candidates || []) {
|
|
117
|
+
const display = typeof candidate.display === 'string' && candidate.display !== '' ? candidate.display : '(none)';
|
|
118
|
+
const reason = candidate.reason ? `: ${candidate.reason}` : '';
|
|
119
|
+
console.log(` ${candidate.layer} ${candidate.source}: ${display} — ${candidate.status}${reason}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function printSettingsList(report , showOrigin ) {
|
|
124
|
+
const home = report.configHome;
|
|
125
|
+
const ignored = home.ignored || [];
|
|
126
|
+
const homeLabel = home.dir
|
|
127
|
+
? `${home.dir}${ignored.length ? ` | ${ignored.join(', ')} ignored` : ''}`
|
|
128
|
+
: `none${ignored.length ? ` (${ignored.join(', ')} ignored)` : ''}`;
|
|
129
|
+
console.log(`config home: ${homeLabel}`);
|
|
130
|
+
for (const name of ignored) console.log(`note: ignored relative ${name}`);
|
|
131
|
+
const project = report.project;
|
|
132
|
+
console.log(`project: ${project.root || '(none)'}${project.checkout ? ` (${project.checkout})` : ''}`);
|
|
133
|
+
|
|
134
|
+
for (const [key, value] of Object.entries(report.keys || {})) {
|
|
135
|
+
const dualView = value && typeof value === 'object' && !('key' in (value ))
|
|
136
|
+
&& 'project' in (value ) && 'global' in (value )
|
|
137
|
+
&& Array.isArray((value ).project?.meta?.views) && (value ).project.meta.views.includes('global');
|
|
138
|
+
if (dualView) {
|
|
139
|
+
printResolution(key, (value ).project, showOrigin, ' [project roots]');
|
|
140
|
+
printResolution(key, (value ).global, showOrigin, ' [user roots]');
|
|
141
|
+
} else {
|
|
142
|
+
const views = (value )?.meta?.views;
|
|
143
|
+
const suffix = Array.isArray(views) && views.includes('global')
|
|
144
|
+
? ((value ).view === 'global' ? ' [user roots]' : ' [project roots]')
|
|
145
|
+
: '';
|
|
146
|
+
printResolution(key, value, showOrigin, suffix);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const error of report.errors || []) {
|
|
150
|
+
console.log(`error: ${error.key || 'settings'} (${error.layer}: ${error.source}): ${error.reason}`);
|
|
151
|
+
}
|
|
152
|
+
for (const note of report.notes || []) console.log(`note: ${note.text}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function securityFault(report ) {
|
|
156
|
+
const check = (resolution ) => {
|
|
157
|
+
if (resolution && resolution.meta?.securityRelevant
|
|
158
|
+
&& ['fail-safe', 'cross-key'].includes(resolution.origin?.via)) return true;
|
|
159
|
+
if (resolution && typeof resolution === 'object' && 'project' in resolution && 'global' in resolution) {
|
|
160
|
+
return check(resolution.project) || check(resolution.global);
|
|
161
|
+
}
|
|
162
|
+
return false;
|
|
163
|
+
};
|
|
164
|
+
return Object.values(report.keys || {}).some(check);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const CONFIG_ACTIONS = ['list', 'schema', 'validate', 'set', 'unset'];
|
|
168
|
+
const CONFIG_LAYERS = ['user', 'project', 'local'];
|
|
169
|
+
/** Positional words after the action: the key and, for validate and set, a JSON value. */
|
|
170
|
+
const CONFIG_OPERANDS = { schema: 0, validate: 2, set: 2, unset: 1 };
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
/** Splits `config [list] [path] | schema | validate <key> <value> | set <key> <value> | unset <key>` and its flags. */
|
|
175
|
+
function configArguments(positional , { layer, global, showOrigin, preparedRun } ) {
|
|
176
|
+
const args = Array.isArray(positional) ? [...positional] : [];
|
|
177
|
+
const fail = (error ) => ({ action: 'list', project: null, key: null, valueText: null, error });
|
|
178
|
+
let action = 'list';
|
|
179
|
+
if (CONFIG_ACTIONS.includes(args[0])) action = args.shift();
|
|
180
|
+
else if (args.length === 1 && !args[0].includes(path.sep) && !fs.existsSync(args[0])) {
|
|
181
|
+
return fail(`unknown action '${args[0]}'; expected ${CONFIG_ACTIONS.join(', ')}`);
|
|
182
|
+
}
|
|
183
|
+
if (layer !== undefined && !CONFIG_LAYERS.includes(layer)) return fail(`--layer must be one of ${CONFIG_LAYERS.join(', ')}`);
|
|
184
|
+
if (action === 'list') {
|
|
185
|
+
if (args.length > 1) return fail('expected config [list] [project path]');
|
|
186
|
+
if (layer !== undefined) return fail('--layer is only for validate, set and unset');
|
|
187
|
+
if (preparedRun !== undefined) return fail('--prepared-run is only for config validate');
|
|
188
|
+
return { action, project: args[0] || null, key: null, valueText: null, error: null };
|
|
189
|
+
}
|
|
190
|
+
if (showOrigin) return fail('--show-origin is only for config list');
|
|
191
|
+
if (global) return fail(`-g is not for config ${action}`);
|
|
192
|
+
if (action === 'schema' && layer !== undefined) return fail('--layer is only for validate, set and unset');
|
|
193
|
+
if (preparedRun !== undefined) {
|
|
194
|
+
if (action !== 'validate') return fail('--prepared-run is only for config validate');
|
|
195
|
+
if (args.length) return fail('config validate --prepared-run <file> takes no key or value');
|
|
196
|
+
if (layer !== undefined) return fail('--layer is not for config validate --prepared-run (its settings are judged at the project layer)');
|
|
197
|
+
return { action, project: null, key: null, valueText: null, error: null };
|
|
198
|
+
}
|
|
199
|
+
const want = CONFIG_OPERANDS[action];
|
|
200
|
+
if (args.length !== want) {
|
|
201
|
+
const usage = { schema: 'config schema', validate: 'config validate <key> <json-value> [--layer user|project|local] | config validate --prepared-run <file>',
|
|
202
|
+
set: 'config set <key> <json-value> --layer user|project|local', unset: 'config unset <key> --layer user|project|local' }[action];
|
|
203
|
+
return fail(`expected ${usage}`);
|
|
204
|
+
}
|
|
205
|
+
if ((action === 'set' || action === 'unset') && layer === undefined) return fail(`config ${action} needs --layer user|project|local`);
|
|
206
|
+
return { action, project: null, key: args[0] ?? null, valueText: args[1] ?? null, error: null };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function handleConfigCommand({ json = false, global = false, showOrigin = false, positional = [], layer, preparedRun,
|
|
210
|
+
projectRoot, repoRoot = REPO_ROOT, env = process.env, fsImpl = fs } = {}) {
|
|
211
|
+
const args = configArguments(positional, { layer, global, showOrigin, preparedRun });
|
|
212
|
+
if (args.error) return usageError('config', args.error, json);
|
|
213
|
+
const loaded = loadSettingsRegistry({ repoRoot, fsImpl });
|
|
214
|
+
if (!loaded.ok) {
|
|
215
|
+
const detail = loaded.detail || 'settings registry is invalid';
|
|
216
|
+
if (json) console.log(JSON.stringify({ ok: false, status: 'ERROR', exitCode: 2,
|
|
217
|
+
error: 'settings-registry-invalid', detail }, null, 2));
|
|
218
|
+
else console.error(`doflow config: settings registry unavailable: ${detail}`);
|
|
219
|
+
return finishRuntime(2);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (preparedRun !== undefined) {
|
|
223
|
+
return require('./prepared-run.js').handlePreparedRun({
|
|
224
|
+
file: preparedRun, json, registry: loaded.registry, repoRoot, projectRoot: projectRoot || process.cwd(), env, fsImpl,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (args.action !== 'list') {
|
|
229
|
+
// loaded on demand: the writer and the protocol registry stay off the read-only list path
|
|
230
|
+
return require('./config-write.js').handleConfigAction({
|
|
231
|
+
action: args.action, key: args.key, valueText: args.valueText, layer, json, registry: loaded.registry,
|
|
232
|
+
repoRoot, projectRoot: projectRoot || process.cwd(), env, fsImpl,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
const root = global ? null : path.resolve(args.project || projectRoot || process.cwd());
|
|
238
|
+
const view = loadSettings({ projectRoot: root, global, env, fsImpl, registry: loaded.registry });
|
|
239
|
+
const report = safeReport(view.report());
|
|
240
|
+
if (json) console.log(JSON.stringify(report, null, 2));
|
|
241
|
+
else printSettingsList(report, showOrigin);
|
|
242
|
+
return finishRuntime(securityFault(report) ? 1 : 0);
|
|
243
|
+
} catch (error ) {
|
|
244
|
+
const detail = error?.message || String(error);
|
|
245
|
+
if (json) console.log(JSON.stringify({ ok: false, status: 'ERROR', exitCode: 2,
|
|
246
|
+
error: 'settings-registry-invalid', detail }, null, 2));
|
|
247
|
+
else console.error(`doflow config: settings registry unavailable: ${detail}`);
|
|
248
|
+
return finishRuntime(2);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function printSettingsReport(report ) {
|
|
253
|
+
console.log('\n[Settings]');
|
|
254
|
+
console.log(` config home: ${report.configHome.dir || 'none'}`);
|
|
255
|
+
for (const name of report.configHome.ignored || []) {
|
|
256
|
+
console.log(` ignored relative ${name} (ignored)`);
|
|
257
|
+
}
|
|
258
|
+
if (report.project.root) {
|
|
259
|
+
console.log(` project: ${report.project.root}${report.project.checkout ? ` (${report.project.checkout})` : ''}`);
|
|
260
|
+
}
|
|
261
|
+
const present = (report.files || []).filter((file ) => file.status !== 'absent');
|
|
262
|
+
if (!present.length) console.log(' files: none');
|
|
263
|
+
for (const file of present) {
|
|
264
|
+
const deprecated = file.kind === 'legacy' ? ' (deprecated)' : '';
|
|
265
|
+
console.log(` ${file.layer} ${file.path}: ${file.status}${deprecated}`);
|
|
266
|
+
}
|
|
267
|
+
for (const note of report.notes || []) console.log(` note: ${note.text}`);
|
|
268
|
+
for (const error of report.errors || []) {
|
|
269
|
+
console.log(` error: ${error.key || 'settings'} (${error.layer}: ${error.source}): ${error.reason}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
module.exports = {
|
|
274
|
+
maskUrl,
|
|
275
|
+
safeReport,
|
|
276
|
+
settingsReport,
|
|
277
|
+
buildSettingsReport,
|
|
278
|
+
printSettingsReport,
|
|
279
|
+
handleConfigCommand,
|
|
280
|
+
};
|