@khoavu882/doflow 2.0.0-beta.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/bin/doflow.js +21 -11
- package/core/.antigravity-plugin/plugin.json +1 -3
- package/core/.claude-plugin/plugin.json +1 -1
- package/core/.codex-plugin/plugin.json +1 -1
- package/core/.plugin/plugin.json +1 -1
- package/core/harnesses/claude/hooks/lib.sh +43 -24
- package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
- package/core/harnesses/claude/hooks/permission-audit.sh +3 -0
- package/core/harnesses/claude/hooks/post-compact.sh +35 -32
- package/core/harnesses/claude/hooks/post-edit-lint.sh +2 -0
- package/core/harnesses/claude/hooks/post-shell-observe.sh +48 -0
- package/core/harnesses/claude/hooks/post-tool-failure.sh +3 -0
- package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
- package/core/harnesses/claude/hooks/pre-compact.sh +23 -27
- package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
- package/core/harnesses/claude/hooks/session-end.sh +23 -10
- package/core/harnesses/claude/hooks/session-start.sh +5 -3
- package/core/harnesses/claude/hooks/skill-config-audit.sh +3 -0
- package/core/harnesses/claude/hooks/stop-check.sh +5 -3
- package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
- package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
- package/core/harnesses/claude/settings/settings.json +18 -0
- package/core/harnesses/claude/statusline/doflow-statusline.sh +1 -0
- package/core/harnesses/codex/agents/core-implementer.toml +1 -0
- package/core/harnesses/codex/agents/delivery-lead.toml +10 -0
- package/core/harnesses/codex/agents/quality-guardian.toml +1 -1
- package/core/harnesses/codex/agents/research-writer.toml +1 -1
- package/core/harnesses/codex/agents/reviewer.toml +10 -0
- package/core/harnesses/codex/agents/spec-analyst.toml +1 -1
- package/core/harnesses/codex/agents/system-architect.toml +1 -1
- package/core/harnesses/codex/hooks/lib.sh +44 -25
- package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
- package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +3 -1
- package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
- package/core/harnesses/codex/hooks/pre-compact.impl.sh +29 -26
- package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
- package/core/harnesses/codex/hooks/session-end.impl.sh +23 -10
- package/core/harnesses/codex/hooks/session-start.sh +5 -3
- package/core/harnesses/codex/hooks/stop-check.sh +6 -5
- package/core/harnesses/codex/hooks/subagent-audit.sh +18 -6
- package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
- package/core/harnesses/copilot/hooks/doflow-lib.sh +93 -0
- package/core/harnesses/copilot/hooks/doflow-mcp-tool-guard.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-pre-bash-guard.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-pre-implement-gate.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-session-start.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-stop-check.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-subagent-start.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow-subagent-stop.sh +9 -0
- package/core/harnesses/copilot/hooks/doflow.json +57 -0
- package/core/harnesses/kiro/agents/doflow.json +1 -1
- package/core/harnesses/kiro/hooks/lib.sh +26 -6
- package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +21 -5
- package/core/harnesses/kiro/hooks/pre-bash-guard.sh +21 -5
- package/core/harnesses/kiro/hooks/pre-implement-gate.sh +21 -5
- package/core/harnesses/kiro/hooks/session-start.sh +12 -5
- package/core/harnesses/kiro/hooks/stop-check.sh +22 -30
- package/core/harnesses/pi/extensions/doflow-guard.js +167 -0
- package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -12
- package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
- package/core/harnesses/shared/hooks/bridge/bridge.sh +277 -0
- package/core/harnesses/shared/hooks/bridge/envelope.jq +129 -0
- package/core/harnesses/shared/hooks/bridge/observe-model.sh +75 -0
- package/core/harnesses/shared/hooks/bridge/respond.sh +70 -0
- package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +28 -14
- package/core/harnesses/shared/hooks/policies/capture-failure.sh +51 -16
- package/core/harnesses/shared/hooks/policies/compact-text.sh +46 -0
- package/core/harnesses/shared/hooks/policies/contract.sh +78 -0
- package/core/harnesses/shared/hooks/policies/deny-json.sh +35 -9
- package/core/harnesses/shared/hooks/policies/emission-rules.sh +37 -0
- package/core/harnesses/shared/hooks/policies/emission.jq +209 -0
- package/core/harnesses/shared/hooks/policies/emission.sh +383 -0
- package/core/harnesses/shared/hooks/policies/identity.sh +177 -0
- package/core/harnesses/shared/hooks/policies/lib.sh +65 -40
- package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +48 -35
- package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +284 -33
- package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +180 -110
- package/core/harnesses/shared/hooks/policies/session-context.sh +66 -7
- package/core/harnesses/shared/hooks/policies/stop-check.sh +61 -23
- package/core/harnesses/shared/hooks/policies/subagent-audit.sh +39 -6
- package/core/harnesses/shared/hooks/policies/summary-store.sh +347 -0
- package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +97 -159
- package/core/harnesses/shared/hooks/stream-hook-runner.js +114 -187
- package/core/harnesses/shared/locator/doflow-run +2 -3
- package/core/registry/advice.json +3 -3
- package/core/registry/assets.json +72 -80
- package/core/registry/capabilities.json +12 -0
- package/core/registry/contracts.json +60 -33
- package/core/registry/contribution-points.json +32 -0
- package/core/registry/gates.json +32 -0
- package/core/registry/guidance-caps.json +40 -0
- package/core/registry/harnesses.json +1542 -277
- package/core/registry/lifecycle.json +2837 -37
- package/core/registry/mcp.json +5 -1
- package/core/registry/models.json +7 -1
- package/core/registry/package-templates/README.md +19 -0
- package/core/registry/package-templates/agent/files/agent.md +9 -0
- package/core/registry/package-templates/agent/template.json +4 -0
- package/core/registry/package-templates/capability-provider/files/provider.json +9 -0
- package/core/registry/package-templates/capability-provider/template.json +11 -0
- package/core/registry/package-templates/debate-preset/files/preset.json +26 -0
- package/core/registry/package-templates/debate-preset/template.json +4 -0
- package/core/registry/package-templates/review-preset/files/preset.json +30 -0
- package/core/registry/package-templates/review-preset/template.json +4 -0
- package/core/registry/package-templates/skill/files/SKILL.md +8 -0
- package/core/registry/package-templates/skill/template.json +4 -0
- package/core/registry/package-templates/worker/files/worker.json +92 -0
- package/core/registry/package-templates/worker/template.json +11 -0
- package/core/registry/packages/doflow/doflow-package.json +15 -0
- package/core/registry/packages/doflow/presets/debate-3.json +26 -0
- package/core/registry/protocols.json +61 -0
- package/core/registry/routes.json +17 -0
- package/core/registry/rules.json +431 -0
- package/core/registry/settings.json +276 -0
- package/core/registry/storage.json +701 -30
- package/core/registry/telemetry.json +236 -0
- package/core/registry/transcripts.json +142 -0
- package/core/registry/verification.json +76 -1
- package/core/registry/workflows.json +55 -0
- package/core/shared/agent-specs/core-implementer.md +3 -0
- package/core/shared/agent-specs/delivery-lead.md +68 -0
- package/core/shared/agent-specs/quality-guardian.md +5 -1
- package/core/shared/agent-specs/research-writer.md +10 -3
- package/core/shared/agent-specs/reviewer.md +53 -0
- package/core/shared/agent-specs/spec-analyst.md +5 -6
- package/core/shared/agent-specs/system-architect.md +5 -1
- package/core/shared/guidance/DOFLOW_CORE.md +1 -5
- package/core/shared/guidance/modes/MODE_DeepResearch.md +1 -1
- package/core/shared/guidance/modes/MODE_Orchestration.md +4 -3
- package/core/shared/guidance/modes/MODE_Task_Management.md +14 -14
- package/core/shared/guidance/pointers/codex.md +1 -4
- package/core/shared/guidance/references/ARTIFACT_FORMAT.md +30 -16
- package/core/shared/guidance/references/ARTIFACT_VOICE.md +3 -2
- package/core/shared/guidance/references/CONSTITUTION_BASE.md +17 -15
- package/core/shared/guidance/references/DIAGRAM_GUIDE.md +1 -1
- package/core/shared/guidance/references/DOFLOW_CHAIN.md +17 -19
- package/core/shared/guidance/references/EVIDENCE_LEDGER.md +7 -8
- package/core/shared/guidance/references/MODEL_SELECTION.md +5 -3
- package/core/shared/guidance/references/ORCHESTRATION.md +1 -2
- package/core/shared/guidance/rules/RULES.md +45 -0
- package/core/shared/scripts/doflow/bash/do-args.sh +37 -0
- package/core/shared/scripts/doflow/bash/do-exec-paths.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-git-state.sh +15 -4
- package/core/shared/scripts/doflow/bash/do-parallel-check.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-paths.sh +40 -2
- package/core/shared/scripts/doflow/bash/do-prereqs.sh +2 -1
- package/core/shared/scripts/doflow/bash/do-review-package.sh +4 -0
- package/core/shared/scripts/doflow/bash/do-task-brief.sh +58 -16
- package/core/shared/scripts/doflow/bash/render-audit.sh +26 -2
- package/core/shared/scripts/doflow/bash/render-diagrams.sh +1 -0
- package/core/shared/scripts/doflow/bash/render-puml.sh +2 -1
- package/core/shared/scripts/doflow/bash/validate-artifacts.sh +48 -4
- package/core/shared/scripts/doflow/bin/doflow-run +154 -35
- package/core/shared/skills/do/SKILL.md +12 -10
- package/core/shared/skills/do/references/advice_calls.md +26 -0
- package/core/shared/skills/do/references/pm_routing.md +1 -2
- package/core/shared/skills/do/references/program_mode.md +31 -0
- package/core/shared/skills/do-brainstorm/SKILL.md +20 -74
- package/core/shared/skills/do-brainstorm/references/handoff_branches.md +35 -0
- package/core/shared/skills/do-brainstorm/references/intent_seed.md +21 -0
- package/core/shared/skills/do-brainstorm/references/round_log.md +17 -0
- package/core/shared/skills/do-code-review/SKILL.md +41 -144
- package/core/shared/skills/do-code-review/content-types/markdown.md +24 -2
- package/core/shared/skills/do-code-review/references/tools.md +90 -0
- package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +549 -7
- package/core/shared/skills/do-design/SKILL.md +24 -23
- package/core/shared/skills/do-diagnose/SKILL.md +14 -4
- package/core/shared/skills/do-document/SKILL.md +11 -1
- package/core/shared/skills/do-document/references/deep_research.md +1 -2
- package/core/shared/skills/do-document/references/embedded-research.md +18 -6
- package/core/shared/skills/do-document/references/implementation-flow.md +5 -6
- package/core/shared/skills/do-execute-plan/SKILL.md +17 -59
- package/core/shared/skills/do-execute-plan/references/handoff_record.md +7 -2
- package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +13 -0
- package/core/shared/skills/do-execute-plan/references/readiness_gate.md +28 -1
- package/core/shared/skills/do-execute-plan/references/run_position.md +13 -1
- package/core/shared/skills/do-execute-plan/references/scaffold.md +17 -9
- package/core/shared/skills/do-execute-plan/references/state_checkpoint.md +11 -0
- package/core/shared/skills/do-execute-plan/references/task_attempts.md +78 -24
- package/core/shared/skills/do-flow/SKILL.md +8 -9
- package/core/shared/skills/do-flow/references/task_classes.md +2 -2
- package/core/shared/skills/do-git/SKILL.md +4 -0
- package/core/shared/skills/do-implement/SKILL.md +7 -9
- package/core/shared/skills/do-plan/SKILL.md +29 -19
- package/core/shared/skills/do-test/SKILL.md +7 -4
- package/core/shared/templates/doflow/constitution-template.md +9 -3
- package/core/shared/templates/doflow/data-model-template.md +1 -1
- package/core/shared/templates/doflow/design-template.md +113 -16
- package/core/shared/templates/doflow/plan-template.md +11 -10
- package/core/shared/templates/doflow/question-log-template.md +14 -2
- package/core/shared/templates/doflow/requirement-template.md +1 -1
- package/core/worker-evidence/antigravity/checks.json +14 -0
- package/core/worker-evidence/codex/2026-10-18-cli-check.json +107 -0
- package/core/worker-evidence/codex/2026-10-18-live-run-edit.json +73 -0
- package/core/worker-evidence/codex/2026-10-18-live-run-read-only.json +62 -0
- package/core/worker-evidence/codex/2026-10-24-cli-check.json +126 -0
- package/core/worker-evidence/codex/checks.json +38 -0
- package/package.json +10 -6
- package/src/adapters/antigravity/index.js +226 -113
- package/src/adapters/claude/index.js +39 -5
- package/src/adapters/codex/agents.js +25 -15
- package/src/adapters/codex/hooks.js +40 -5
- package/src/adapters/codex/index.js +100 -22
- package/src/adapters/codex/native-projection.js +6 -2
- package/src/adapters/copilot/index.js +58 -23
- package/src/adapters/copy-tree.js +294 -48
- package/src/adapters/guidance-manifest.js +71 -0
- package/src/adapters/guidance-pointer.js +19 -0
- package/src/adapters/hook-commands.js +6 -10
- package/src/adapters/index.js +1 -0
- package/src/adapters/kiro/index.js +38 -13
- package/src/adapters/opencode/index.js +8 -8
- package/src/adapters/pi/hooks.js +120 -0
- package/src/adapters/pi/index.js +48 -16
- package/src/adapters/resolve-source.js +26 -2
- package/src/cli/commands/install.js +3 -2
- package/src/cli/commands/reconcile.js +53 -9
- package/src/cli/commands/remove.js +2 -2
- package/src/cli/commands/rollback.js +6 -3
- package/src/cli/commands/self-update.js +18 -9
- package/src/cli/commands/status.js +21 -2
- package/src/cli/commands/ui.js +99 -0
- package/src/cli/commands/update.js +3 -2
- package/src/cli/index.js +338 -33
- package/src/cli/runtime-commands.js +243 -52
- package/src/cli/shared.js +0 -2
- package/src/helper/git.js +1 -1
- package/src/helper/guardrails.js +1 -1
- package/src/helper/marker-merge.js +31 -13
- package/src/helper/package-ids.js +37 -0
- package/src/helper/semver.js +94 -0
- package/src/install/backup.js +105 -15
- package/src/install/context.js +1 -1
- package/src/install/targets.js +31 -16
- package/src/lifecycle/coverage.js +74 -0
- package/src/lifecycle/hook-step.js +61 -0
- package/src/lifecycle/hook-tier.js +160 -0
- package/src/lifecycle/index.js +434 -86
- package/src/lifecycle/retired-harnesses.js +318 -0
- package/src/lifecycle/view.js +35 -15
- package/src/registry/index.js +686 -32
- package/src/registry/worker-ids.js +45 -0
- package/src/release/build-package.js +0 -3
- package/src/release/docs-blocks.js +492 -0
- package/src/release/preflight.js +425 -0
- package/src/release/rehearse.js +401 -0
- package/src/release/release-workflow.js +733 -0
- package/src/release/sync-plugin-versions.js +43 -7
- package/src/runtime/advice/bench-gate.js +25 -0
- package/src/runtime/advice/cli.js +59 -16
- package/src/runtime/advice/client.js +32 -9
- package/src/runtime/advice/config.js +98 -133
- package/src/runtime/advice/doctor.js +1 -1
- package/src/runtime/advice/elevation.js +97 -0
- package/src/runtime/advice/endpoint-guard.js +9 -3
- package/src/runtime/advice/mode.js +37 -0
- package/src/runtime/advice/record.js +18 -5
- package/src/runtime/advice/registry.js +4 -1
- package/src/runtime/advice/shadow-config.js +229 -0
- package/src/runtime/advice/shadow-dispatcher.js +276 -0
- package/src/runtime/brief-rules.js +81 -0
- package/src/runtime/brief-tools.js +111 -34
- package/src/runtime/candidate.js +514 -0
- package/src/runtime/capabilities/executor.js +450 -0
- package/src/runtime/capabilities/loopback.js +41 -0
- package/src/runtime/capabilities/sanitizer.js +88 -0
- package/src/runtime/capability-router.js +135 -3
- package/src/runtime/checkouts.js +73 -11
- package/src/runtime/claims.js +27 -12
- package/src/runtime/cli-result.js +11 -4
- package/src/runtime/cli.js +221 -277
- package/src/runtime/config-home.js +42 -0
- package/src/runtime/context/arbitrate.js +767 -0
- package/src/runtime/context/budget.js +203 -0
- package/src/runtime/context/compose.js +1367 -0
- package/src/runtime/context/delivery-store.js +100 -0
- package/src/runtime/context/emission-rules.js +118 -0
- package/src/runtime/context/identity.js +227 -0
- package/src/runtime/context/mandatory.js +594 -0
- package/src/runtime/context/pointer.js +142 -0
- package/src/runtime/context/primary-command.js +117 -0
- package/src/runtime/context/primary.js +344 -0
- package/src/runtime/context/summary-store.js +655 -0
- package/src/runtime/context-pack.js +1106 -245
- package/src/runtime/decision-register.js +13 -4
- package/src/runtime/dispatch/admission.js +392 -0
- package/src/runtime/dispatch/attempt-end.js +274 -0
- package/src/runtime/dispatch/command.js +628 -0
- package/src/runtime/dispatch/controls.js +904 -0
- package/src/runtime/dispatch/envelope.js +276 -0
- package/src/runtime/dispatch/grants.js +310 -0
- package/src/runtime/dispatch/integrate.js +617 -0
- package/src/runtime/dispatch/loop.js +1835 -0
- package/src/runtime/dispatch/store.js +352 -0
- package/src/runtime/dispatch/verify-run.js +201 -0
- package/src/runtime/evidence-fields.js +39 -0
- package/src/runtime/evidence-ledger.js +41 -7
- package/src/runtime/failure/capture.js +3 -1
- package/src/runtime/failure/cli.js +25 -9
- package/src/runtime/failure/home.js +57 -30
- package/src/runtime/failure/store.js +7 -2
- package/src/runtime/feature-pointer.js +174 -0
- package/src/runtime/feature-resolve.js +13 -2
- package/src/runtime/fleet/command.js +77 -0
- package/src/runtime/fleet/projects.js +178 -0
- package/src/runtime/fleet/tree.js +383 -0
- package/src/runtime/freshness.js +77 -10
- package/src/runtime/git-memo.js +46 -0
- package/src/runtime/guidance/ablation.js +427 -0
- package/src/runtime/health.js +565 -17
- package/src/runtime/history-compactor.js +13 -3
- package/src/runtime/implementation-gate.js +277 -22
- package/src/runtime/inventory/coverage.js +1 -1
- package/src/runtime/inventory/index.js +1 -1
- package/src/runtime/inventory/precedence.js +2 -2
- package/src/runtime/inventory/siblings.js +6 -4
- package/src/runtime/knowledge/code-corpus.js +277 -0
- package/src/runtime/knowledge/code-lexical.js +130 -0
- package/src/runtime/knowledge/code-retrieval.js +307 -0
- package/src/runtime/knowledge/code-validation.js +106 -0
- package/src/runtime/knowledge/gp3-gate.js +74 -0
- package/src/runtime/knowledge/graph-adapter.js +288 -0
- package/src/runtime/knowledge/graph-fallback.js +394 -0
- package/src/runtime/knowledge/hybrid.js +136 -8
- package/src/runtime/knowledge/retrieval.js +34 -1
- package/src/runtime/knowledge/rtk-compress.js +77 -0
- package/src/runtime/knowledge/semble-bridge.py +106 -0
- package/src/runtime/knowledge/semble-lifecycle.js +114 -0
- package/src/runtime/knowledge/semble-provider.js +365 -0
- package/src/runtime/lifecycle/cli.js +16 -6
- package/src/runtime/lifecycle/event-store.js +8 -6
- package/src/runtime/lifecycle/followup.js +6 -1
- package/src/runtime/lifecycle/overview.js +24 -1
- package/src/runtime/lifecycle/report-store.js +8 -10
- package/src/runtime/lifecycle/retention.js +95 -31
- package/src/runtime/lifecycle/root.js +9 -1
- package/src/runtime/lifecycle/status.js +34 -17
- package/src/runtime/lifecycle/store-upkeep.js +56 -7
- package/src/runtime/mask.js +134 -7
- package/src/runtime/mcp-consultations.js +40 -6
- package/src/runtime/model-router.js +79 -7
- package/src/runtime/models/catalogue.js +191 -0
- package/src/runtime/models/command.js +153 -0
- package/src/runtime/off-words.js +12 -0
- package/src/runtime/outcome.js +3 -3
- package/src/runtime/packages/command.js +1009 -0
- package/src/runtime/packages/contributions.js +116 -0
- package/src/runtime/packages/digest.js +132 -0
- package/src/runtime/packages/fetch.js +182 -0
- package/src/runtime/packages/grants.js +192 -0
- package/src/runtime/packages/index-file.js +134 -0
- package/src/runtime/packages/instruction.js +90 -0
- package/src/runtime/packages/manifest.js +331 -0
- package/src/runtime/packages/points.js +477 -0
- package/src/runtime/packages/programs.js +216 -0
- package/src/runtime/packages/scaffold.js +277 -0
- package/src/runtime/packages/source.js +90 -0
- package/src/runtime/packages/state.js +164 -0
- package/src/runtime/packages/store.js +449 -0
- package/src/runtime/packages/tar.js +106 -0
- package/src/runtime/packages/view.js +406 -0
- package/src/runtime/plan-check.js +59 -0
- package/src/runtime/plan-content.js +324 -0
- package/src/runtime/policy-init.js +118 -0
- package/src/runtime/profiles/doctor.js +96 -0
- package/src/runtime/profiles/resolve.js +244 -0
- package/src/runtime/profiles/rollback.js +254 -0
- package/src/runtime/profiles/sampler.js +41 -0
- package/src/runtime/readiness-record.js +16 -11
- package/src/runtime/readiness.js +127 -16
- package/src/runtime/research-request.js +50 -25
- package/src/runtime/retrieval-plan.js +402 -73
- package/src/runtime/retrieval-record.js +293 -0
- package/src/runtime/review/command.js +246 -0
- package/src/runtime/review/dominance.js +68 -0
- package/src/runtime/review/findings.js +434 -0
- package/src/runtime/review/identity.js +255 -0
- package/src/runtime/review/protocol-command.js +109 -0
- package/src/runtime/review/protocols.js +405 -0
- package/src/runtime/review/resolve-protocol.js +302 -0
- package/src/runtime/review/start.js +530 -0
- package/src/runtime/roadmap/facts.js +479 -0
- package/src/runtime/roadmap/gates.js +270 -0
- package/src/runtime/roadmap/loop.js +1636 -0
- package/src/runtime/roadmap/merge.js +381 -0
- package/src/runtime/roadmap/rows.js +1113 -0
- package/src/runtime/roadmap/seed.js +951 -0
- package/src/runtime/rules-report.js +336 -0
- package/src/runtime/scaffold/artifacts.js +63 -9
- package/src/runtime/scaffold/generate.js +21 -9
- package/src/runtime/settings/autopilot.js +106 -0
- package/src/runtime/settings/cli.js +280 -0
- package/src/runtime/settings/config-write.js +314 -0
- package/src/runtime/settings/files.js +271 -0
- package/src/runtime/settings/legacy.js +154 -0
- package/src/runtime/settings/lexical.js +56 -0
- package/src/runtime/settings/prepared-run.js +269 -0
- package/src/runtime/settings/project-layers.js +118 -0
- package/src/runtime/settings/refs.js +288 -0
- package/src/runtime/settings/registry.js +553 -0
- package/src/runtime/settings/resolve.js +713 -0
- package/src/runtime/settings/shared.js +37 -0
- package/src/runtime/settings/worker-billing.js +107 -0
- package/src/runtime/settings/write.js +269 -0
- package/src/runtime/slot-command.js +78 -0
- package/src/runtime/slots.js +671 -0
- package/src/runtime/source-version.js +290 -0
- package/src/runtime/state-root.js +217 -0
- package/src/runtime/storage/cli.js +12 -5
- package/src/runtime/storage/engine.js +9 -2
- package/src/runtime/storage/registry.js +14 -1
- package/src/runtime/storage/roots.js +66 -16
- package/src/runtime/storage/rules.js +82 -10
- package/src/runtime/storage/upkeep.js +10 -2
- package/src/runtime/storage/work-status.js +245 -26
- package/src/runtime/task-attempts.js +589 -69
- package/src/runtime/task-classifier.js +47 -11
- package/src/runtime/task-graph.js +373 -0
- package/src/runtime/task-run.js +778 -0
- package/src/runtime/task-scope.js +202 -56
- package/src/runtime/task-sources.js +147 -0
- package/src/runtime/task-state.js +440 -65
- package/src/runtime/team/admission.js +301 -0
- package/src/runtime/team/envelope.js +324 -0
- package/src/runtime/team/review-guard.js +156 -0
- package/src/runtime/trace/analyze.js +427 -0
- package/src/runtime/trace/baseline.js +770 -0
- package/src/runtime/trace/ledger.js +63 -140
- package/src/runtime/trace/otlp-export.js +568 -0
- package/src/runtime/trace/otlp-map.js +481 -0
- package/src/runtime/trace/spans.js +745 -0
- package/src/runtime/trace/telemetry.js +225 -0
- package/src/runtime/trace/views.js +1 -0
- package/src/runtime/transcripts/command.js +98 -0
- package/src/runtime/transcripts/cursor.js +326 -0
- package/src/runtime/transcripts/read.js +126 -0
- package/src/runtime/transcripts/readers/claude-jsonl.js +74 -0
- package/src/runtime/transcripts/readers/codex-rollout.js +70 -0
- package/src/runtime/transcripts/readers/copilot-events.js +90 -0
- package/src/runtime/transcripts/readers/kiro-jsonl.js +77 -0
- package/src/runtime/transcripts/readers/pi-jsonl.js +59 -0
- package/src/runtime/transcripts/registry.js +161 -0
- package/src/runtime/transcripts/stats.js +161 -0
- package/src/runtime/verification/check-key.js +628 -0
- package/src/runtime/verification/contract-runner.js +546 -11
- package/src/runtime/verification/engine.js +499 -9
- package/src/runtime/verification/impact.js +617 -0
- package/src/runtime/verification/inflight.js +205 -0
- package/src/runtime/verification/registry.js +176 -0
- package/src/runtime/verification/reuse.js +184 -0
- package/src/runtime/verification/telemetry-emit.js +254 -0
- package/src/runtime/verification/test-selection.js +67 -7
- package/src/runtime/worker/active.js +90 -0
- package/src/runtime/worker/cancel.js +222 -0
- package/src/runtime/worker/catalogue.js +122 -0
- package/src/runtime/worker/command.js +677 -0
- package/src/runtime/worker/evidence.js +288 -0
- package/src/runtime/worker/launch.js +288 -0
- package/src/runtime/worker/models.js +137 -0
- package/src/runtime/worker/parsers.js +218 -0
- package/src/runtime/worker/probes/index.js +706 -0
- package/src/runtime/worker/process-tree.js +415 -0
- package/src/runtime/worker/quota.js +43 -0
- package/src/runtime/worker/readiness.js +713 -0
- package/src/runtime/worker/run-store.js +166 -0
- package/src/runtime/worker/supervisor.js +541 -0
- package/src/runtime/worker/worktree-check.js +252 -0
- package/src/runtime/workflow-engine.js +5 -1
- package/src/runtime/workflow-orchestrator.js +578 -63
- package/src/runtime/worktree.js +149 -22
- package/src/state/index.js +1 -1
- package/src/state/lockfile.js +64 -10
- package/src/state/run-lock.js +1 -1
- package/types/node-commonjs.d.ts +106 -7
- package/core/.antigravity-plugin/hooks.json +0 -39
- package/core/harnesses/gemini/hooks/hooks.json +0 -77
- package/core/harnesses/gemini/hooks/lib.sh +0 -302
- package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +0 -21
- package/core/harnesses/gemini/hooks/post-edit-lint.sh +0 -39
- package/core/harnesses/gemini/hooks/pre-bash-guard.sh +0 -21
- package/core/harnesses/gemini/hooks/pre-compact.sh +0 -38
- package/core/harnesses/gemini/hooks/pre-implement-gate.sh +0 -22
- package/core/harnesses/gemini/hooks/session-end.impl.sh +0 -89
- package/core/harnesses/gemini/hooks/session-end.sh +0 -5
- package/core/harnesses/gemini/hooks/session-start.sh +0 -5
- package/core/harnesses/gemini/settings/adapter-defaults.json +0 -4
- package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
- package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
- package/core/harnesses/shared/hooks/hooks.json +0 -47
- package/core/shared/guidance/FLAGS.md +0 -25
- package/core/shared/guidance/rules/RULE_01_SAFETY.md +0 -25
- package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +0 -23
- package/core/shared/guidance/rules/RULE_03_QUALITY.md +0 -14
- package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +0 -46
- package/src/adapters/gemini/hooks.js +0 -210
- package/src/adapters/gemini/index.js +0 -390
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "doflow-worker-checks-v1",
|
|
3
|
+
"harness": "codex",
|
|
4
|
+
"binary": "codex",
|
|
5
|
+
"version": { "argv": ["--version"], "expect": "^codex-cli \\d+\\.\\d+\\.\\d+" },
|
|
6
|
+
"checks": [
|
|
7
|
+
{
|
|
8
|
+
"id": "exec-one-shot",
|
|
9
|
+
"argv": ["exec", "--help"],
|
|
10
|
+
"expect": ["^Usage: codex exec \\[OPTIONS\\] \\[PROMPT\\]", "instructions are read from stdin"],
|
|
11
|
+
"establishes": ["runnableProbe", "oneShot"]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "exec-json",
|
|
15
|
+
"argv": ["exec", "--help"],
|
|
16
|
+
"expect": ["^\\s+--json$", "Print events to stdout as JSONL", "-o, --output-last-message"],
|
|
17
|
+
"establishes": ["structuredOutput"]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "exec-sandbox",
|
|
21
|
+
"argv": ["exec", "--help"],
|
|
22
|
+
"expect": ["-s, --sandbox <SANDBOX_MODE>", "read-only, workspace-write"],
|
|
23
|
+
"establishes": ["readOnly", "isolatedEdit"]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "spawn-denial",
|
|
27
|
+
"argv": ["features", "list", "--disable", "multi_agent", "--disable", "multi_agent_v2"],
|
|
28
|
+
"expect": ["^multi_agent\\s+\\S+\\s+false$", "^multi_agent_v2\\s+\\S+\\s+false$"],
|
|
29
|
+
"establishes": ["spawnDenial"]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "exec-model",
|
|
33
|
+
"argv": ["exec", "--help"],
|
|
34
|
+
"expect": ["^\\s+-m, --model <MODEL>$"],
|
|
35
|
+
"establishes": ["model"]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khoavu882/doflow",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "DoFlow config installer — npx CLI for the registry-driven multi-harness install/update/remove lifecycle",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
7
7
|
"codex",
|
|
8
|
-
"gemini",
|
|
9
8
|
"opencode",
|
|
10
9
|
"ai-coding-agent",
|
|
11
10
|
"skills",
|
|
@@ -26,16 +25,21 @@
|
|
|
26
25
|
"doflow": "bin/doflow.js"
|
|
27
26
|
},
|
|
28
27
|
"engines": {
|
|
29
|
-
"node": "
|
|
28
|
+
"node": ">=24.22.1"
|
|
30
29
|
},
|
|
31
30
|
"scripts": {
|
|
32
|
-
"test": "node --test \"test/**/*.test.js\"",
|
|
31
|
+
"test": "node --test \"test/**/*.test.js\" \"test/**/*.test.ts\"",
|
|
32
|
+
"test:fast": "node test/helper/fast-tier.ts",
|
|
33
33
|
"typecheck": "npx -y -p typescript@5.7.2 tsc -p tsconfig.json",
|
|
34
34
|
"build:package": "node src/release/build-package.js .pack",
|
|
35
|
-
"bench": "node bench/runner.
|
|
35
|
+
"bench": "node bench/runner.ts",
|
|
36
36
|
"drift": "node scripts/check-format-drift.js",
|
|
37
|
+
"emission-rules": "node src/runtime/context/emission-rules.js --check",
|
|
37
38
|
"release-notes": "node src/release/changelog-section.js",
|
|
38
|
-
"
|
|
39
|
+
"docs:blocks": "node src/release/docs-blocks.js --check",
|
|
40
|
+
"release:preflight": "node src/release/preflight.js",
|
|
41
|
+
"release:rehearse": "node src/release/rehearse.js",
|
|
42
|
+
"version": "node src/release/sync-plugin-versions.js && git add core/.codex-plugin/plugin.json core/.claude-plugin/plugin.json core/.plugin/plugin.json core/registry/packages/doflow/doflow-package.json core/registry/contribution-points.json"
|
|
39
43
|
},
|
|
40
44
|
"files": [
|
|
41
45
|
"bin/",
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
// Antigravity CLI adapter (#8). Scope follows the surfaces verified against Antigravity's own
|
|
6
6
|
// docs (antigravity.google/docs/cli/*):
|
|
7
|
-
// instructions — marker-managed section in
|
|
8
|
-
//
|
|
9
|
-
// one
|
|
7
|
+
// instructions — marker-managed section in project AGENTS.md and global ~/.gemini/GEMINI.md (left
|
|
8
|
+
// alone while another live harness declares it); a retired harness's span there is taken over in
|
|
9
|
+
// one write (row 127 IC-007), a person-edited file kept until --force. See instructionTarget.
|
|
10
|
+
// rules — the core set (DOFLOW_CORE.md and the files it imports), flat, in project .agents/rules
|
|
11
|
+
// only; the full guidance tree stays in .doflow/guidance.
|
|
10
12
|
// skills — folder-form copy-tree into project .agents/skills or user ~/.gemini/config/skills.
|
|
11
13
|
// agents — copy-tree into project .agents/agents or user ~/.gemini/config/agents.
|
|
12
14
|
// mcp — entries of the mcpServers object in .agents/mcp_config.json (workspace) or
|
|
@@ -20,9 +22,10 @@ const fs = require('node:fs');
|
|
|
20
22
|
const os = require('node:os');
|
|
21
23
|
const path = require('node:path');
|
|
22
24
|
|
|
23
|
-
const { MARKER_START, MARKER_END } = require('../../helper/marker-merge.js');
|
|
24
|
-
const { planTree, applyTree, removeTree, verifyTree, copyTreeAssets, ledgerFileResources, ledgerSiblingFingerprints, siblingReplacedNotices, fingerprint, readJson, sourceDirFor } = require('../copy-tree.js');
|
|
25
|
+
const { MARKER_START, MARKER_END, removeMarkedSection } = require('../../helper/marker-merge.js');
|
|
26
|
+
const { planTree, applyTree, removeTree, verifyTree, resolveTransform, copyTreeAssets, ledgerFileResources, ledgerSiblingFingerprints, siblingReplacedNotices, fingerprint, readJson, sourceDirFor } = require('../copy-tree.js');
|
|
25
27
|
const { declaredHarnessPaths, resolveHarnessPaths } = require('../../helper/harness-paths.js');
|
|
28
|
+
const { renderGuidancePointer } = require('../guidance-pointer.js');
|
|
26
29
|
const { readMcpFiles, planMcpEntries, verifyMcpEntries, ownedMcpIds, writeMcpEntries } = require('../mcp-entries.js');
|
|
27
30
|
|
|
28
31
|
const HARNESS = 'antigravity';
|
|
@@ -136,8 +139,8 @@ function sha256File(fsImpl , file ) {
|
|
|
136
139
|
|
|
137
140
|
/** Native paths per scope, resolved from the declaration in core/registry/harnesses.json
|
|
138
141
|
* ("paths"): project customization lives at <root>/.agents, global config at ~/.gemini/config
|
|
139
|
-
* (the shared-customization root); instructions
|
|
140
|
-
* rule is declared
|
|
142
|
+
* (the shared-customization root); instructions are AGENTS.md in the project and ~/.gemini/GEMINI.md
|
|
143
|
+
* globally; the hook surfaces are project-only, so no user rule is declared and they resolve to null. */
|
|
141
144
|
function resolveNativePaths(declaredPaths , { scope, scopeRoot, homeDir } = {}) {
|
|
142
145
|
if (scope !== 'project' && scope !== 'global') throw new Error(`Unsupported Antigravity scope '${scope}'`);
|
|
143
146
|
const resolved = resolveHarnessPaths(declaredPaths, { scope, scopeRoot, homeDir });
|
|
@@ -178,6 +181,8 @@ function createAntigravityAdapter({ declaredPaths = DEFAULT_DECLARED_PATHS }
|
|
|
178
181
|
apply,
|
|
179
182
|
remove,
|
|
180
183
|
verify: (options , impl = {}) => verify(options, { ...impl, nativePaths: nativePathsFor }),
|
|
184
|
+
planHookDoors: (options , impl = {}) => planHookDoors(options, { ...impl, nativePaths: nativePathsFor }),
|
|
185
|
+
verifyHookDoors: (options , impl = {}) => verifyHookDoors(options, { ...impl, nativePaths: nativePathsFor }),
|
|
181
186
|
};
|
|
182
187
|
}
|
|
183
188
|
|
|
@@ -210,16 +215,25 @@ function render({ content = '' } = {}) {
|
|
|
210
215
|
return `${MARKER_START}\n${String(content).trimEnd()}\n${MARKER_END}\n`;
|
|
211
216
|
}
|
|
212
217
|
|
|
213
|
-
|
|
218
|
+
const INSTRUCTIONS_IDENTITY = `doflow:${HARNESS}:instructions:managed-section`;
|
|
219
|
+
/** The short start marker the retired harness wrote into ~/.gemini/GEMINI.md (row 127). It is read
|
|
220
|
+
* only in a file this adapter is taking over, never written: the span it opens is replaced with ours. */
|
|
221
|
+
const PREDECESSOR_MARKER_START = '<!-- doflow:start -->';
|
|
222
|
+
|
|
223
|
+
/** The file's content with `rendered` as its DoFlow span: created, appended to a file with none, or
|
|
224
|
+
* replacing the span in place. `predecessor` also accepts the retired harness's start marker, for a
|
|
225
|
+
* file being taken over. `name` is the file's name in the conflict. */
|
|
226
|
+
function managedInstruction(existing , rendered , { name = 'AGENTS.md', predecessor = false } = {}) {
|
|
214
227
|
if (existing === null) return { ok: true, operation: 'create', content: rendered };
|
|
215
|
-
|
|
228
|
+
let start = existing.indexOf(MARKER_START);
|
|
229
|
+
if (start === -1 && predecessor) start = existing.indexOf(PREDECESSOR_MARKER_START);
|
|
216
230
|
const end = existing.indexOf(MARKER_END);
|
|
217
231
|
if (start === -1 && end === -1) {
|
|
218
232
|
const separator = existing === '' || existing.endsWith('\n') ? '\n' : '\n\n';
|
|
219
233
|
const content = `${existing}${separator}${rendered}`;
|
|
220
234
|
return { ok: true, operation: 'merge', content };
|
|
221
235
|
}
|
|
222
|
-
if (start === -1 || end === -1 || end < start) return { ok: false, conflict:
|
|
236
|
+
if (start === -1 || end === -1 || end < start) return { ok: false, conflict: `${name} has malformed DoFlow managed-section markers` };
|
|
223
237
|
const content = `${existing.slice(0, start)}${rendered}${existing.slice(end + MARKER_END.length).replace(/^\n?/, '')}`;
|
|
224
238
|
return { ok: true, operation: content === existing ? 'none' : 'merge', content };
|
|
225
239
|
}
|
|
@@ -277,7 +291,7 @@ function planTrees({ assets, paths, scope, neutralResources, removing, repoRoot,
|
|
|
277
291
|
for (const { asset, destDir } of targets) {
|
|
278
292
|
const sourceDir = sourceDirFor(asset, { repoRoot }, fsImpl, HARNESS);
|
|
279
293
|
const previousResources = ledgerFileResources(neutralResources, HARNESS, asset.id);
|
|
280
|
-
const result = planTree({ sourceDir, destDir, previousResources, siblingFingerprints: ledgerSiblingFingerprints(neutralResources, HARNESS), operation: removing ? 'remove' : 'apply', fsImpl, layout: asset.layout, keepModified: !removing,
|
|
294
|
+
const result = planTree({ sourceDir, destDir, previousResources, siblingFingerprints: ledgerSiblingFingerprints(neutralResources, HARNESS), operation: removing ? 'remove' : 'apply', fsImpl, layout: asset.layout, transform: asset.transform, select: asset.select, keepModified: !removing,
|
|
281
295
|
// Forwarded so the CLI's --force reaches planTree's conflict check; omitting it let
|
|
282
296
|
// planTree's own `force = false` default stand in silently. Gated on `!removing` for the
|
|
283
297
|
// reason codex/index.ts states in full: force heals drift on apply, but a hand-edited file
|
|
@@ -295,6 +309,7 @@ function planTrees({ assets, paths, scope, neutralResources, removing, repoRoot,
|
|
|
295
309
|
ownershipIdentity: `doflow:${HARNESS}:copy-tree:${asset.id}:${change.relPath}`,
|
|
296
310
|
kind: 'copy-tree-file', identity: change.relPath,
|
|
297
311
|
afterFingerprint: change.fingerprint, fingerprint: change.fingerprint, sourceVersion: 'registry-v1',
|
|
312
|
+
transformName: asset.transform || null,
|
|
298
313
|
...(change.kept ? { retained: true, retainedFor: [] } : {}),
|
|
299
314
|
projection: { renderer: 'copy-tree' },
|
|
300
315
|
});
|
|
@@ -313,7 +328,8 @@ function runTreeChanges(changes , mode ) {
|
|
|
313
328
|
.filter((c ) => c.projection?.renderer === 'copy-tree' || c.kind === 'copy-tree-file')
|
|
314
329
|
.map((c ) => ({ relPath: c.identity ?? c.relPath, target: c.target,
|
|
315
330
|
source: c._text ? undefined : c.source, operation: c.operation,
|
|
316
|
-
fingerprint: c.fingerprint, pruneGuard: c.pruneGuard,
|
|
331
|
+
fingerprint: c.fingerprint, pruneGuard: c.pruneGuard, transformName: c.transformName || null,
|
|
332
|
+
...(c._text ? { _text: c._text } : {}) }));
|
|
317
333
|
// Content-managed tree files (hook scripts): write rendered text with +x, not a byte copy.
|
|
318
334
|
for (const t of treeChanges) {
|
|
319
335
|
if (t._text === undefined) continue;
|
|
@@ -328,58 +344,100 @@ function runTreeChanges(changes , mode ) {
|
|
|
328
344
|
const plain = treeChanges.filter((t ) => t._text === undefined);
|
|
329
345
|
const writes = plain.filter((c ) => c.operation !== 'remove');
|
|
330
346
|
const removals = plain.filter((c ) => c.operation === 'remove');
|
|
331
|
-
|
|
347
|
+
// A projection that declares a transform (the rules' always_on header) is re-derived from the
|
|
348
|
+
// source at write time, so each change is applied under its own transform.
|
|
349
|
+
const byTransform = new Map ();
|
|
350
|
+
for (const change of writes) byTransform.set(change.transformName, [...(byTransform.get(change.transformName) || []), change]);
|
|
351
|
+
let applied = 0;
|
|
352
|
+
for (const [transformName, group] of byTransform) {
|
|
353
|
+
applied += applyTree({ changes: group, transform: transformName ? resolveTransform(transformName) : undefined }).applied;
|
|
354
|
+
}
|
|
332
355
|
const removed = removals.length ? removeTree({ changes: removals }).removed : 0;
|
|
333
356
|
return { applied, removed };
|
|
334
357
|
})(),
|
|
335
358
|
};
|
|
336
|
-
const writes = treeChanges.filter((c ) => c.operation !== 'remove');
|
|
337
|
-
const removals = treeChanges.filter((c ) => c.operation === 'remove');
|
|
338
|
-
const applied = writes.length ? applyTree({ changes: writes }).applied : 0;
|
|
339
|
-
const removed = removals.length ? removeTree({ changes: removals }).removed : 0;
|
|
340
|
-
return { applied, removed };
|
|
341
359
|
}
|
|
342
360
|
|
|
343
361
|
// ---- instructions component ----
|
|
344
362
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
363
|
+
/** The instruction file this run manages, or null: project AGENTS.md as ever; the global GEMINI.md
|
|
364
|
+
* only when the pointer asset is selected and no other live harness in `registry` declares that same
|
|
365
|
+
* file (until the harness that owned it retires, its adapter keeps it and this one stays out). */
|
|
366
|
+
function instructionTarget({ paths, assets, registry } ) {
|
|
367
|
+
if (!paths.instruction) return null;
|
|
368
|
+
if (scopeOf(paths) === 'project') return paths.instruction;
|
|
369
|
+
if (!(assets ?? []).some((asset ) => asset.id === POINTER_ASSET_ID)) return null;
|
|
370
|
+
const declaredBy = (harness ) => {
|
|
371
|
+
if (harness?.id === HARNESS || !harness?.paths?.instruction) return false;
|
|
372
|
+
try { return resolveHarnessPaths({ instruction: harness.paths.instruction }, { scope: 'global', scopeRoot: paths.root, homeDir: paths.root }).instruction === paths.instruction; } catch { return false; }
|
|
373
|
+
};
|
|
374
|
+
return (registry?.harnesses ?? []).some(declaredBy) ? null : paths.instruction;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** How this run stands to a section it took over (IC-007): the lifecycle's handover verdict for the
|
|
378
|
+
* file, this harness's own row on it, and whether a person-edited file stays as it is (`retained`:
|
|
379
|
+
* edited before the handover, or kept since, and no --force). `predecessor` lets the retired
|
|
380
|
+
* harness's span count as the section to replace; `keptRow` is a row recorded as kept. A handover
|
|
381
|
+
* file whose DoFlow span already is this harness's render was written by DoFlow itself (a run that
|
|
382
|
+
* threw after that write and before its ledger write), so it does not count as edited. */
|
|
383
|
+
function instructionState({ target, context, resources, paths, fsImpl = fs } ) {
|
|
384
|
+
const handover = (context.handovers ?? []).find((item ) => item.target === target) ?? null;
|
|
385
|
+
const ownRow = (resources ?? []).find((row ) => row.harness === HARNESS && row.target === target && row.ownershipIdentity === INSTRUCTIONS_IDENTITY) ?? null;
|
|
386
|
+
const ownWrite = () => {
|
|
387
|
+
const rendered = renderedInstruction(paths, fsImpl);
|
|
388
|
+
if (rendered === null || !fsImpl.existsSync(target)) return false;
|
|
389
|
+
const outcome = managedInstruction(fsImpl.readFileSync(target, 'utf8'), rendered);
|
|
390
|
+
return outcome.ok && outcome.operation === 'none';
|
|
391
|
+
};
|
|
392
|
+
const edited = (handover?.edited === true && !ownWrite()) || ownRow?.retainedEdit === true;
|
|
393
|
+
return { predecessor: Boolean(handover) || ownRow?.retainedEdit === true, retained: edited && context.force !== true,
|
|
394
|
+
keptRow: ownRow?.retainedEdit === true };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function instructionsChange(target , fields ) {
|
|
398
|
+
return { assetId: POINTER_ASSET_ID, target, ownershipIdentity: INSTRUCTIONS_IDENTITY,
|
|
399
|
+
kind: 'instructions-section', identity: path.basename(target), projection: { renderer: 'antigravity-instructions' }, ...fields };
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function planInstructions({ paths, target, removing, state, fsImpl = fs } ) {
|
|
403
|
+
const none = { changes: [], conflicts: [], notices: [] };
|
|
404
|
+
if (!target) return none;
|
|
348
405
|
if (removing) {
|
|
349
406
|
// Removal must strip the section DoFlow owns while leaving foreign bytes untouched — same
|
|
350
407
|
// contract as the other AGENTS-style adapters.
|
|
351
|
-
if (!fsImpl.existsSync(
|
|
352
|
-
const text = fsImpl.readFileSync(
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
ownershipIdentity: `doflow:${HARNESS}:instructions:managed-section`,
|
|
358
|
-
kind: 'instructions-section', identity: 'AGENTS.md',
|
|
359
|
-
projection: { renderer: 'antigravity-instructions' },
|
|
360
|
-
}],
|
|
361
|
-
conflicts: [],
|
|
362
|
-
};
|
|
408
|
+
if (!fsImpl.existsSync(target)) return none;
|
|
409
|
+
const text = fsImpl.readFileSync(target, 'utf8');
|
|
410
|
+
// A kept edited file with no span left still carries this harness's row: the remove change
|
|
411
|
+
// releases the row, and apply finds no span to strip, so the person's file is not touched.
|
|
412
|
+
if (!text.includes(MARKER_START) && !state.keptRow) return none;
|
|
413
|
+
return { ...none, changes: [instructionsChange(target, { operation: 'remove' })] };
|
|
363
414
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
if (
|
|
415
|
+
if (state.retained) {
|
|
416
|
+
const shown = scopeOf(paths) === 'global' ? `~/${path.relative(paths.root, target)}` : path.relative(paths.root, target);
|
|
417
|
+
return { ...none, notices: [`kept ${shown}: changed before handover; --force replaces the DoFlow section`] };
|
|
418
|
+
}
|
|
419
|
+
const rendered = renderedInstruction(paths, fsImpl);
|
|
420
|
+
if (rendered === null) return none;
|
|
421
|
+
const existing = fsImpl.existsSync(target) ? fsImpl.readFileSync(target, 'utf8') : null;
|
|
422
|
+
const outcome = managedInstruction(existing, rendered, { name: path.basename(target), predecessor: state.predecessor });
|
|
423
|
+
if (!outcome.ok) return { ...none, conflicts: [outcome.conflict] };
|
|
424
|
+
if (outcome.operation === 'none') return none;
|
|
370
425
|
return {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
kind: 'instructions-section', identity: 'AGENTS.md',
|
|
426
|
+
...none,
|
|
427
|
+
changes: [instructionsChange(target, {
|
|
428
|
+
operation: existing === null ? 'create' : 'update',
|
|
375
429
|
afterFingerprint: fingerprint(outcome.content), sourceVersion: 'registry-v1',
|
|
376
|
-
projection: { renderer: 'antigravity-instructions' },
|
|
377
430
|
_content: outcome.content,
|
|
378
|
-
}],
|
|
379
|
-
conflicts: [],
|
|
431
|
+
})],
|
|
380
432
|
};
|
|
381
433
|
}
|
|
382
434
|
|
|
435
|
+
/** This scope's DoFlow section: the shared pointer rendered for the scope, inside the markers. */
|
|
436
|
+
function renderedInstruction(paths , fsImpl ) {
|
|
437
|
+
const sourceText = pointerBody(fsImpl);
|
|
438
|
+
return sourceText ? render({ content: renderGuidancePointer(sourceText, { scope: scopeOf(paths), scopeRoot: paths.root }) }) : null;
|
|
439
|
+
}
|
|
440
|
+
|
|
383
441
|
function pointerBody(fsImpl ) {
|
|
384
442
|
// The shared pointer prose ships once; read it through the same repo-relative anchor the other
|
|
385
443
|
// AGENTS-style adapters use.
|
|
@@ -430,13 +488,18 @@ function plan(options = {}, impl = {}) {
|
|
|
430
488
|
const selectedServers = Array.isArray(options.mcp) ? options.mcp : [];
|
|
431
489
|
const discovery = options.discovery ?? discover(options, impl);
|
|
432
490
|
|
|
433
|
-
const
|
|
491
|
+
const instructionFile = instructionTarget({ paths, assets: options.assets, registry: options.registry });
|
|
492
|
+
const instructions = planInstructions({ paths, target: instructionFile, removing, fsImpl,
|
|
493
|
+
state: instructionState({ target: instructionFile, context, resources: neutralResources, paths, fsImpl }) });
|
|
434
494
|
const trees = planTrees({ assets: options.assets, paths, scope, neutralResources, removing, repoRoot: context.repoRoot, force: context.force === true, fsImpl });
|
|
435
495
|
const mcp = planMcpEntries({
|
|
436
496
|
...mcpEntriesInput({ paths, mcp: selectedServers, mcpAdoptable: options.mcpAdoptable, resources: neutralResources }),
|
|
437
497
|
files: discovery.mcpSnapshot, removing,
|
|
438
498
|
});
|
|
439
|
-
|
|
499
|
+
// Hook tiers (maint-hooks): outside `hooks.harnesses` this plan carries no hook change; the lifecycle
|
|
500
|
+
// plans the removal of what an earlier run wrote, from the ledger, against the full registry.
|
|
501
|
+
const hooksPlan = context.hooksOff === true && !removing ? { changes: [], conflicts: [] }
|
|
502
|
+
: planHooks({ paths, scope, neutralResources, removing, repoRoot: context.repoRoot, fsImpl });
|
|
440
503
|
|
|
441
504
|
const changes = [...instructions.changes, ...trees.changes, ...mcp.changes, ...hooksPlan.changes];
|
|
442
505
|
const conflicts = [...instructions.conflicts, ...trees.conflicts, ...mcp.conflicts, ...hooksPlan.conflicts];
|
|
@@ -445,10 +508,33 @@ function plan(options = {}, impl = {}) {
|
|
|
445
508
|
conflicts,
|
|
446
509
|
prerequisites: [],
|
|
447
510
|
requiredNativeResources: changes,
|
|
448
|
-
notices: [...trees.notices, ...mcp.notices],
|
|
511
|
+
notices: [...instructions.notices, ...trees.notices, ...mcp.notices],
|
|
449
512
|
};
|
|
450
513
|
}
|
|
451
514
|
|
|
515
|
+
/** The hook front doors (IC-037): the shims and the hooks.json groups that run them, planned and
|
|
516
|
+
* verified alone. Project scope only, and only when the harness selected the hooks asset. */
|
|
517
|
+
function planHookDoors(options = {}, impl = {}) {
|
|
518
|
+
const fsImpl = impl.fsImpl || fs;
|
|
519
|
+
const context = options.context ?? {};
|
|
520
|
+
const scope = options.scope ?? 'project';
|
|
521
|
+
if (!(options.assets ?? []).some((asset ) => asset.id === HOOKS_ASSET_ID)) return { changes: [], conflicts: [], prerequisites: [], notices: [] };
|
|
522
|
+
const paths = (impl.nativePaths ?? singleton.nativePaths)({ ...options, scope, homeDir: context.homeDir });
|
|
523
|
+
const doors = planHooks({ paths, scope, neutralResources: ledgerResources(options), removing: false, repoRoot: context.repoRoot, fsImpl });
|
|
524
|
+
return { changes: doors.changes, conflicts: doors.conflicts, prerequisites: [], notices: [] };
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function verifyHookDoors(options = {}, impl = {}) {
|
|
528
|
+
const fsImpl = impl.fsImpl || fs;
|
|
529
|
+
const context = options.context ?? {};
|
|
530
|
+
const scope = options.scope ?? 'project';
|
|
531
|
+
if (scope !== 'project' || !(options.assets ?? []).some((asset ) => asset.id === HOOKS_ASSET_ID)) return { ok: true, statuses: [], resources: [], conflicts: [] };
|
|
532
|
+
const paths = (impl.nativePaths ?? singleton.nativePaths)({ ...options, scope, homeDir: context.homeDir });
|
|
533
|
+
const doors = verifyHooks({ options, paths, context, fsImpl });
|
|
534
|
+
const conflicts = doors.statuses.filter((status ) => status.status === 'conflict').map((status ) => status.reason ?? status.identity);
|
|
535
|
+
return { ok: conflicts.length === 0, ...doors, conflicts };
|
|
536
|
+
}
|
|
537
|
+
|
|
452
538
|
function apply(options = {}, impl = {}) {
|
|
453
539
|
const fsImpl = impl.fsImpl || fs;
|
|
454
540
|
// apply()/verify() are reached through the lifecycle with the same scope inputs plan() saw, so
|
|
@@ -460,14 +546,26 @@ function apply(options = {}, impl = {}) {
|
|
|
460
546
|
|
|
461
547
|
for (const change of changes.filter((c ) => c.projection?.renderer === 'antigravity-instructions')) {
|
|
462
548
|
if (change.operation === 'remove') {
|
|
463
|
-
// pi precedent: strip only the managed span; the file survives even when nothing remains.
|
|
464
549
|
if (!fsImpl.existsSync(change.target)) continue;
|
|
550
|
+
// The global file is the person's: the span goes with the one newline put before it, so their
|
|
551
|
+
// bytes come back exactly (and a file that held only the span goes with it). A kept file taken
|
|
552
|
+
// over from the retired harness may still hold that harness's span, under its short marker.
|
|
553
|
+
if ((options.scope ?? 'project') === 'global') { removeMarkedSection(change.target, { startMarkers: [MARKER_START, PREDECESSOR_MARKER_START] }); continue; }
|
|
554
|
+
// pi precedent: strip only the managed span; the file survives even when nothing remains.
|
|
465
555
|
const next = strippedInstruction(fsImpl.readFileSync(change.target, 'utf8'));
|
|
466
556
|
if (next !== null) fsImpl.writeFileSync(change.target, next, 'utf8');
|
|
467
557
|
continue;
|
|
468
558
|
}
|
|
559
|
+
// One rename onto the file: no reader, and no failure, ever sees it without its DoFlow span.
|
|
469
560
|
fsImpl.mkdirSync(path.dirname(change.target), { recursive: true });
|
|
470
|
-
|
|
561
|
+
const tmp = `${change.target}.${process.pid}.tmp`;
|
|
562
|
+
try {
|
|
563
|
+
fsImpl.writeFileSync(tmp, change._content ?? render({ content: '' }), 'utf8');
|
|
564
|
+
fsImpl.renameSync(tmp, change.target);
|
|
565
|
+
} catch (error) {
|
|
566
|
+
fsImpl.rmSync(tmp, { force: true });
|
|
567
|
+
throw error;
|
|
568
|
+
}
|
|
471
569
|
}
|
|
472
570
|
for (const change of changes.filter((c ) => c.projection?.renderer === 'antigravity-hooks')) {
|
|
473
571
|
if (change.kind === 'copy-tree-file') continue; // handled by runTreeChanges below
|
|
@@ -506,6 +604,60 @@ function remove(options = {}, impl = {}) {
|
|
|
506
604
|
return apply(options, impl);
|
|
507
605
|
}
|
|
508
606
|
|
|
607
|
+
/** The hook shims' bytes and the registered groups (project scope), as statuses and resources. */
|
|
608
|
+
function verifyHooks({ options, paths, context, fsImpl } ) {
|
|
609
|
+
const statuses = [];
|
|
610
|
+
const resources = [];
|
|
611
|
+
const hooksTarget = paths.hooksJson;
|
|
612
|
+
const scriptTargets = {
|
|
613
|
+
'pre-implementation-gate.sh': paths.hookScript,
|
|
614
|
+
'stop-check.sh': paths.stopHookScript,
|
|
615
|
+
};
|
|
616
|
+
// Source-side residue: reads the shims from THIS checkout (the authored source of the
|
|
617
|
+
// projection, not an install destination — the destination is declared as the paths above).
|
|
618
|
+
const scriptSourceDir = path.join(path.resolve(registryRepoRoot(options)), 'core', 'harnesses', 'antigravity', 'hooks');
|
|
619
|
+
const removingOp = (context.operation ?? options.operation ?? '') === 'remove';
|
|
620
|
+
const fingerprints = {};
|
|
621
|
+
let scriptsOk = true;
|
|
622
|
+
let anyPresent = false;
|
|
623
|
+
for (const identity of HOOK_SCRIPTS) {
|
|
624
|
+
let sourceFp = null;
|
|
625
|
+
try { sourceFp = sha256File(fsImpl, path.join(scriptSourceDir, identity)); } catch { /* checkout without that shim */ }
|
|
626
|
+
fingerprints[identity] = sourceFp;
|
|
627
|
+
const target = scriptTargets[identity];
|
|
628
|
+
const current = fsImpl.existsSync(target) ? sha256File(fsImpl, target) : null;
|
|
629
|
+
if (current !== null) anyPresent = true;
|
|
630
|
+
if (current === null || current !== sourceFp) scriptsOk = false;
|
|
631
|
+
}
|
|
632
|
+
const doc = readJsonObject(hooksTarget, { fsImpl });
|
|
633
|
+
const gate = doc?.[HOOKS_GROUP];
|
|
634
|
+
const stop = doc?.[STOP_HOOKS_GROUP];
|
|
635
|
+
const gateOk = Boolean(gate?.PreToolUse?.[0]?.hooks?.[0]?.command)
|
|
636
|
+
&& gate.PreToolUse[0].hooks[0].command === scriptTargets['pre-implementation-gate.sh']
|
|
637
|
+
&& gate.PreToolUse[0].matcher === GATE_MATCHER;
|
|
638
|
+
// Stop registration is matcher-free: handlers sit directly under the event key.
|
|
639
|
+
const stopOk = Array.isArray(stop?.Stop) && stop.Stop.length > 0
|
|
640
|
+
&& stop.Stop[0]?.command === scriptTargets['stop-check.sh'];
|
|
641
|
+
const groupsOk = gateOk && stopOk;
|
|
642
|
+
statuses.push({ assetId: HOOKS_ASSET_ID, capability: 'hooks', status:
|
|
643
|
+
removingOp ? (!anyPresent && !groupsOk ? 'absent' : 'retained')
|
|
644
|
+
: (scriptsOk && groupsOk ? 'managed' : (!anyPresent && !groupsOk ? 'absent' : 'missing')),
|
|
645
|
+
ownershipIdentity: `${HARNESS}:hooks:registration`, target: hooksTarget });
|
|
646
|
+
if (!removingOp && scriptsOk && groupsOk) {
|
|
647
|
+
resources.push({ assetId: HOOKS_ASSET_ID, target: hooksTarget,
|
|
648
|
+
ownershipIdentity: `${HARNESS}:hooks:registration`, kind: 'hooks-json',
|
|
649
|
+
fingerprint: fingerprint(JSON.stringify(doc)), sourceVersion: 'registry-v1',
|
|
650
|
+
projection: { renderer: 'antigravity-hooks' } });
|
|
651
|
+
for (const identity of HOOK_SCRIPTS) {
|
|
652
|
+
resources.push({ assetId: HOOKS_ASSET_ID, target: scriptTargets[identity],
|
|
653
|
+
ownershipIdentity: `${HARNESS}:copy-tree:${HOOKS_ASSET_ID}:${identity}`,
|
|
654
|
+
kind: 'copy-tree-file', identity, fingerprint: fingerprints[identity],
|
|
655
|
+
sourceVersion: 'registry-v1', projection: { renderer: 'antigravity-hooks' } });
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return { statuses, resources };
|
|
659
|
+
}
|
|
660
|
+
|
|
509
661
|
function verify(options = {}, impl = {}) {
|
|
510
662
|
const fsImpl = impl.fsImpl || fs;
|
|
511
663
|
const context = options.context ?? {};
|
|
@@ -515,24 +667,28 @@ function verify(options = {}, impl = {}) {
|
|
|
515
667
|
const statuses = [];
|
|
516
668
|
const resources = [];
|
|
517
669
|
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
const
|
|
521
|
-
|
|
670
|
+
const instructionFile = instructionTarget({ paths, assets: options.assets, registry: options.registry });
|
|
671
|
+
const state = instructionState({ target: instructionFile, context, resources: ledgerResources(options), paths, fsImpl });
|
|
672
|
+
const instruction = instructionFile && fsImpl.existsSync(instructionFile)
|
|
673
|
+
? fsImpl.readFileSync(instructionFile, 'utf8') : null;
|
|
674
|
+
const managed = instruction !== null && instruction.includes(MARKER_END)
|
|
675
|
+
&& (instruction.includes(MARKER_START) || (state.predecessor && instruction.includes(PREDECESSOR_MARKER_START)));
|
|
676
|
+
// A kept, person-edited file (IC-007) is owned as it is now, markers or not: an edit can drop the
|
|
677
|
+
// span, and without its row the next run would see no owner and append the section unasked.
|
|
678
|
+
const kept = !removing && state.retained && instruction !== null;
|
|
679
|
+
if (instructionFile) {
|
|
522
680
|
// Removal verification asks "did our section go away?"; install/update asks "is it managed?".
|
|
523
681
|
statuses.push({
|
|
524
682
|
assetId: POINTER_ASSET_ID, capability: 'instructions',
|
|
525
|
-
status: removing ? (managed ? 'retained' : 'absent') : (managed ? 'managed' : 'missing'),
|
|
526
|
-
target:
|
|
683
|
+
status: removing ? (managed ? 'retained' : 'absent') : (managed ? 'managed' : (kept ? 'retained' : 'missing')),
|
|
684
|
+
target: instructionFile,
|
|
527
685
|
});
|
|
528
|
-
if (
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
ownershipIdentity: `doflow:${HARNESS}:instructions:managed-section`,
|
|
532
|
-
kind: 'instructions-section', identity: 'AGENTS.md',
|
|
686
|
+
if (!removing && (managed || kept)) {
|
|
687
|
+
// Recorded with the file as it is now; a kept one is flagged so later runs keep it until --force.
|
|
688
|
+
resources.push(instructionsChange(instructionFile, {
|
|
533
689
|
fingerprint: fingerprint(instruction), sourceVersion: 'registry-v1',
|
|
534
|
-
|
|
535
|
-
});
|
|
690
|
+
...(state.retained ? { retainedEdit: true } : {}),
|
|
691
|
+
}));
|
|
536
692
|
}
|
|
537
693
|
}
|
|
538
694
|
|
|
@@ -540,7 +696,7 @@ function verify(options = {}, impl = {}) {
|
|
|
540
696
|
const destDir = treeDestFor(asset, paths, scope);
|
|
541
697
|
if (!destDir) continue;
|
|
542
698
|
const sourceDir = sourceDirFor(asset, { repoRoot: context.repoRoot }, fsImpl, HARNESS);
|
|
543
|
-
const result = verifyTree({ sourceDir, destDir, fsImpl, layout: asset.layout, plannedWrites: context.plannedWrites });
|
|
699
|
+
const result = verifyTree({ sourceDir, destDir, fsImpl, layout: asset.layout, transform: asset.transform, select: asset.select, plannedWrites: context.plannedWrites });
|
|
544
700
|
conflictsToStatuses(result.conflicts, asset.id, statuses);
|
|
545
701
|
for (const resource of result.resources) {
|
|
546
702
|
resources.push({
|
|
@@ -563,54 +719,10 @@ function verify(options = {}, impl = {}) {
|
|
|
563
719
|
resources.push(...mcp.resources);
|
|
564
720
|
|
|
565
721
|
// Hooks projection (project scope): the shims' bytes and the registered groups.
|
|
566
|
-
if (scope === 'project') {
|
|
567
|
-
const
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
'stop-check.sh': paths.stopHookScript,
|
|
571
|
-
};
|
|
572
|
-
// Source-side residue: reads the shims from THIS checkout (the authored source of the
|
|
573
|
-
// projection, not an install destination — the destination is declared as the paths above).
|
|
574
|
-
const scriptSourceDir = path.join(path.resolve(registryRepoRoot(options)), 'core', 'harnesses', 'antigravity', 'hooks');
|
|
575
|
-
const removingOp = (context.operation ?? options.operation ?? '') === 'remove';
|
|
576
|
-
const fingerprints = {};
|
|
577
|
-
let scriptsOk = true;
|
|
578
|
-
let anyPresent = false;
|
|
579
|
-
for (const identity of HOOK_SCRIPTS) {
|
|
580
|
-
let sourceFp = null;
|
|
581
|
-
try { sourceFp = sha256File(fsImpl, path.join(scriptSourceDir, identity)); } catch { /* checkout without that shim */ }
|
|
582
|
-
fingerprints[identity] = sourceFp;
|
|
583
|
-
const target = scriptTargets[identity];
|
|
584
|
-
const current = fsImpl.existsSync(target) ? sha256File(fsImpl, target) : null;
|
|
585
|
-
if (current !== null) anyPresent = true;
|
|
586
|
-
if (current === null || current !== sourceFp) scriptsOk = false;
|
|
587
|
-
}
|
|
588
|
-
const doc = readJsonObject(hooksTarget, { fsImpl });
|
|
589
|
-
const gate = doc?.[HOOKS_GROUP];
|
|
590
|
-
const stop = doc?.[STOP_HOOKS_GROUP];
|
|
591
|
-
const gateOk = Boolean(gate?.PreToolUse?.[0]?.hooks?.[0]?.command)
|
|
592
|
-
&& gate.PreToolUse[0].hooks[0].command === scriptTargets['pre-implementation-gate.sh']
|
|
593
|
-
&& gate.PreToolUse[0].matcher === GATE_MATCHER;
|
|
594
|
-
// Stop registration is matcher-free: handlers sit directly under the event key.
|
|
595
|
-
const stopOk = Array.isArray(stop?.Stop) && stop.Stop.length > 0
|
|
596
|
-
&& stop.Stop[0]?.command === scriptTargets['stop-check.sh'];
|
|
597
|
-
const groupsOk = gateOk && stopOk;
|
|
598
|
-
statuses.push({ assetId: HOOKS_ASSET_ID, capability: 'hooks', status:
|
|
599
|
-
removingOp ? (!anyPresent && !groupsOk ? 'absent' : 'retained')
|
|
600
|
-
: (scriptsOk && groupsOk ? 'managed' : (!anyPresent && !groupsOk ? 'absent' : 'missing')),
|
|
601
|
-
ownershipIdentity: `${HARNESS}:hooks:registration`, target: hooksTarget });
|
|
602
|
-
if (!removingOp && scriptsOk && groupsOk) {
|
|
603
|
-
resources.push({ assetId: HOOKS_ASSET_ID, target: hooksTarget,
|
|
604
|
-
ownershipIdentity: `${HARNESS}:hooks:registration`, kind: 'hooks-json',
|
|
605
|
-
fingerprint: fingerprint(JSON.stringify(doc)), sourceVersion: 'registry-v1',
|
|
606
|
-
projection: { renderer: 'antigravity-hooks' } });
|
|
607
|
-
for (const identity of HOOK_SCRIPTS) {
|
|
608
|
-
resources.push({ assetId: HOOKS_ASSET_ID, target: scriptTargets[identity],
|
|
609
|
-
ownershipIdentity: `${HARNESS}:copy-tree:${HOOKS_ASSET_ID}:${identity}`,
|
|
610
|
-
kind: 'copy-tree-file', identity, fingerprint: fingerprints[identity],
|
|
611
|
-
sourceVersion: 'registry-v1', projection: { renderer: 'antigravity-hooks' } });
|
|
612
|
-
}
|
|
613
|
-
}
|
|
722
|
+
if (scope === 'project' && context.hooksOff !== true) {
|
|
723
|
+
const hooks = verifyHooks({ options, paths, context, fsImpl });
|
|
724
|
+
statuses.push(...hooks.statuses);
|
|
725
|
+
resources.push(...hooks.resources);
|
|
614
726
|
}
|
|
615
727
|
|
|
616
728
|
const conflicts = [...statuses.filter((s) => s.status === 'conflict').map((s) => s.reason ?? s.identity), ...mcp.conflicts];
|
|
@@ -627,5 +739,6 @@ function conflictsToStatuses(conflicts , assetId , statuses ) {
|
|
|
627
739
|
|
|
628
740
|
module.exports = {
|
|
629
741
|
HARNESS, nativePaths: singleton.nativePaths, discover, render, plan, apply, remove, verify,
|
|
742
|
+
planHookDoors: singleton.planHookDoors, verifyHookDoors: singleton.verifyHookDoors,
|
|
630
743
|
createAntigravityAdapter,
|
|
631
744
|
};
|