zob-harness 0.1.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/.pi/adapters/registry.json +103 -0
- package/.pi/agents/architecture-cartographer.md +53 -0
- package/.pi/agents/chief-vision.md +39 -0
- package/.pi/agents/clarifier.md +58 -0
- package/.pi/agents/context-steward.md +52 -0
- package/.pi/agents/doc-steward.md +34 -0
- package/.pi/agents/explore.md +49 -0
- package/.pi/agents/factory.md +41 -0
- package/.pi/agents/implementer.md +44 -0
- package/.pi/agents/librarian.md +32 -0
- package/.pi/agents/oracle-merge.md +50 -0
- package/.pi/agents/oracle.md +55 -0
- package/.pi/agents/pattern-miner.md +53 -0
- package/.pi/agents/planner.md +39 -0
- package/.pi/agents/project-dna-golden-evaluator.md +32 -0
- package/.pi/agents/project-dna-ontology-steward.md +30 -0
- package/.pi/agents/project-dna-oracle.md +56 -0
- package/.pi/agents/project-dna-orchestrator.md +60 -0
- package/.pi/agents/project-dna-query-steward.md +38 -0
- package/.pi/agents/project-dna-safety-preflight.md +54 -0
- package/.pi/agents/project-dna-test-linker.md +27 -0
- package/.pi/agents/qa.md +38 -0
- package/.pi/agents/refactor-cartographer.md +28 -0
- package/.pi/agents/refactor-mover.md +31 -0
- package/.pi/agents/refactor-oracle.md +49 -0
- package/.pi/agents/repo-scout.md +60 -0
- package/.pi/agents/sample-architect.md +48 -0
- package/.pi/agents/specifier.md +57 -0
- package/.pi/agents/symbol-range-curator.md +41 -0
- package/.pi/agents/synthesis.md +52 -0
- package/.pi/agents/temp-agent-creator.md +35 -0
- package/.pi/autonomy-policy.json +67 -0
- package/.pi/budget-policy.json +54 -0
- package/.pi/capabilities/zob-public-runtime-capabilities.json +1700 -0
- package/.pi/chains/explore-plan-oracle.json +78 -0
- package/.pi/chains/explore-spec-clarify-plan-oracle.json +64 -0
- package/.pi/chains/explore-spec-plan-oracle.json +53 -0
- package/.pi/chains/spec-clarify-plan-oracle.json +53 -0
- package/.pi/chains/spec-factory-oracle.json +42 -0
- package/.pi/chains/spec-plan-oracle.json +42 -0
- package/.pi/compute-profiles/defaults.json +19 -0
- package/.pi/compute-profiles/overrides.json +13 -0
- package/.pi/compute-profiles/risk-rules.json +16 -0
- package/.pi/daemon-policy.json +80 -0
- package/.pi/damage-control-rules.json +45 -0
- package/.pi/extensions/zob-child-safety/index.ts +212 -0
- package/.pi/extensions/zob-harness/AGENTS.md +28 -0
- package/.pi/extensions/zob-harness/index.ts +391 -0
- package/.pi/extensions/zob-harness/src/AGENTS.md +25 -0
- package/.pi/extensions/zob-harness/src/agents.ts +82 -0
- package/.pi/extensions/zob-harness/src/autonomous-runtime.ts +2912 -0
- package/.pi/extensions/zob-harness/src/autonomy-readiness.ts +778 -0
- package/.pi/extensions/zob-harness/src/budget-policy.ts +308 -0
- package/.pi/extensions/zob-harness/src/capabilities.ts +249 -0
- package/.pi/extensions/zob-harness/src/child-runner.ts +249 -0
- package/.pi/extensions/zob-harness/src/chronicle.ts +262 -0
- package/.pi/extensions/zob-harness/src/compute-profile.ts +602 -0
- package/.pi/extensions/zob-harness/src/compute-workflow-shape.ts +168 -0
- package/.pi/extensions/zob-harness/src/coms-v2/AGENTS.md +16 -0
- package/.pi/extensions/zob-harness/src/coms-v2/envelope.ts +121 -0
- package/.pi/extensions/zob-harness/src/coms-v2/identity.ts +53 -0
- package/.pi/extensions/zob-harness/src/coms-v2/ledger-bridge.ts +67 -0
- package/.pi/extensions/zob-harness/src/coms-v2/local-transport.ts +147 -0
- package/.pi/extensions/zob-harness/src/coms-v2/pending-replies.ts +80 -0
- package/.pi/extensions/zob-harness/src/coms-v2/policy.ts +125 -0
- package/.pi/extensions/zob-harness/src/coms-v2/presence.ts +55 -0
- package/.pi/extensions/zob-harness/src/coms-v2/registry.ts +113 -0
- package/.pi/extensions/zob-harness/src/coms-v2/response-capture.ts +50 -0
- package/.pi/extensions/zob-harness/src/coms-v2/transcript-capture.ts +164 -0
- package/.pi/extensions/zob-harness/src/coms-v2/types.ts +149 -0
- package/.pi/extensions/zob-harness/src/coms-v2/zpeer-profile.ts +140 -0
- package/.pi/extensions/zob-harness/src/coms-v2/zpeer.ts +452 -0
- package/.pi/extensions/zob-harness/src/constants.ts +108 -0
- package/.pi/extensions/zob-harness/src/context-gbrain.ts +465 -0
- package/.pi/extensions/zob-harness/src/daemon-policy.ts +223 -0
- package/.pi/extensions/zob-harness/src/daemon-readiness.ts +134 -0
- package/.pi/extensions/zob-harness/src/daemon-runtime.ts +393 -0
- package/.pi/extensions/zob-harness/src/factory/AGENTS.md +24 -0
- package/.pi/extensions/zob-harness/src/factory/agentic-plan.ts +65 -0
- package/.pi/extensions/zob-harness/src/factory/quarantine.ts +319 -0
- package/.pi/extensions/zob-harness/src/factory/run.ts +520 -0
- package/.pi/extensions/zob-harness/src/factory/validation.ts +454 -0
- package/.pi/extensions/zob-harness/src/factory-selector.ts +318 -0
- package/.pi/extensions/zob-harness/src/full-autonomy-test.ts +226 -0
- package/.pi/extensions/zob-harness/src/git-ops.ts +868 -0
- package/.pi/extensions/zob-harness/src/goal-room.ts +178 -0
- package/.pi/extensions/zob-harness/src/goal-runtime.ts +1569 -0
- package/.pi/extensions/zob-harness/src/goal-todo-imports.ts +111 -0
- package/.pi/extensions/zob-harness/src/goal-todo-types.ts +231 -0
- package/.pi/extensions/zob-harness/src/goal-todos.ts +1410 -0
- package/.pi/extensions/zob-harness/src/goal.ts +152 -0
- package/.pi/extensions/zob-harness/src/governed-requests.ts +436 -0
- package/.pi/extensions/zob-harness/src/interactive-autonomy.ts +595 -0
- package/.pi/extensions/zob-harness/src/launch-apply.ts +313 -0
- package/.pi/extensions/zob-harness/src/merge-queue.ts +290 -0
- package/.pi/extensions/zob-harness/src/mission-control.ts +573 -0
- package/.pi/extensions/zob-harness/src/model-availability.ts +52 -0
- package/.pi/extensions/zob-harness/src/model-routing.ts +429 -0
- package/.pi/extensions/zob-harness/src/orchestration/AGENTS.md +23 -0
- package/.pi/extensions/zob-harness/src/orchestration/adaptive-delegation.ts +547 -0
- package/.pi/extensions/zob-harness/src/orchestration/adaptive-workflow.ts +585 -0
- package/.pi/extensions/zob-harness/src/orchestration/lead-plan.ts +192 -0
- package/.pi/extensions/zob-harness/src/orchestration/plan.ts +168 -0
- package/.pi/extensions/zob-harness/src/orchestration/room.ts +346 -0
- package/.pi/extensions/zob-harness/src/orchestration/run.ts +134 -0
- package/.pi/extensions/zob-harness/src/orchestration/supervised-readonly.ts +1147 -0
- package/.pi/extensions/zob-harness/src/orchestration/widget-readers.ts +132 -0
- package/.pi/extensions/zob-harness/src/output-contracts.ts +656 -0
- package/.pi/extensions/zob-harness/src/project-dna.ts +533 -0
- package/.pi/extensions/zob-harness/src/promotion/AGENTS.md +24 -0
- package/.pi/extensions/zob-harness/src/promotion/candidate.ts +336 -0
- package/.pi/extensions/zob-harness/src/promotion/coms.ts +127 -0
- package/.pi/extensions/zob-harness/src/promotion/documentation.ts +142 -0
- package/.pi/extensions/zob-harness/src/promotion/factory.ts +107 -0
- package/.pi/extensions/zob-harness/src/promotion/ledger.ts +2 -0
- package/.pi/extensions/zob-harness/src/promotion/temp-agent.ts +151 -0
- package/.pi/extensions/zob-harness/src/promotion/types.ts +149 -0
- package/.pi/extensions/zob-harness/src/promotion/validate.ts +6 -0
- package/.pi/extensions/zob-harness/src/promotion/write-lane.ts +162 -0
- package/.pi/extensions/zob-harness/src/prompt-packs.ts +239 -0
- package/.pi/extensions/zob-harness/src/queue.ts +386 -0
- package/.pi/extensions/zob-harness/src/rules.ts +225 -0
- package/.pi/extensions/zob-harness/src/runtime/AGENTS.md +26 -0
- package/.pi/extensions/zob-harness/src/runtime/adaptive-zmode.ts +116 -0
- package/.pi/extensions/zob-harness/src/runtime/auto-compaction.ts +715 -0
- package/.pi/extensions/zob-harness/src/runtime/commands.ts +1315 -0
- package/.pi/extensions/zob-harness/src/runtime/compaction-policy.ts +516 -0
- package/.pi/extensions/zob-harness/src/runtime/delegation-click-markers.ts +141 -0
- package/.pi/extensions/zob-harness/src/runtime/delegation-feed.ts +415 -0
- package/.pi/extensions/zob-harness/src/runtime/delegation-markdown.ts +97 -0
- package/.pi/extensions/zob-harness/src/runtime/delegation-monitor.ts +553 -0
- package/.pi/extensions/zob-harness/src/runtime/delegation-mouse.ts +205 -0
- package/.pi/extensions/zob-harness/src/runtime/delegation-overlay.ts +434 -0
- package/.pi/extensions/zob-harness/src/runtime/events.ts +736 -0
- package/.pi/extensions/zob-harness/src/runtime/goal-todo-overlay.ts +214 -0
- package/.pi/extensions/zob-harness/src/runtime/mode-intent.ts +144 -0
- package/.pi/extensions/zob-harness/src/runtime/plan-capture.ts +270 -0
- package/.pi/extensions/zob-harness/src/runtime/state.ts +403 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-autonomous.ts +117 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-compute.ts +136 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-coms.ts +365 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-context.ts +70 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-delegation.ts +1854 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-factory.ts +810 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-goal-room.ts +46 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-governed-requests.ts +38 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-merge-queue.ts +61 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-mission-control.ts +77 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-orchestration.ts +106 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-project-dna.ts +123 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-worker-pool.ts +93 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-workspace-claims.ts +62 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-zcommit.ts +147 -0
- package/.pi/extensions/zob-harness/src/runtime/widget.ts +353 -0
- package/.pi/extensions/zob-harness/src/runtime/zobHarness.ts +60 -0
- package/.pi/extensions/zob-harness/src/safety.ts +338 -0
- package/.pi/extensions/zob-harness/src/sandbox.ts +1508 -0
- package/.pi/extensions/zob-harness/src/schemas-project-dna.ts +47 -0
- package/.pi/extensions/zob-harness/src/schemas.ts +695 -0
- package/.pi/extensions/zob-harness/src/telemetry.ts +373 -0
- package/.pi/extensions/zob-harness/src/topology/AGENTS.md +22 -0
- package/.pi/extensions/zob-harness/src/topology/chains.ts +236 -0
- package/.pi/extensions/zob-harness/src/topology/coms.ts +211 -0
- package/.pi/extensions/zob-harness/src/topology/orchestration-profiles.ts +204 -0
- package/.pi/extensions/zob-harness/src/topology/teams.ts +113 -0
- package/.pi/extensions/zob-harness/src/types/core.ts +47 -0
- package/.pi/extensions/zob-harness/src/types.ts +939 -0
- package/.pi/extensions/zob-harness/src/utils/AGENTS.md +22 -0
- package/.pi/extensions/zob-harness/src/utils/formatting.ts +34 -0
- package/.pi/extensions/zob-harness/src/utils/hashing.ts +11 -0
- package/.pi/extensions/zob-harness/src/utils/json.ts +28 -0
- package/.pi/extensions/zob-harness/src/utils/paths.ts +54 -0
- package/.pi/extensions/zob-harness/src/utils/records.ts +25 -0
- package/.pi/extensions/zob-harness/src/utils/resources.ts +38 -0
- package/.pi/extensions/zob-harness/src/worker-pool.ts +672 -0
- package/.pi/extensions/zob-harness/src/workspace-claims.ts +297 -0
- package/.pi/extensions/zob-switch/index.ts +180 -0
- package/.pi/factories/budget-preflight-dry-run/batch-manifest.json +59 -0
- package/.pi/factories/budget-preflight-dry-run/factory.json +94 -0
- package/.pi/factories/budget-preflight-dry-run/pilot-manifest.json +50 -0
- package/.pi/factories/budget-preflight-dry-run/smoke-manifest.json +43 -0
- package/.pi/factories/code-review-matrix/batch-manifest.json +61 -0
- package/.pi/factories/code-review-matrix/factory.json +163 -0
- package/.pi/factories/code-review-matrix/pilot-manifest.json +41 -0
- package/.pi/factories/code-review-matrix/smoke-manifest.json +35 -0
- package/.pi/factories/factory-forge/batch-manifest.json +56 -0
- package/.pi/factories/factory-forge/factory.json +84 -0
- package/.pi/factories/factory-forge/pilot-manifest.json +32 -0
- package/.pi/factories/factory-forge/smoke-manifest.json +19 -0
- package/.pi/factories/opencode-pattern-canonizer/batch-manifest.json +54 -0
- package/.pi/factories/opencode-pattern-canonizer/factory.json +86 -0
- package/.pi/factories/opencode-pattern-canonizer/pilot-manifest.json +39 -0
- package/.pi/factories/opencode-pattern-canonizer/smoke-manifest.json +26 -0
- package/.pi/factories/project-dna/README.md +182 -0
- package/.pi/factories/project-dna/batch-manifest.json +37 -0
- package/.pi/factories/project-dna/example-project-dna-manifest-v2.json +80 -0
- package/.pi/factories/project-dna/example-project-dna-manifest.json +58 -0
- package/.pi/factories/project-dna/factory.json +131 -0
- package/.pi/factories/project-dna/golden-cases-smoke.json +62 -0
- package/.pi/factories/project-dna/pi-agentic-ontology.json +88 -0
- package/.pi/factories/project-dna/pilot-manifest.json +32 -0
- package/.pi/factories/project-dna/schemas/benchmark-suite.schema.json +27 -0
- package/.pi/factories/project-dna/schemas/code-knowledge-graph.schema.json +97 -0
- package/.pi/factories/project-dna/schemas/context-pack.schema.json +43 -0
- package/.pi/factories/project-dna/schemas/golden-case.schema.json +36 -0
- package/.pi/factories/project-dna/schemas/manifest-v2.schema.json +128 -0
- package/.pi/factories/project-dna/schemas/manifest.schema.json +77 -0
- package/.pi/factories/project-dna/schemas/ontology.schema.json +45 -0
- package/.pi/factories/project-dna/schemas/project-fingerprint.schema.json +28 -0
- package/.pi/factories/project-dna/schemas/query-steward-report.schema.json +52 -0
- package/.pi/factories/project-dna/smoke-manifest.json +27 -0
- package/.pi/factories/roadmap-smoke-lots/batch-manifest.json +49 -0
- package/.pi/factories/roadmap-smoke-lots/factory.json +89 -0
- package/.pi/factories/roadmap-smoke-lots/pilot-manifest.json +50 -0
- package/.pi/factories/roadmap-smoke-lots/smoke-manifest.json +35 -0
- package/.pi/git-policy.json +120 -0
- package/.pi/mission-control/zob_coms_transport.json +64 -0
- package/.pi/model-catalog.example.json +345 -0
- package/.pi/model-economy.example.json +196 -0
- package/.pi/model-routing.json +86 -0
- package/.pi/orchestrations/adaptive-chief-vision.json +193 -0
- package/.pi/orchestrations/ceo-feature-build.json +182 -0
- package/.pi/orchestrations/readonly-dynamic-smoke.json +75 -0
- package/.pi/output-contracts/agent-event.v1.json +19 -0
- package/.pi/output-contracts/base.v1.json +24 -0
- package/.pi/output-contracts/brain-lookup.v1.json +21 -0
- package/.pi/output-contracts/clarification.v1.json +21 -0
- package/.pi/output-contracts/context-pack.v1.json +20 -0
- package/.pi/output-contracts/context-request.v1.json +21 -0
- package/.pi/output-contracts/context-steward.v1.json +19 -0
- package/.pi/output-contracts/context-writeback-proposal.v1.json +18 -0
- package/.pi/output-contracts/delegation-request.v1.json +21 -0
- package/.pi/output-contracts/explore.v1.json +52 -0
- package/.pi/output-contracts/factory.v1.json +48 -0
- package/.pi/output-contracts/guidance-steward.v1.json +18 -0
- package/.pi/output-contracts/implement.v1.json +40 -0
- package/.pi/output-contracts/launch-authorization.v1.json +21 -0
- package/.pi/output-contracts/lead-plan.v1.json +22 -0
- package/.pi/output-contracts/mission-readiness.v1.json +20 -0
- package/.pi/output-contracts/oracle-merge.v1.json +44 -0
- package/.pi/output-contracts/oracle-request.v1.json +20 -0
- package/.pi/output-contracts/oracle.v1.json +44 -0
- package/.pi/output-contracts/orchestration-profile.v1.json +22 -0
- package/.pi/output-contracts/plan.v1.json +48 -0
- package/.pi/output-contracts/prompt-pack.v1.json +20 -0
- package/.pi/output-contracts/qa.v1.json +40 -0
- package/.pi/output-contracts/research.v1.json +36 -0
- package/.pi/output-contracts/spec.v1.json +22 -0
- package/.pi/output-contracts/synthesis.v1.json +44 -0
- package/.pi/output-contracts/temp-agent-card.v1.json +23 -0
- package/.pi/output-contracts/todo-child-result.v1.json +20 -0
- package/.pi/output-contracts/todo-child-result.v2.json +22 -0
- package/.pi/output-contracts/todo-claim-validation.v1.json +22 -0
- package/.pi/output-contracts/todo-split-request.v1.json +20 -0
- package/.pi/prompts/adaptive-workflow.md +63 -0
- package/.pi/prompts/autonomous-runtime.md +15 -0
- package/.pi/prompts/benchmark-contender.md +15 -0
- package/.pi/prompts/benchmark-judge.md +19 -0
- package/.pi/prompts/clarify-spec.md +20 -0
- package/.pi/prompts/compute-plan.md +36 -0
- package/.pi/prompts/compute-preview.md +42 -0
- package/.pi/prompts/contract.md +29 -0
- package/.pi/prompts/explore.md +13 -0
- package/.pi/prompts/factory-run.md +36 -0
- package/.pi/prompts/factory.md +20 -0
- package/.pi/prompts/implement.md +27 -0
- package/.pi/prompts/model-catalog.md +68 -0
- package/.pi/prompts/model-economy.md +64 -0
- package/.pi/prompts/oracle-merge.md +18 -0
- package/.pi/prompts/oracle.md +13 -0
- package/.pi/prompts/orchestrator.md +48 -0
- package/.pi/prompts/parallel-review.md +21 -0
- package/.pi/prompts/plan.md +21 -0
- package/.pi/prompts/project-dna.md +90 -0
- package/.pi/prompts/refactor-oracle.md +23 -0
- package/.pi/prompts/refactor-slice.md +24 -0
- package/.pi/prompts/research.md +20 -0
- package/.pi/prompts/spec.md +19 -0
- package/.pi/prompts/synthesis.md +18 -0
- package/.pi/rules/always.md +38 -0
- package/.pi/rules/docs.md +32 -0
- package/.pi/rules/factory.md +44 -0
- package/.pi/rules/oracle.md +34 -0
- package/.pi/rules/orchestration.md +44 -0
- package/.pi/rules/project.md +34 -0
- package/.pi/rules/prompts.md +43 -0
- package/.pi/rules/runtime.md +43 -0
- package/.pi/rules/sandbox.md +43 -0
- package/.pi/settings.json +28 -0
- package/.pi/skills/zob-agentic-access/SKILL.md +20 -0
- package/.pi/skills/zob-autonomous-runtime/SKILL.md +41 -0
- package/.pi/skills/zob-commit/SKILL.md +79 -0
- package/.pi/skills/zob-compaction-policy/SKILL.md +92 -0
- package/.pi/skills/zob-compute-profile/SKILL.md +108 -0
- package/.pi/skills/zob-coms-safety/SKILL.md +54 -0
- package/.pi/skills/zob-coms-v2-live/SKILL.md +47 -0
- package/.pi/skills/zob-delegation-routing/SKILL.md +82 -0
- package/.pi/skills/zob-factory/SKILL.md +28 -0
- package/.pi/skills/zob-goal-todo-tree/SKILL.md +279 -0
- package/.pi/skills/zob-harness/SKILL.md +68 -0
- package/.pi/skills/zob-mission-control-coms/SKILL.md +39 -0
- package/.pi/skills/zob-oracle/SKILL.md +21 -0
- package/.pi/skills/zob-owner-pool-drill-writer/SKILL.md +244 -0
- package/.pi/skills/zob-owner-pool-launcher/SKILL.md +261 -0
- package/.pi/skills/zob-project-dna/SKILL.md +275 -0
- package/.pi/skills/zob-sandbox/SKILL.md +29 -0
- package/.pi/skills/zob-spec/SKILL.md +25 -0
- package/.pi/skills/zob-split-refactor/SKILL.md +39 -0
- package/.pi/skills/zob-tool-router/SKILL.md +104 -0
- package/.pi/teams/zob-core.json +122 -0
- package/AGENTS.md +89 -0
- package/CONTRIBUTING.md +56 -0
- package/LICENSE +21 -0
- package/README.md +360 -0
- package/SECURITY.md +35 -0
- package/SOURCE_INDEX.md +46 -0
- package/package.json +135 -0
- package/scripts/README.md +57 -0
- package/scripts/autonomy/mission-readiness-secret-smoke.mjs +90 -0
- package/scripts/compute-profile/plan-workflow.mjs +85 -0
- package/scripts/compute-profile/preview.mjs +242 -0
- package/scripts/compute-profile/regression-smoke.mjs +38 -0
- package/scripts/compute-profile/summarize.mjs +72 -0
- package/scripts/compute-profile/validate-policy.mjs +50 -0
- package/scripts/compute-profile/validate-preview.mjs +95 -0
- package/scripts/compute-profile/validate-workflow.mjs +58 -0
- package/scripts/git-ops/commit-policy-smoke.mjs +221 -0
- package/scripts/goal-todo/child-goal-ref-smoke.mjs +252 -0
- package/scripts/harness-switch/static-smoke.mjs +43 -0
- package/scripts/model-catalog/validate-economy.mjs +223 -0
- package/scripts/model-catalog/validate.mjs +199 -0
- package/scripts/package-surface/validate-script-refs.mjs +190 -0
- package/scripts/path-policy/validate-smoke.mjs +103 -0
- package/scripts/project-dna/bench-smoke.mjs +217 -0
- package/scripts/project-dna/build-capsules.mjs +207 -0
- package/scripts/project-dna/build-sample-spec.mjs +140 -0
- package/scripts/project-dna/emit-golden-cases.mjs +75 -0
- package/scripts/project-dna/emit-ontology.mjs +75 -0
- package/scripts/project-dna/generate-sample.mjs +302 -0
- package/scripts/project-dna/oracle-review-smoke.mjs +157 -0
- package/scripts/project-dna/plan-workflow.mjs +289 -0
- package/scripts/project-dna/query-context.mjs +276 -0
- package/scripts/project-dna/query-steward.mjs +149 -0
- package/scripts/project-dna/scan.mjs +553 -0
- package/scripts/project-dna/validate-5of5.mjs +159 -0
- package/scripts/project-dna/validate-golden-cases.mjs +78 -0
- package/scripts/project-dna/validate-ontology.mjs +97 -0
- package/scripts/project-dna/validate-sample-project.mjs +105 -0
- package/scripts/project-dna/validate-scaffold.mjs +383 -0
- package/scripts/project-dna/validate-scan-artifacts.mjs +187 -0
- package/scripts/project-dna/validate-workflow.mjs +166 -0
- package/scripts/start-pi.sh +4 -0
- package/scripts/worker-pool/static-smoke.mjs +54 -0
- package/scripts/zpeer-local-e2e-smoke.mjs +395 -0
- package/scripts/zpeer-static-smoke.mjs +129 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { loadProjectAgents } from "../agents.js";
|
|
5
|
+
import { DEFAULT_RULES } from "../constants.js";
|
|
6
|
+
import { validateOutputContractId } from "../output-contracts.js";
|
|
7
|
+
import { normalizeAdaptiveDelegationPolicy, validateAdaptiveDelegationPolicy } from "../orchestration/adaptive-delegation.js";
|
|
8
|
+
import { validateToolList } from "../safety.js";
|
|
9
|
+
import type { FactoryAdaptiveDispatchGate, FactoryAdaptiveDispatchGateInput, FactoryDefinition, FactoryExecutionMode, FactoryInputManifest, FactoryManifestItem, FactoryOracleReview, FactoryRunInput, FactoryStage } from "../types.js";
|
|
10
|
+
import { sha256 } from "../utils/hashing.js";
|
|
11
|
+
import { parseJsonFile } from "../utils/json.js";
|
|
12
|
+
import { isSafeArtifactName, pathMatches, resolveRepoPath, safeFileStem } from "../utils/paths.js";
|
|
13
|
+
import { isRecord } from "../utils/records.js";
|
|
14
|
+
import { readableZobResourcePath } from "../utils/resources.js";
|
|
15
|
+
|
|
16
|
+
function isFactoryManifestItem(value: unknown): value is FactoryManifestItem {
|
|
17
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.path === "string";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isFactoryInputManifest(value: unknown): value is FactoryInputManifest {
|
|
21
|
+
return isRecord(value) && typeof value.factory === "string" && Array.isArray(value.items) && value.items.every(isFactoryManifestItem);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function isFactoryStage(value: unknown): value is FactoryStage {
|
|
25
|
+
return (
|
|
26
|
+
isRecord(value) &&
|
|
27
|
+
typeof value.name === "string" &&
|
|
28
|
+
(value.type === "map" || value.type === "reduce" || value.type === "validate") &&
|
|
29
|
+
typeof value.agent === "string" &&
|
|
30
|
+
typeof value.outputContract === "string" &&
|
|
31
|
+
Array.isArray(value.requiredTools) &&
|
|
32
|
+
value.requiredTools.every((tool) => typeof tool === "string") &&
|
|
33
|
+
typeof value.promptTemplate === "string" &&
|
|
34
|
+
(value.expectedOutcome === undefined || typeof value.expectedOutcome === "string") &&
|
|
35
|
+
(value.context === undefined || typeof value.context === "string") &&
|
|
36
|
+
(value.mustDo === undefined || (Array.isArray(value.mustDo) && value.mustDo.every((item) => typeof item === "string"))) &&
|
|
37
|
+
(value.mustNotDo === undefined || (Array.isArray(value.mustNotDo) && value.mustNotDo.every((item) => typeof item === "string")))
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isFactoryDefinition(value: unknown): value is FactoryDefinition {
|
|
42
|
+
return (
|
|
43
|
+
isRecord(value) &&
|
|
44
|
+
typeof value.name === "string" &&
|
|
45
|
+
typeof value.version === "string" &&
|
|
46
|
+
typeof value.description === "string" &&
|
|
47
|
+
(value.defaultMode === undefined || value.defaultMode === "smoke" || value.defaultMode === "pilot" || value.defaultMode === "batch") &&
|
|
48
|
+
(value.expectedArtifacts === undefined || (Array.isArray(value.expectedArtifacts) && value.expectedArtifacts.every((artifact) => typeof artifact === "string"))) &&
|
|
49
|
+
(value.requiredStages === undefined || (Array.isArray(value.requiredStages) && value.requiredStages.every((stage) => typeof stage === "string"))) &&
|
|
50
|
+
(value.stages === undefined || (Array.isArray(value.stages) && value.stages.every(isFactoryStage)))
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const FACTORY_PHASE_SENTINELS: Record<"smoke" | "pilot" | "batch", string> = {
|
|
55
|
+
smoke: "SMOKE_PASSED.sentinel",
|
|
56
|
+
pilot: "PILOT_PASSED.sentinel",
|
|
57
|
+
batch: "BATCH_PASSED.sentinel",
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export function factoryPhaseSentinelForMode(mode: "smoke" | "pilot" | "batch"): string {
|
|
61
|
+
return FACTORY_PHASE_SENTINELS[mode];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const RESERVED_FACTORY_ARTIFACTS = new Set(["DONE.sentinel", "SMOKE_PASSED.sentinel", "PILOT_PASSED.sentinel", "BATCH_PASSED.sentinel", "validation.json", "manifest.json", "ledger.jsonl", "final-report.md", "agentic-plan.json", "telemetry.json", "checkpoints", "outputs"]);
|
|
65
|
+
|
|
66
|
+
function validateExpectedArtifacts(artifacts: string[] | undefined, source: string): string[] {
|
|
67
|
+
const errors: string[] = [];
|
|
68
|
+
for (const artifact of artifacts ?? []) {
|
|
69
|
+
if (!isSafeArtifactName(artifact)) errors.push(`${source} expected artifact must be a safe basename: ${artifact}`);
|
|
70
|
+
if (RESERVED_FACTORY_ARTIFACTS.has(artifact)) errors.push(`${source} expected artifact uses reserved factory artifact name: ${artifact}`);
|
|
71
|
+
}
|
|
72
|
+
return errors;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const KNOWN_FACTORY_REQUIRED_STAGES = new Set([
|
|
76
|
+
"initialized",
|
|
77
|
+
"manifest_loaded",
|
|
78
|
+
"agentic_plan_written",
|
|
79
|
+
"item_processed",
|
|
80
|
+
"patterns_canonicalized",
|
|
81
|
+
"risks_canonicalized",
|
|
82
|
+
"workflow_rules_written",
|
|
83
|
+
"agent_instructions_written",
|
|
84
|
+
"quality_gates_written",
|
|
85
|
+
"dashboard_summary_written",
|
|
86
|
+
"validation",
|
|
87
|
+
"phase_sentinel",
|
|
88
|
+
"sentinel",
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
function validateFactoryRequiredStages(definition: FactoryDefinition | undefined): string[] {
|
|
92
|
+
const errors: string[] = [];
|
|
93
|
+
const seen = new Set<string>();
|
|
94
|
+
for (const stage of definition?.requiredStages ?? []) {
|
|
95
|
+
if (!isSafeArtifactName(stage)) errors.push(`Factory required stage must be path-safe: ${stage}`);
|
|
96
|
+
if (seen.has(stage)) errors.push(`Duplicate factory required stage: ${stage}`);
|
|
97
|
+
seen.add(stage);
|
|
98
|
+
if (!KNOWN_FACTORY_REQUIRED_STAGES.has(stage)) errors.push(`Unknown factory required stage: ${stage}`);
|
|
99
|
+
}
|
|
100
|
+
return errors;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function validateFactoryStages(repoRoot: string, definition: FactoryDefinition | undefined): string[] {
|
|
104
|
+
const errors: string[] = [];
|
|
105
|
+
errors.push(...validateFactoryRequiredStages(definition));
|
|
106
|
+
const stages = definition?.stages ?? [];
|
|
107
|
+
const agents = new Map(loadProjectAgents(repoRoot).map((agent) => [agent.name.toLowerCase(), agent]));
|
|
108
|
+
const stageNames = new Set<string>();
|
|
109
|
+
for (const stage of stages) {
|
|
110
|
+
if (!isSafeArtifactName(stage.name)) errors.push(`Factory stage name must be path-safe: ${stage.name}`);
|
|
111
|
+
if (stageNames.has(stage.name)) errors.push(`Duplicate factory stage name: ${stage.name}`);
|
|
112
|
+
stageNames.add(stage.name);
|
|
113
|
+
const agent = agents.get(stage.agent.toLowerCase());
|
|
114
|
+
if (!agent) {
|
|
115
|
+
errors.push(`Factory stage '${stage.name}' references unknown agent '${stage.agent}'`);
|
|
116
|
+
} else {
|
|
117
|
+
errors.push(...validateToolList(agent, stage.requiredTools).map((error) => `Factory stage '${stage.name}': ${error}`));
|
|
118
|
+
}
|
|
119
|
+
errors.push(...validateOutputContractId(stage.outputContract).map((error) => `Factory stage '${stage.name}': ${error}`));
|
|
120
|
+
if (stage.promptTemplate.trim().length === 0) errors.push(`Factory stage '${stage.name}' has an empty promptTemplate`);
|
|
121
|
+
}
|
|
122
|
+
if (stages.length > 0 && !stages.some((stage) => stage.type === "map")) errors.push("Factory stages must include at least one map stage");
|
|
123
|
+
return errors;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function loadFactoryDefinition(repoRoot: string, factoryName: string): { definition?: FactoryDefinition; errors: string[] } {
|
|
127
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(factoryName)) return { errors: [`Invalid factory name '${factoryName}'`] };
|
|
128
|
+
const factoryPath = readableZobResourcePath(repoRoot, "factories", factoryName, "factory.json");
|
|
129
|
+
if (!existsSync(factoryPath)) return { errors: [`Factory not found: ${factoryPath}`] };
|
|
130
|
+
try {
|
|
131
|
+
const parsed = parseJsonFile(factoryPath);
|
|
132
|
+
if (!isFactoryDefinition(parsed)) return { errors: [`Invalid factory definition: ${factoryPath}`] };
|
|
133
|
+
if (parsed.name !== factoryName) return { errors: [`Factory definition name '${parsed.name}' does not match requested '${factoryName}'`] };
|
|
134
|
+
return { definition: parsed, errors: [] };
|
|
135
|
+
} catch (error) {
|
|
136
|
+
return { errors: [`Could not parse factory definition '${factoryPath}': ${error instanceof Error ? error.message : String(error)}`] };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function loadFactoryInputManifest(repoRoot: string, inputManifest: string): { manifest?: FactoryInputManifest; manifestPath: string; errors: string[] } {
|
|
141
|
+
const resolved = resolveRepoPath(repoRoot, inputManifest);
|
|
142
|
+
if (resolved.errors.length > 0) return { manifestPath: resolved.path, errors: resolved.errors };
|
|
143
|
+
if (!existsSync(resolved.path)) return { manifestPath: resolved.path, errors: [`Input manifest not found: ${inputManifest}`] };
|
|
144
|
+
try {
|
|
145
|
+
const parsed = parseJsonFile(resolved.path);
|
|
146
|
+
if (!isFactoryInputManifest(parsed)) return { manifestPath: resolved.path, errors: [`Invalid factory input manifest: ${inputManifest}`] };
|
|
147
|
+
return { manifest: parsed, manifestPath: resolved.path, errors: [] };
|
|
148
|
+
} catch (error) {
|
|
149
|
+
return { manifestPath: resolved.path, errors: [`Could not parse input manifest '${inputManifest}': ${error instanceof Error ? error.message : String(error)}`] };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function isFactoryOracleReview(value: unknown): value is FactoryOracleReview {
|
|
154
|
+
if (!isRecord(value)) return false;
|
|
155
|
+
const schema = value.schema;
|
|
156
|
+
const verdict = value.verdict;
|
|
157
|
+
const noShip = value.no_ship;
|
|
158
|
+
const evidence = value.evidence;
|
|
159
|
+
const reviewer = value.reviewer;
|
|
160
|
+
const reviewedRunId = value.reviewedRunId;
|
|
161
|
+
return (
|
|
162
|
+
(schema === undefined || schema === "zob.oracle-review.v1") &&
|
|
163
|
+
(verdict === undefined || verdict === "PASS" || verdict === "FAIL" || verdict === "WARN") &&
|
|
164
|
+
(noShip === undefined || typeof noShip === "boolean") &&
|
|
165
|
+
(evidence === undefined || typeof evidence === "string") &&
|
|
166
|
+
(reviewer === undefined || typeof reviewer === "string") &&
|
|
167
|
+
(reviewedRunId === undefined || typeof reviewedRunId === "string")
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function loadFactoryOracleReview(repoRoot: string, oracleReviewPath: string | undefined): { review?: FactoryOracleReview; reviewPath?: string; errors: string[] } {
|
|
172
|
+
const errors: string[] = [];
|
|
173
|
+
if (!oracleReviewPath) return { errors: ["promotion requires oracle_review_path referencing a persisted oracle review artifact"] };
|
|
174
|
+
const resolved = resolveRepoPath(repoRoot, oracleReviewPath);
|
|
175
|
+
if (resolved.errors.length > 0) return { reviewPath: resolved.path, errors: resolved.errors.map((error) => `oracle_review_path: ${error}`) };
|
|
176
|
+
for (const protectedPattern of DEFAULT_RULES.zeroAccessPaths) {
|
|
177
|
+
if (pathMatches(oracleReviewPath, protectedPattern, repoRoot, repoRoot)) errors.push(`oracle_review_path references zero-access path: ${protectedPattern}`);
|
|
178
|
+
}
|
|
179
|
+
if (errors.length > 0) return { reviewPath: resolved.path, errors };
|
|
180
|
+
if (!existsSync(resolved.path)) return { reviewPath: resolved.path, errors: [`Referenced oracle review does not exist: ${oracleReviewPath}`] };
|
|
181
|
+
try {
|
|
182
|
+
const parsed = parseJsonFile(resolved.path);
|
|
183
|
+
if (!isFactoryOracleReview(parsed)) return { reviewPath: resolved.path, errors: [`Invalid oracle review artifact: ${oracleReviewPath}`] };
|
|
184
|
+
return { review: parsed, reviewPath: resolved.path, errors: [] };
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return { reviewPath: resolved.path, errors: [`Could not parse oracle review '${oracleReviewPath}': ${error instanceof Error ? error.message : String(error)}`] };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function summarizeFactoryOracleReview(review: FactoryOracleReview | undefined): Record<string, unknown> | undefined {
|
|
191
|
+
if (!review) return undefined;
|
|
192
|
+
return {
|
|
193
|
+
schema: review.schema ?? "zob.oracle-review.v1",
|
|
194
|
+
verdict: review.verdict,
|
|
195
|
+
no_ship: review.no_ship,
|
|
196
|
+
evidence: review.evidence,
|
|
197
|
+
reviewer: review.reviewer ?? "unspecified",
|
|
198
|
+
reviewedRunId: review.reviewedRunId,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function validateOracleReviewForPromotion(repoRoot: string, input: FactoryRunInput, reviewedRunId: string | undefined, phase: "pilot" | "batch", prerequisiteField: "prerequisite_smoke_run_id" | "prerequisite_pilot_run_id"): string[] {
|
|
203
|
+
const loaded = loadFactoryOracleReview(repoRoot, input.oracle_review_path);
|
|
204
|
+
const errors = [...loaded.errors];
|
|
205
|
+
const review = loaded.review;
|
|
206
|
+
if (!review) return errors;
|
|
207
|
+
|
|
208
|
+
if (review.schema !== "zob.oracle-review.v1") errors.push("oracle review schema must be zob.oracle-review.v1");
|
|
209
|
+
if (review.reviewedRunId !== reviewedRunId) errors.push(`oracle review reviewedRunId must match ${prerequisiteField}`);
|
|
210
|
+
if (review.verdict !== "PASS") errors.push(`${phase} oracle review verdict must be PASS`);
|
|
211
|
+
if (review.no_ship !== false) errors.push(`${phase} oracle review no_ship must be false`);
|
|
212
|
+
if (typeof review.evidence !== "string" || review.evidence.trim().length === 0) errors.push(`${phase} oracle review evidence is required`);
|
|
213
|
+
|
|
214
|
+
const inlineGate = input.oracle_gate;
|
|
215
|
+
if (isRecord(inlineGate)) {
|
|
216
|
+
if (inlineGate.verdict !== undefined && inlineGate.verdict !== review.verdict) errors.push("inline oracle_gate verdict conflicts with oracle_review_path");
|
|
217
|
+
if (inlineGate.no_ship !== undefined && inlineGate.no_ship !== review.no_ship) errors.push("inline oracle_gate no_ship conflicts with oracle_review_path");
|
|
218
|
+
if (typeof inlineGate.evidence === "string" && inlineGate.evidence.trim().length > 0 && inlineGate.evidence.trim() !== review.evidence?.trim()) errors.push("inline oracle_gate evidence conflicts with oracle_review_path");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return errors;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function validatePilotGate(repoRoot: string, input: FactoryRunInput, factoryName: string, mode: string, execution: FactoryExecutionMode): string[] {
|
|
225
|
+
const errors: string[] = [];
|
|
226
|
+
if (mode !== "pilot" || execution === "plan_only") return errors;
|
|
227
|
+
|
|
228
|
+
const smokeRunId = input.prerequisite_smoke_run_id;
|
|
229
|
+
if (!smokeRunId) {
|
|
230
|
+
errors.push("pilot requires prerequisite_smoke_run_id referencing a completed smoke run");
|
|
231
|
+
} else if (safeFileStem(smokeRunId) !== smokeRunId) {
|
|
232
|
+
errors.push(`prerequisite_smoke_run_id must be path-safe: ${smokeRunId}`);
|
|
233
|
+
} else {
|
|
234
|
+
const smokeRunDir = join(repoRoot, "reports", "factory-runs", smokeRunId);
|
|
235
|
+
const smokeValidationPath = join(smokeRunDir, "validation.json");
|
|
236
|
+
const smokePhaseSentinelPath = join(smokeRunDir, "SMOKE_PASSED.sentinel");
|
|
237
|
+
const smokeDoneSentinelPath = join(smokeRunDir, "DONE.sentinel");
|
|
238
|
+
if (!existsSync(smokeRunDir)) errors.push(`Referenced smoke run does not exist: ${smokeRunId}`);
|
|
239
|
+
if (!existsSync(smokePhaseSentinelPath)) errors.push(`Referenced smoke run is missing SMOKE_PASSED.sentinel: ${smokeRunId}`);
|
|
240
|
+
if (!existsSync(smokeDoneSentinelPath)) errors.push(`Referenced smoke run is missing DONE.sentinel: ${smokeRunId}`);
|
|
241
|
+
if (!existsSync(smokeValidationPath)) {
|
|
242
|
+
errors.push(`Referenced smoke run is missing validation.json: ${smokeRunId}`);
|
|
243
|
+
} else {
|
|
244
|
+
try {
|
|
245
|
+
const smokeValidation = parseJsonFile(smokeValidationPath);
|
|
246
|
+
if (!isRecord(smokeValidation)) {
|
|
247
|
+
errors.push(`Referenced smoke validation is not an object: ${smokeRunId}`);
|
|
248
|
+
} else {
|
|
249
|
+
if (smokeValidation.factory !== factoryName) errors.push(`Referenced smoke run factory does not match '${factoryName}': ${smokeRunId}`);
|
|
250
|
+
if (smokeValidation.mode !== "smoke") errors.push(`Referenced prerequisite run is not mode=smoke: ${smokeRunId}`);
|
|
251
|
+
if (smokeValidation.status !== "passed") errors.push(`Referenced smoke run validation did not pass: ${smokeRunId}`);
|
|
252
|
+
const phaseSentinel = isRecord(smokeValidation.phaseSentinel) ? smokeValidation.phaseSentinel : undefined;
|
|
253
|
+
if (phaseSentinel?.artifact !== "SMOKE_PASSED.sentinel" || phaseSentinel?.written !== true) errors.push(`Referenced smoke validation does not record SMOKE_PASSED.sentinel: ${smokeRunId}`);
|
|
254
|
+
if (smokeValidation.sentinelWritten !== true) errors.push(`Referenced smoke validation does not record DONE.sentinel: ${smokeRunId}`);
|
|
255
|
+
}
|
|
256
|
+
} catch (error) {
|
|
257
|
+
errors.push(`Could not parse referenced smoke validation '${smokeValidationPath}': ${error instanceof Error ? error.message : String(error)}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
errors.push(...validateOracleReviewForPromotion(repoRoot, input, smokeRunId, "pilot", "prerequisite_smoke_run_id"));
|
|
263
|
+
return errors;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function validateFactoryBudgetInput(input: FactoryRunInput): string[] {
|
|
267
|
+
const errors: string[] = [];
|
|
268
|
+
const budget = input.budget;
|
|
269
|
+
if (budget === undefined) return errors;
|
|
270
|
+
const numericKeys = ["maxCostUsd", "maxRuns", "maxDurationMs", "maxParallelChildren", "estimatedCostUsd", "estimatedRuns", "estimatedDurationMs", "estimatedParallelChildren"] as const;
|
|
271
|
+
for (const key of numericKeys) {
|
|
272
|
+
const value = budget[key];
|
|
273
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value) || value < 0)) errors.push(`budget.${key} must be a nonnegative finite number`);
|
|
274
|
+
}
|
|
275
|
+
if (budget.strictEnabled !== undefined && typeof budget.strictEnabled !== "boolean") errors.push("budget.strictEnabled must be boolean");
|
|
276
|
+
if (budget.strictRequested !== undefined && typeof budget.strictRequested !== "boolean") errors.push("budget.strictRequested must be boolean");
|
|
277
|
+
return errors;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function isLowerSha256(value: unknown): value is string {
|
|
281
|
+
return typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function normalizeFactoryAdaptiveDispatchGate(input?: FactoryAdaptiveDispatchGateInput): FactoryAdaptiveDispatchGate | undefined {
|
|
285
|
+
if (!input) return undefined;
|
|
286
|
+
const proofRunId = typeof input.proofRunId === "string" ? input.proofRunId.trim() : "";
|
|
287
|
+
const approvedBy = typeof input.approvedBy === "string" ? input.approvedBy.trim() : "";
|
|
288
|
+
const approvalId = typeof input.approvalId === "string" ? input.approvalId.trim() : "";
|
|
289
|
+
const scope = typeof input.scope === "string" ? input.scope.trim() : "";
|
|
290
|
+
const liveReadOnlyProofEnabled = input.enabled === true && input.liveReadOnlyProofEnabled === true;
|
|
291
|
+
return {
|
|
292
|
+
schema: "zob.factory-adaptive-dispatch-gate.v1",
|
|
293
|
+
enabled: input.enabled === true,
|
|
294
|
+
liveReadOnlyProofEnabled,
|
|
295
|
+
proofRunIdHash: proofRunId ? sha256(proofRunId) : undefined,
|
|
296
|
+
proofReviewHash: typeof input.proofReviewHash === "string" ? input.proofReviewHash : undefined,
|
|
297
|
+
approvedByHash: approvedBy ? sha256(approvedBy) : undefined,
|
|
298
|
+
approvedAt: typeof input.approvedAt === "string" && input.approvedAt.trim().length > 0 ? input.approvedAt.trim() : undefined,
|
|
299
|
+
approvalIdHash: approvalId ? sha256(approvalId) : undefined,
|
|
300
|
+
scopeHash: scope ? sha256(scope) : undefined,
|
|
301
|
+
liveFactoryAdaptiveDispatchEnabled: liveReadOnlyProofEnabled,
|
|
302
|
+
parentOwnedDispatch: true,
|
|
303
|
+
childDirectDispatch: false,
|
|
304
|
+
productionWritesPerformed: false,
|
|
305
|
+
autoApply: false,
|
|
306
|
+
bodyStored: false,
|
|
307
|
+
promptBodiesStored: false,
|
|
308
|
+
outputBodiesStored: false,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function validateFactoryAdaptiveDispatchGate(gate?: FactoryAdaptiveDispatchGate): string[] {
|
|
313
|
+
const errors: string[] = [];
|
|
314
|
+
if (!gate) return errors;
|
|
315
|
+
if (gate.enabled === true) {
|
|
316
|
+
if (!isLowerSha256(gate.proofRunIdHash)) errors.push("adaptive_factory_dispatch_gate.proofRunId is required and stored as proofRunIdHash");
|
|
317
|
+
if (!isLowerSha256(gate.proofReviewHash)) errors.push("adaptive_factory_dispatch_gate.proofReviewHash must be lowercase sha256 hex");
|
|
318
|
+
if (!isLowerSha256(gate.approvedByHash)) errors.push("adaptive_factory_dispatch_gate.approvedBy is required and stored as approvedByHash");
|
|
319
|
+
if (!isLowerSha256(gate.approvalIdHash)) errors.push("adaptive_factory_dispatch_gate.approvalId is required and stored as approvalIdHash");
|
|
320
|
+
if (typeof gate.approvedAt !== "string" || gate.approvedAt.trim().length === 0) errors.push("adaptive_factory_dispatch_gate.approvedAt is required");
|
|
321
|
+
if (gate.scopeHash !== undefined && !isLowerSha256(gate.scopeHash)) errors.push("adaptive_factory_dispatch_gate.scopeHash must be lowercase sha256 hex");
|
|
322
|
+
}
|
|
323
|
+
if (gate.liveReadOnlyProofEnabled === true && gate.enabled !== true) errors.push("adaptive_factory_dispatch_gate liveReadOnlyProofEnabled requires enabled=true");
|
|
324
|
+
if (gate.liveFactoryAdaptiveDispatchEnabled !== gate.liveReadOnlyProofEnabled) errors.push("adaptive_factory_dispatch_gate liveFactoryAdaptiveDispatchEnabled must equal liveReadOnlyProofEnabled");
|
|
325
|
+
if (gate.productionWritesPerformed !== false || gate.autoApply !== false) errors.push("adaptive_factory_dispatch_gate must keep production writes and auto-apply disabled");
|
|
326
|
+
if (gate.parentOwnedDispatch !== true || gate.childDirectDispatch !== false) errors.push("adaptive_factory_dispatch_gate must preserve parentOwnedDispatch=true and childDirectDispatch=false");
|
|
327
|
+
if (gate.bodyStored !== false || gate.promptBodiesStored !== false || gate.outputBodiesStored !== false) errors.push("adaptive_factory_dispatch_gate must be hash-only with body flags false");
|
|
328
|
+
return errors;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function validateFactoryAdaptiveDelegationInput(input: FactoryRunInput, mode: string, execution: FactoryExecutionMode): string[] {
|
|
332
|
+
const policy = normalizeAdaptiveDelegationPolicy(input.adaptive_delegation);
|
|
333
|
+
const gate = normalizeFactoryAdaptiveDispatchGate(input.adaptive_factory_dispatch_gate);
|
|
334
|
+
const errors = [
|
|
335
|
+
...validateAdaptiveDelegationPolicy(policy).map((error) => `factory adaptive_delegation: ${error}`),
|
|
336
|
+
...validateFactoryAdaptiveDispatchGate(gate).map((error) => `factory ${error}`),
|
|
337
|
+
];
|
|
338
|
+
if (!policy.enabled) return errors;
|
|
339
|
+
if (policy.dispatch === true) {
|
|
340
|
+
if (gate?.enabled !== true) errors.push("factory adaptive_delegation live dispatch requires adaptive_factory_dispatch_gate.enabled=true with hash-only proof metadata");
|
|
341
|
+
if (gate?.liveReadOnlyProofEnabled !== true) errors.push("factory adaptive_delegation live dispatch requires adaptive_factory_dispatch_gate.liveReadOnlyProofEnabled=true");
|
|
342
|
+
if (execution !== "agentic") errors.push("factory adaptive_delegation live dispatch proof gate requires execution=agentic");
|
|
343
|
+
if (mode !== "smoke") errors.push("factory adaptive_delegation live dispatch proof gate is smoke-only until a registered proof passes");
|
|
344
|
+
if (policy.mode !== "when_pertinent") errors.push("factory adaptive_delegation live dispatch proof gate requires mode=when_pertinent");
|
|
345
|
+
if (policy.runtimeMaxDepth > 2) errors.push("factory adaptive_delegation live read-only proof runtimeMaxDepth must be <= 2");
|
|
346
|
+
if (policy.maxTotalAgentsWithOracle > 4) errors.push("factory adaptive_delegation live read-only proof maxTotalAgentsWithOracle must be <= 4");
|
|
347
|
+
} else if (policy.mode !== "advisory_only") {
|
|
348
|
+
errors.push("factory adaptive_delegation P8 supports only mode=advisory_only unless a future live proof gate is activated");
|
|
349
|
+
}
|
|
350
|
+
return errors;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function validateFactoryModelRoutingInput(input: FactoryRunInput): string[] {
|
|
354
|
+
const errors: string[] = [];
|
|
355
|
+
const routing = input.model_routing;
|
|
356
|
+
if (routing === undefined) return errors;
|
|
357
|
+
if (routing.enabled !== undefined && typeof routing.enabled !== "boolean") errors.push("model_routing.enabled must be boolean");
|
|
358
|
+
if (routing.risk !== undefined && routing.risk !== "low" && routing.risk !== "medium" && routing.risk !== "high") errors.push("model_routing.risk must be low, medium, or high");
|
|
359
|
+
if (routing.contextTokens !== undefined && (typeof routing.contextTokens !== "number" || !Number.isFinite(routing.contextTokens) || routing.contextTokens < 0)) errors.push("model_routing.contextTokens must be a nonnegative finite number");
|
|
360
|
+
if (routing.modelByClass !== undefined) {
|
|
361
|
+
if (!isRecord(routing.modelByClass)) {
|
|
362
|
+
errors.push("model_routing.modelByClass must be an object when provided");
|
|
363
|
+
} else {
|
|
364
|
+
for (const [modelClass, modelName] of Object.entries(routing.modelByClass)) {
|
|
365
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(modelClass)) errors.push(`model_routing.modelByClass key must be path-safe/model-class-safe: ${modelClass}`);
|
|
366
|
+
if (typeof modelName !== "string" || modelName.trim().length === 0) errors.push(`model_routing.modelByClass.${modelClass} must be a non-empty string`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return errors;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function validateBatchGate(repoRoot: string, input: FactoryRunInput, factoryName: string, mode: string, execution: FactoryExecutionMode): string[] {
|
|
374
|
+
const errors: string[] = [];
|
|
375
|
+
if (mode !== "batch" || execution === "plan_only") return errors;
|
|
376
|
+
|
|
377
|
+
const concurrency = input.batch_concurrency;
|
|
378
|
+
if (concurrency === undefined) {
|
|
379
|
+
errors.push("batch requires batch_concurrency as a positive concurrency cap");
|
|
380
|
+
} else if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
381
|
+
errors.push("batch_concurrency must be a positive integer");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const pilotRunId = input.prerequisite_pilot_run_id;
|
|
385
|
+
if (!pilotRunId) {
|
|
386
|
+
errors.push("batch requires prerequisite_pilot_run_id referencing a completed pilot run");
|
|
387
|
+
} else if (safeFileStem(pilotRunId) !== pilotRunId) {
|
|
388
|
+
errors.push(`prerequisite_pilot_run_id must be path-safe: ${pilotRunId}`);
|
|
389
|
+
} else {
|
|
390
|
+
const pilotRunDir = join(repoRoot, "reports", "factory-runs", pilotRunId);
|
|
391
|
+
const pilotValidationPath = join(pilotRunDir, "validation.json");
|
|
392
|
+
const pilotPhaseSentinelPath = join(pilotRunDir, "PILOT_PASSED.sentinel");
|
|
393
|
+
const pilotDoneSentinelPath = join(pilotRunDir, "DONE.sentinel");
|
|
394
|
+
if (!existsSync(pilotRunDir)) errors.push(`Referenced pilot run does not exist: ${pilotRunId}`);
|
|
395
|
+
if (!existsSync(pilotPhaseSentinelPath)) errors.push(`Referenced pilot run is missing PILOT_PASSED.sentinel: ${pilotRunId}`);
|
|
396
|
+
if (!existsSync(pilotDoneSentinelPath)) errors.push(`Referenced pilot run is missing DONE.sentinel: ${pilotRunId}`);
|
|
397
|
+
if (!existsSync(pilotValidationPath)) {
|
|
398
|
+
errors.push(`Referenced pilot run is missing validation.json: ${pilotRunId}`);
|
|
399
|
+
} else {
|
|
400
|
+
try {
|
|
401
|
+
const pilotValidation = parseJsonFile(pilotValidationPath);
|
|
402
|
+
if (!isRecord(pilotValidation)) {
|
|
403
|
+
errors.push(`Referenced pilot validation is not an object: ${pilotRunId}`);
|
|
404
|
+
} else {
|
|
405
|
+
if (pilotValidation.factory !== factoryName) errors.push(`Referenced pilot run factory does not match '${factoryName}': ${pilotRunId}`);
|
|
406
|
+
if (pilotValidation.mode !== "pilot") errors.push(`Referenced prerequisite run is not mode=pilot: ${pilotRunId}`);
|
|
407
|
+
if (pilotValidation.status !== "passed") errors.push(`Referenced pilot run validation did not pass: ${pilotRunId}`);
|
|
408
|
+
const phaseSentinel = isRecord(pilotValidation.phaseSentinel) ? pilotValidation.phaseSentinel : undefined;
|
|
409
|
+
if (phaseSentinel?.artifact !== "PILOT_PASSED.sentinel" || phaseSentinel?.written !== true) errors.push(`Referenced pilot validation does not record PILOT_PASSED.sentinel: ${pilotRunId}`);
|
|
410
|
+
if (pilotValidation.sentinelWritten !== true) errors.push(`Referenced pilot validation does not record DONE.sentinel: ${pilotRunId}`);
|
|
411
|
+
}
|
|
412
|
+
} catch (error) {
|
|
413
|
+
errors.push(`Could not parse referenced pilot validation '${pilotValidationPath}': ${error instanceof Error ? error.message : String(error)}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
errors.push(...validateOracleReviewForPromotion(repoRoot, input, pilotRunId, "batch", "prerequisite_pilot_run_id"));
|
|
419
|
+
return errors;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export function validateFactoryRunInputs(repoRoot: string, input: FactoryRunInput): string[] {
|
|
423
|
+
const errors: string[] = [];
|
|
424
|
+
const factory = loadFactoryDefinition(repoRoot, input.factory);
|
|
425
|
+
errors.push(...factory.errors);
|
|
426
|
+
errors.push(...validateExpectedArtifacts(factory.definition?.expectedArtifacts, "factory"));
|
|
427
|
+
errors.push(...validateFactoryStages(repoRoot, factory.definition));
|
|
428
|
+
const manifest = loadFactoryInputManifest(repoRoot, input.input_manifest);
|
|
429
|
+
errors.push(...manifest.errors);
|
|
430
|
+
errors.push(...validateExpectedArtifacts(manifest.manifest?.expectedArtifacts, "manifest"));
|
|
431
|
+
if (manifest.manifest && manifest.manifest.factory !== input.factory) errors.push(`Manifest factory '${manifest.manifest.factory}' does not match requested '${input.factory}'`);
|
|
432
|
+
if (input.run_id && safeFileStem(input.run_id) !== input.run_id) errors.push(`run_id must be path-safe: ${input.run_id}`);
|
|
433
|
+
if (input.max_items !== undefined && (!Number.isInteger(input.max_items) || input.max_items < 1)) errors.push("max_items must be a positive integer");
|
|
434
|
+
if (input.batch_concurrency !== undefined && (!Number.isInteger(input.batch_concurrency) || input.batch_concurrency < 1)) errors.push("batch_concurrency must be a positive integer");
|
|
435
|
+
errors.push(...validateFactoryBudgetInput(input));
|
|
436
|
+
errors.push(...validateFactoryModelRoutingInput(input));
|
|
437
|
+
const mode = input.mode ?? factory.definition?.defaultMode ?? "smoke";
|
|
438
|
+
const execution = input.execution ?? "deterministic";
|
|
439
|
+
if (!["smoke", "pilot", "batch"].includes(mode)) errors.push(`Invalid factory mode '${mode}'`);
|
|
440
|
+
if (input.execution !== undefined && !["deterministic", "plan_only", "agentic"].includes(input.execution)) errors.push(`Invalid factory execution '${input.execution}'`);
|
|
441
|
+
errors.push(...validateFactoryAdaptiveDelegationInput(input, mode, execution));
|
|
442
|
+
errors.push(...validatePilotGate(repoRoot, input, input.factory, mode, execution));
|
|
443
|
+
errors.push(...validateBatchGate(repoRoot, input, input.factory, mode, execution));
|
|
444
|
+
for (const item of manifest.manifest?.items ?? []) {
|
|
445
|
+
const itemPath = resolveRepoPath(repoRoot, item.path);
|
|
446
|
+
errors.push(...itemPath.errors.map((error) => `Item '${item.id}': ${error}`));
|
|
447
|
+
for (const protectedPattern of DEFAULT_RULES.zeroAccessPaths) {
|
|
448
|
+
if (pathMatches(item.path, protectedPattern, repoRoot, repoRoot)) errors.push(`Item '${item.id}' references zero-access path: ${protectedPattern}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return errors;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export { FACTORY_PHASE_SENTINELS, loadFactoryOracleReview, summarizeFactoryOracleReview };
|