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,152 @@
|
|
|
1
|
+
import type { BillableJobIntake, BudgetSidecar, GoalState } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export type StrictGoalSpecAnchorKind = "active_goal" | "orchestrate_run" | "factory_run" | "delegate_write" | "quarantine";
|
|
4
|
+
|
|
5
|
+
export interface StrictGoalSpecAnchor {
|
|
6
|
+
kind: StrictGoalSpecAnchorKind;
|
|
7
|
+
activeGoal?: GoalState;
|
|
8
|
+
originalUserAsk?: string;
|
|
9
|
+
goal?: string;
|
|
10
|
+
expectedOutput?: string;
|
|
11
|
+
constraints?: string;
|
|
12
|
+
validationEvidence?: string;
|
|
13
|
+
factoryName?: string;
|
|
14
|
+
factoryDescription?: string;
|
|
15
|
+
inputManifest?: string;
|
|
16
|
+
manifestFactory?: string;
|
|
17
|
+
manifestDescription?: string;
|
|
18
|
+
manifestItems?: number;
|
|
19
|
+
taskText?: string;
|
|
20
|
+
requiredTools?: string[];
|
|
21
|
+
operation?: string;
|
|
22
|
+
runId?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function extractGoalField(text: string, label: string): string | undefined {
|
|
26
|
+
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27
|
+
const regex = new RegExp(`(?:^|\\n)\\s*${escaped}\\s*:\\s*([^\\n]+(?:\\n(?!\\s*[A-Z_]+\\s*:).+)*)`, "i");
|
|
28
|
+
return regex.exec(text)?.[1]?.trim();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function parseGoalState(text: string): GoalState {
|
|
32
|
+
return {
|
|
33
|
+
originalUserAsk: extractGoalField(text, "ORIGINAL_USER_ASK") ?? text,
|
|
34
|
+
activeGoal: extractGoalField(text, "ACTIVE_GOAL") ?? text,
|
|
35
|
+
expectedOutput: extractGoalField(text, "EXPECTED_OUTPUT") ?? "Not specified",
|
|
36
|
+
constraints: extractGoalField(text, "CONSTRAINTS") ?? "Not specified",
|
|
37
|
+
validationEvidence: extractGoalField(text, "VALIDATION_EVIDENCE") ?? "Not specified",
|
|
38
|
+
setAt: new Date().toISOString(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isPlaceholderValue(value: string | undefined): boolean {
|
|
43
|
+
const trimmed = value?.trim() ?? "";
|
|
44
|
+
return !trimmed || /^\[.*\]$/.test(trimmed) || /^(not set|not specified|todo|tbd)$/i.test(trimmed);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function validateGoalState(goal: GoalState | undefined): string[] {
|
|
48
|
+
const errors: string[] = [];
|
|
49
|
+
if (!goal) return ["Active ZOB goal is required. Set /goal_gate or /job_intake before dispatch."];
|
|
50
|
+
if (isPlaceholderValue(goal.originalUserAsk)) errors.push("ORIGINAL_USER_ASK is required and must not be a placeholder");
|
|
51
|
+
if (isPlaceholderValue(goal.activeGoal)) errors.push("ACTIVE_GOAL is required and must not be a placeholder");
|
|
52
|
+
if (isPlaceholderValue(goal.expectedOutput)) errors.push("EXPECTED_OUTPUT is required and must not be a placeholder");
|
|
53
|
+
if (isPlaceholderValue(goal.constraints)) errors.push("CONSTRAINTS is required and must not be a placeholder");
|
|
54
|
+
if (isPlaceholderValue(goal.validationEvidence)) errors.push("VALIDATION_EVIDENCE is required and must not be a placeholder");
|
|
55
|
+
return errors;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function validateOptionalGoalText(value: string | undefined, label: string): string[] {
|
|
59
|
+
return isPlaceholderValue(value) ? [`${label} is required and must not be a placeholder`] : [];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function extractInlineOriginalUserAsk(text: string | undefined): string | undefined {
|
|
63
|
+
if (!text) return undefined;
|
|
64
|
+
return extractGoalField(text, "ORIGINAL_USER_ASK");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function hasWriteTool(tools: string[] | undefined): boolean {
|
|
68
|
+
return (tools ?? []).some((tool) => tool === "edit" || tool === "write");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function validateStrictGoalSpecAnchor(anchor: StrictGoalSpecAnchor | undefined): string[] {
|
|
72
|
+
if (!anchor) return ["Strict goal/spec anchor is required for autonomous/write/factory/orchestrate dispatch"];
|
|
73
|
+
const activeGoalErrors = validateGoalState(anchor.activeGoal);
|
|
74
|
+
if (activeGoalErrors.length === 0) return [];
|
|
75
|
+
|
|
76
|
+
const errors: string[] = [];
|
|
77
|
+
if (anchor.kind === "orchestrate_run") {
|
|
78
|
+
errors.push(...validateOptionalGoalText(anchor.originalUserAsk, "original_user_ask"));
|
|
79
|
+
errors.push(...validateOptionalGoalText(anchor.goal, "goal"));
|
|
80
|
+
return errors.map((error) => `orchestrate_run strict goal/spec gate: ${error}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (anchor.kind === "factory_run") {
|
|
84
|
+
if (isPlaceholderValue(anchor.factoryName)) errors.push("factory name is required");
|
|
85
|
+
if (isPlaceholderValue(anchor.factoryDescription)) errors.push("factory definition description is required");
|
|
86
|
+
if (isPlaceholderValue(anchor.inputManifest)) errors.push("input_manifest is required");
|
|
87
|
+
if (anchor.manifestFactory !== anchor.factoryName) errors.push("input_manifest factory must match requested factory");
|
|
88
|
+
if (typeof anchor.manifestItems !== "number" || anchor.manifestItems < 1) errors.push("input_manifest must contain at least one item");
|
|
89
|
+
return errors.map((error) => `factory_run strict goal/spec gate: ${error}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (anchor.kind === "delegate_write") {
|
|
93
|
+
if (!hasWriteTool(anchor.requiredTools)) return [];
|
|
94
|
+
const originalUserAsk = anchor.originalUserAsk ?? extractInlineOriginalUserAsk(anchor.taskText);
|
|
95
|
+
errors.push(...validateOptionalGoalText(originalUserAsk, "ORIGINAL_USER_ASK/original_user_ask"));
|
|
96
|
+
errors.push(...validateOptionalGoalText(anchor.taskText, "delegation task contract"));
|
|
97
|
+
return errors.map((error) => `delegate write strict goal/spec gate: ${error}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (anchor.kind === "quarantine") {
|
|
101
|
+
if (isPlaceholderValue(anchor.operation)) errors.push("quarantine operation is required");
|
|
102
|
+
if (isPlaceholderValue(anchor.runId)) errors.push("quarantine run_id is required");
|
|
103
|
+
return errors.map((error) => `factory quarantine strict goal/spec gate: ${error}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return activeGoalErrors;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function numberFromGoalField(text: string, label: string): number | undefined {
|
|
110
|
+
const raw = extractGoalField(text, label);
|
|
111
|
+
if (!raw) return undefined;
|
|
112
|
+
const match = raw.match(/\d+(?:\.\d+)?/);
|
|
113
|
+
if (!match) return undefined;
|
|
114
|
+
const value = Number(match[0]);
|
|
115
|
+
return Number.isFinite(value) ? value : undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function parseBudgetSidecar(text: string): BudgetSidecar | undefined {
|
|
119
|
+
const raw = extractGoalField(text, "BUDGET") ?? extractGoalField(text, "BUDGET_SIDECAR");
|
|
120
|
+
const strictRequested = /\b(strict|enforce|enforced|hard gate)\b/i.test(raw ?? extractGoalField(text, "BUDGET_MODE") ?? extractGoalField(text, "BUDGET_STRICT") ?? "");
|
|
121
|
+
const sidecar: BudgetSidecar = {
|
|
122
|
+
mode: "advisory",
|
|
123
|
+
advisory: true,
|
|
124
|
+
budgetEnforced: false,
|
|
125
|
+
strictRequested,
|
|
126
|
+
strictEnabled: false,
|
|
127
|
+
raw,
|
|
128
|
+
maxCostUsd: numberFromGoalField(text, "BUDGET_MAX_USD") ?? numberFromGoalField(text, "MAX_COST_USD"),
|
|
129
|
+
maxRuns: numberFromGoalField(text, "BUDGET_MAX_RUNS") ?? numberFromGoalField(text, "MAX_RUNS"),
|
|
130
|
+
maxDurationMs: numberFromGoalField(text, "BUDGET_MAX_DURATION_MS") ?? numberFromGoalField(text, "MAX_DURATION_MS"),
|
|
131
|
+
maxParallelChildren: numberFromGoalField(text, "BUDGET_MAX_PARALLEL_CHILDREN") ?? numberFromGoalField(text, "MAX_PARALLEL_CHILDREN"),
|
|
132
|
+
};
|
|
133
|
+
const hasBudget = raw !== undefined || sidecar.maxCostUsd !== undefined || sidecar.maxRuns !== undefined || sidecar.maxDurationMs !== undefined || sidecar.maxParallelChildren !== undefined;
|
|
134
|
+
return hasBudget ? sidecar : undefined;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function parseBillableJobIntake(text: string): BillableJobIntake {
|
|
138
|
+
return {
|
|
139
|
+
schema: "zob.billable-job-intake.v1",
|
|
140
|
+
goal: parseGoalState(text),
|
|
141
|
+
budget: parseBudgetSidecar(text),
|
|
142
|
+
budgetEnforced: false,
|
|
143
|
+
parsedAt: new Date().toISOString(),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function validateBillableJobIntake(intake: BillableJobIntake): string[] {
|
|
148
|
+
const errors = validateGoalState(intake.goal);
|
|
149
|
+
if (intake.budgetEnforced !== false) errors.push("budgetEnforced must remain false for advisory billable intake");
|
|
150
|
+
if (intake.budget && intake.budget.budgetEnforced !== false) errors.push("budget sidecar must be advisory and budgetEnforced=false");
|
|
151
|
+
return errors;
|
|
152
|
+
}
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { DEFAULT_RULES } from "./constants.js";
|
|
2
|
+
import { appendGoalRoomMessage } from "./goal-room.js";
|
|
3
|
+
import type { TeamDefinition } from "./types.js";
|
|
4
|
+
import { sha256 } from "./utils/hashing.js";
|
|
5
|
+
import { pathMatches } from "./utils/paths.js";
|
|
6
|
+
import { resolveRepoPath, safeFileStem } from "./utils/paths.js";
|
|
7
|
+
import { isRecord } from "./utils/records.js";
|
|
8
|
+
|
|
9
|
+
export type GovernedRequestKind = "DELEGATION_REQUEST" | "ORACLE_REQUEST" | "CONTEXT_REQUEST" | "OWNER_CHANGE_REQUEST";
|
|
10
|
+
export type GovernedRequestPriority = "low" | "normal" | "high" | "critical";
|
|
11
|
+
export type GovernedRequestRisk = "low" | "medium" | "high";
|
|
12
|
+
|
|
13
|
+
export interface GovernedRequestRecord {
|
|
14
|
+
schema: "zob.governed-request.v1";
|
|
15
|
+
contract: "delegation-request.v1" | "oracle-request.v1" | "context-request.v1" | "owner-change-request.v1";
|
|
16
|
+
kind: GovernedRequestKind;
|
|
17
|
+
requestId: string;
|
|
18
|
+
goalId: string | null;
|
|
19
|
+
todoId: string | null;
|
|
20
|
+
requestedBy: string;
|
|
21
|
+
requestedAction: string;
|
|
22
|
+
priority: GovernedRequestPriority;
|
|
23
|
+
riskLevel: GovernedRequestRisk;
|
|
24
|
+
bodyHash: string;
|
|
25
|
+
requestHash: string;
|
|
26
|
+
sourceOutputHash: string;
|
|
27
|
+
agent: string | null;
|
|
28
|
+
outputContract: string | null;
|
|
29
|
+
requiredTools: string[];
|
|
30
|
+
allowedPaths: string[];
|
|
31
|
+
forbiddenPaths: string[];
|
|
32
|
+
contextScopeId: string | null;
|
|
33
|
+
ownerWorker: string | null;
|
|
34
|
+
requestedPaths: string[];
|
|
35
|
+
changeHash: string | null;
|
|
36
|
+
reasonHash: string | null;
|
|
37
|
+
validationPlanHash: string | null;
|
|
38
|
+
evidenceRefs: string[];
|
|
39
|
+
artifactRefs: string[];
|
|
40
|
+
noShip: boolean;
|
|
41
|
+
finalMarker: string;
|
|
42
|
+
parentVisible: true;
|
|
43
|
+
requiresParentAction: true;
|
|
44
|
+
parentOwnedActions: true;
|
|
45
|
+
childDirectDispatch: false;
|
|
46
|
+
canonicalTodoMutation: false;
|
|
47
|
+
dispatchExecuted: false;
|
|
48
|
+
bodyStored: false;
|
|
49
|
+
promptBodiesStored: false;
|
|
50
|
+
outputBodiesStored: false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface GovernedRequestExtractionResult {
|
|
54
|
+
schema: "zob.governed-request-extraction.v1";
|
|
55
|
+
sourceOutputHash: string;
|
|
56
|
+
requests: GovernedRequestRecord[];
|
|
57
|
+
extractionErrors: string[];
|
|
58
|
+
goalRoomMessageIds: string[];
|
|
59
|
+
parentOwnedActions: true;
|
|
60
|
+
childDirectDispatch: false;
|
|
61
|
+
dispatchExecuted: false;
|
|
62
|
+
bodyStored: false;
|
|
63
|
+
promptBodiesStored: false;
|
|
64
|
+
outputBodiesStored: false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const SHA256_HEX = /^[a-f0-9]{64}$/i;
|
|
68
|
+
const REQUEST_TYPES = new Set<GovernedRequestKind>(["DELEGATION_REQUEST", "ORACLE_REQUEST", "CONTEXT_REQUEST", "OWNER_CHANGE_REQUEST"]);
|
|
69
|
+
const PRIORITIES = new Set<GovernedRequestPriority>(["low", "normal", "high", "critical"]);
|
|
70
|
+
const RISKS = new Set<GovernedRequestRisk>(["low", "medium", "high"]);
|
|
71
|
+
const FORBIDDEN_PLAINTEXT_LABELS = new Set(["body", "task", "prompt", "output", "content", "message", "text", "rationale", "diff", "patch"]);
|
|
72
|
+
const KNOWN_LABELS = new Set([
|
|
73
|
+
"deliverabledelivered",
|
|
74
|
+
"requesttype",
|
|
75
|
+
"requestid",
|
|
76
|
+
"goalid",
|
|
77
|
+
"todoid",
|
|
78
|
+
"requestedby",
|
|
79
|
+
"requestedaction",
|
|
80
|
+
"priority",
|
|
81
|
+
"risklevel",
|
|
82
|
+
"bodyhash",
|
|
83
|
+
"agent",
|
|
84
|
+
"outputcontract",
|
|
85
|
+
"requiredtools",
|
|
86
|
+
"allowedpaths",
|
|
87
|
+
"forbiddenpaths",
|
|
88
|
+
"contextscopeid",
|
|
89
|
+
"ownerworker",
|
|
90
|
+
"requestedpaths",
|
|
91
|
+
"changehash",
|
|
92
|
+
"reasonhash",
|
|
93
|
+
"validationplanhash",
|
|
94
|
+
"evidencerefs",
|
|
95
|
+
"artifactrefs",
|
|
96
|
+
"noship",
|
|
97
|
+
"compliance",
|
|
98
|
+
"finalmarker",
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
function knownRoleIds(definition: TeamDefinition): Set<string> {
|
|
102
|
+
return new Set([definition.orchestrator.id, ...definition.leads.map((lead) => lead.id), ...definition.workers.map((worker) => worker.id), "parent", "mission-control"]);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function normalizeLabel(label: string): string {
|
|
106
|
+
return label.toLowerCase().replace(/[^a-z0-9]+/g, "");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function stripBullet(line: string): string {
|
|
110
|
+
return line.trim().replace(/^[-*•]\s+/, "").trim();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function splitLabel(line: string): { label: string; value: string } | undefined {
|
|
114
|
+
const stripped = stripBullet(line);
|
|
115
|
+
const match = stripped.match(/^([A-Za-z0-9 _.-]+)\s*[:=]\s*(.*)$/);
|
|
116
|
+
if (!match) return undefined;
|
|
117
|
+
return { label: normalizeLabel(match[1] ?? ""), value: (match[2] ?? "").trim() };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function scalar(lines: string[], labels: string[]): string | undefined {
|
|
121
|
+
const wanted = new Set(labels.map(normalizeLabel));
|
|
122
|
+
for (const line of lines) {
|
|
123
|
+
const parsed = splitLabel(line);
|
|
124
|
+
if (parsed && wanted.has(parsed.label)) return parsed.value;
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function listValue(lines: string[], labels: string[]): string[] {
|
|
130
|
+
const wanted = new Set(labels.map(normalizeLabel));
|
|
131
|
+
const values: string[] = [];
|
|
132
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
133
|
+
const parsed = splitLabel(lines[index] ?? "");
|
|
134
|
+
if (!parsed || !wanted.has(parsed.label)) continue;
|
|
135
|
+
if (parsed.value) values.push(...splitInlineList(parsed.value));
|
|
136
|
+
for (let cursor = index + 1; cursor < lines.length; cursor += 1) {
|
|
137
|
+
const next = lines[cursor] ?? "";
|
|
138
|
+
const nextParsed = splitLabel(next);
|
|
139
|
+
if (nextParsed && KNOWN_LABELS.has(nextParsed.label)) break;
|
|
140
|
+
const stripped = stripBullet(next);
|
|
141
|
+
if (!stripped) continue;
|
|
142
|
+
if (/^FINAL_MARKER\s*:/i.test(stripped)) break;
|
|
143
|
+
values.push(...splitInlineList(stripped));
|
|
144
|
+
}
|
|
145
|
+
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
146
|
+
}
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function splitInlineList(value: string): string[] {
|
|
151
|
+
return value
|
|
152
|
+
.split(/[,;]\s*|\s+\|\s+/)
|
|
153
|
+
.map((item) => item.trim().replace(/^[-*•]\s+/, ""))
|
|
154
|
+
.filter(Boolean)
|
|
155
|
+
.filter((item) => item.toLowerCase() !== "none" && item !== "-");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function parseBoolean(value: string | undefined): boolean | undefined {
|
|
159
|
+
if (value === undefined) return undefined;
|
|
160
|
+
const normalized = value.trim().toLowerCase();
|
|
161
|
+
if (["true", "yes", "y", "1"].includes(normalized)) return true;
|
|
162
|
+
if (["false", "no", "n", "0"].includes(normalized)) return false;
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function parseKind(value: string | undefined): GovernedRequestKind | undefined {
|
|
167
|
+
const normalized = value?.trim().replace(/\.v1$/i, "").toUpperCase();
|
|
168
|
+
return REQUEST_TYPES.has(normalized as GovernedRequestKind) ? normalized as GovernedRequestKind : undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function contractForKind(kind: GovernedRequestKind): GovernedRequestRecord["contract"] {
|
|
172
|
+
if (kind === "ORACLE_REQUEST") return "oracle-request.v1";
|
|
173
|
+
if (kind === "CONTEXT_REQUEST") return "context-request.v1";
|
|
174
|
+
if (kind === "OWNER_CHANGE_REQUEST") return "owner-change-request.v1";
|
|
175
|
+
return "delegation-request.v1";
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function finalMarkerForKind(kind: GovernedRequestKind): string {
|
|
179
|
+
return `${kind}_END`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function chunksFromText(text: string): string[] {
|
|
183
|
+
const lines = text.split(/\r?\n/);
|
|
184
|
+
const starts = lines.map((line, index) => ({ index, parsed: splitLabel(line) })).filter((item) => item.parsed?.label === "requesttype");
|
|
185
|
+
if (starts.length === 0) return [];
|
|
186
|
+
return starts.map((start, startIndex) => lines.slice(startIndex === 0 ? 0 : start.index, starts[startIndex + 1]?.index ?? lines.length).join("\n"));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function plaintextLabelErrors(lines: string[]): string[] {
|
|
190
|
+
return lines.flatMap((line) => {
|
|
191
|
+
const parsed = splitLabel(line);
|
|
192
|
+
return parsed && FORBIDDEN_PLAINTEXT_LABELS.has(parsed.label) ? [`governed request must not include raw '${parsed.label}' field`] : [];
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function safeOptionalId(value: string | null, label: string): string[] {
|
|
197
|
+
if (!value) return [];
|
|
198
|
+
return safeFileStem(value) === value ? [] : [`${label} must be path-safe: ${value}`];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function validateRefs(repoRoot: string, refs: string[], label: string): string[] {
|
|
202
|
+
const errors: string[] = [];
|
|
203
|
+
for (const ref of refs) {
|
|
204
|
+
if (typeof ref !== "string" || ref.trim().length === 0) {
|
|
205
|
+
errors.push(`${label} contains an empty ref`);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (ref.includes("\0")) errors.push(`${label} contains NUL byte: ${ref}`);
|
|
209
|
+
const resolved = resolveRepoPath(repoRoot, ref);
|
|
210
|
+
errors.push(...resolved.errors.map((error) => `${label}: ${error}`));
|
|
211
|
+
for (const protectedPattern of DEFAULT_RULES.zeroAccessPaths) {
|
|
212
|
+
if (pathMatches(ref, protectedPattern, repoRoot, repoRoot)) errors.push(`${label} references zero-access path: ${protectedPattern}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return errors;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function validatePathList(repoRoot: string, paths: string[], label: string): string[] {
|
|
219
|
+
return paths.flatMap((path) => validateRefs(repoRoot, [path], label));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function validateForbiddenPathList(paths: string[], label: string): string[] {
|
|
223
|
+
const errors: string[] = [];
|
|
224
|
+
for (const path of paths) {
|
|
225
|
+
if (typeof path !== "string" || path.trim().length === 0) errors.push(`${label} contains an empty path`);
|
|
226
|
+
if (path.includes("\0")) errors.push(`${label} contains NUL byte: ${path}`);
|
|
227
|
+
if (["/", "~", "*", "**"].includes(path.trim())) errors.push(`${label} rejects broad deny-only path: ${path}`);
|
|
228
|
+
}
|
|
229
|
+
return errors;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function recordFromChunk(text: string, chunk: string): { request?: GovernedRequestRecord; errors: string[] } {
|
|
233
|
+
const lines = chunk.split(/\r?\n/);
|
|
234
|
+
const errors = plaintextLabelErrors(lines);
|
|
235
|
+
const deliverable = scalar(lines, ["deliverable_delivered", "deliverable delivered"]);
|
|
236
|
+
if (deliverable?.toLowerCase() !== "yes") errors.push("governed request deliverable_delivered must be yes");
|
|
237
|
+
const kind = parseKind(scalar(lines, ["request_type", "request type"]));
|
|
238
|
+
if (!kind) errors.push("governed request missing valid request_type");
|
|
239
|
+
const requestId = scalar(lines, ["request_id", "request id"]);
|
|
240
|
+
if (!requestId) errors.push("governed request missing request_id");
|
|
241
|
+
const requestedBy = scalar(lines, ["requested_by", "requested by"]);
|
|
242
|
+
if (!requestedBy) errors.push("governed request missing requested_by");
|
|
243
|
+
const requestedAction = scalar(lines, ["requested_action", "requested action"]);
|
|
244
|
+
if (!requestedAction) errors.push("governed request missing requested_action");
|
|
245
|
+
const priority = (scalar(lines, ["priority"]) || "normal").toLowerCase() as GovernedRequestPriority;
|
|
246
|
+
if (!PRIORITIES.has(priority)) errors.push("governed request priority must be low|normal|high|critical");
|
|
247
|
+
const riskLevel = (scalar(lines, ["risk_level", "risk level"]) || "medium").toLowerCase() as GovernedRequestRisk;
|
|
248
|
+
if (!RISKS.has(riskLevel)) errors.push("governed request risk_level must be low|medium|high");
|
|
249
|
+
const bodyHash = scalar(lines, ["body_hash", "body hash"]);
|
|
250
|
+
if (!bodyHash || !SHA256_HEX.test(bodyHash)) errors.push("governed request body_hash must be sha256 hex");
|
|
251
|
+
const noShip = parseBoolean(scalar(lines, ["no_ship", "no ship"]));
|
|
252
|
+
if (noShip === undefined) errors.push("governed request no_ship must be true/false");
|
|
253
|
+
const ownerWorker = scalar(lines, ["owner_worker", "owner worker"]) || null;
|
|
254
|
+
const requestedPaths = listValue(lines, ["requested_paths", "requested paths"]);
|
|
255
|
+
const changeHash = scalar(lines, ["change_hash", "change hash"]) || null;
|
|
256
|
+
const reasonHash = scalar(lines, ["reason_hash", "reason hash"]) || null;
|
|
257
|
+
const validationPlanHash = scalar(lines, ["validation_plan_hash", "validation plan hash"]) || null;
|
|
258
|
+
if (kind === "OWNER_CHANGE_REQUEST") {
|
|
259
|
+
if (!ownerWorker) errors.push("owner change request missing owner_worker");
|
|
260
|
+
if (requestedPaths.length === 0) errors.push("owner change request missing requested_paths");
|
|
261
|
+
if (!changeHash || !SHA256_HEX.test(changeHash)) errors.push("owner change request change_hash must be sha256 hex");
|
|
262
|
+
if (!reasonHash || !SHA256_HEX.test(reasonHash)) errors.push("owner change request reason_hash must be sha256 hex");
|
|
263
|
+
if (validationPlanHash && !SHA256_HEX.test(validationPlanHash)) errors.push("owner change request validation_plan_hash must be sha256 hex");
|
|
264
|
+
}
|
|
265
|
+
const finalMarker = scalar(lines, ["FINAL_MARKER", "final marker"]) ?? "";
|
|
266
|
+
if (kind && finalMarker !== finalMarkerForKind(kind)) errors.push(`governed request final marker must be ${finalMarkerForKind(kind)}`);
|
|
267
|
+
if (errors.length > 0 || !kind || !requestId || !requestedBy || !requestedAction || !bodyHash || noShip === undefined) return { errors };
|
|
268
|
+
const goalId = scalar(lines, ["goal_id", "goal id"]) || null;
|
|
269
|
+
const todoId = scalar(lines, ["todo_id", "todo id"]) || null;
|
|
270
|
+
const sourceOutputHash = sha256(text);
|
|
271
|
+
const stable = {
|
|
272
|
+
contract: contractForKind(kind),
|
|
273
|
+
kind,
|
|
274
|
+
requestId,
|
|
275
|
+
goalId,
|
|
276
|
+
todoId,
|
|
277
|
+
requestedBy,
|
|
278
|
+
requestedAction,
|
|
279
|
+
priority,
|
|
280
|
+
riskLevel,
|
|
281
|
+
bodyHash,
|
|
282
|
+
agent: scalar(lines, ["agent"]) || null,
|
|
283
|
+
outputContract: scalar(lines, ["output_contract", "output contract"]) || null,
|
|
284
|
+
requiredTools: listValue(lines, ["required_tools", "required tools"]),
|
|
285
|
+
allowedPaths: listValue(lines, ["allowed_paths", "allowed paths"]),
|
|
286
|
+
forbiddenPaths: listValue(lines, ["forbidden_paths", "forbidden paths"]),
|
|
287
|
+
contextScopeId: scalar(lines, ["context_scope_id", "context scope id"]) || null,
|
|
288
|
+
ownerWorker,
|
|
289
|
+
requestedPaths,
|
|
290
|
+
changeHash,
|
|
291
|
+
reasonHash,
|
|
292
|
+
validationPlanHash,
|
|
293
|
+
evidenceRefs: listValue(lines, ["evidence_refs", "evidence refs"]),
|
|
294
|
+
artifactRefs: listValue(lines, ["artifact_refs", "artifact refs"]),
|
|
295
|
+
noShip,
|
|
296
|
+
finalMarker,
|
|
297
|
+
};
|
|
298
|
+
return {
|
|
299
|
+
request: {
|
|
300
|
+
schema: "zob.governed-request.v1",
|
|
301
|
+
...stable,
|
|
302
|
+
requestHash: sha256(JSON.stringify(stable)),
|
|
303
|
+
sourceOutputHash,
|
|
304
|
+
parentVisible: true,
|
|
305
|
+
requiresParentAction: true,
|
|
306
|
+
parentOwnedActions: true,
|
|
307
|
+
childDirectDispatch: false,
|
|
308
|
+
canonicalTodoMutation: false,
|
|
309
|
+
dispatchExecuted: false,
|
|
310
|
+
bodyStored: false,
|
|
311
|
+
promptBodiesStored: false,
|
|
312
|
+
outputBodiesStored: false,
|
|
313
|
+
},
|
|
314
|
+
errors: [],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function extractGovernedRequestsFromText(text: string): GovernedRequestExtractionResult {
|
|
319
|
+
const sourceOutputHash = sha256(text);
|
|
320
|
+
const requests: GovernedRequestRecord[] = [];
|
|
321
|
+
const extractionErrors: string[] = [];
|
|
322
|
+
for (const chunk of chunksFromText(text)) {
|
|
323
|
+
const result = recordFromChunk(text, chunk);
|
|
324
|
+
if (result.request) requests.push(result.request);
|
|
325
|
+
extractionErrors.push(...result.errors);
|
|
326
|
+
}
|
|
327
|
+
if (requests.length === 0 && extractionErrors.length === 0) extractionErrors.push("no governed request blocks found");
|
|
328
|
+
return {
|
|
329
|
+
schema: "zob.governed-request-extraction.v1",
|
|
330
|
+
sourceOutputHash,
|
|
331
|
+
requests,
|
|
332
|
+
extractionErrors,
|
|
333
|
+
goalRoomMessageIds: [],
|
|
334
|
+
parentOwnedActions: true,
|
|
335
|
+
childDirectDispatch: false,
|
|
336
|
+
dispatchExecuted: false,
|
|
337
|
+
bodyStored: false,
|
|
338
|
+
promptBodiesStored: false,
|
|
339
|
+
outputBodiesStored: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function validateGovernedRequest(repoRoot: string, definition: TeamDefinition, request: GovernedRequestRecord): string[] {
|
|
344
|
+
const errors: string[] = [];
|
|
345
|
+
if (request.schema !== "zob.governed-request.v1") errors.push("governed request schema must be zob.governed-request.v1");
|
|
346
|
+
if (!REQUEST_TYPES.has(request.kind)) errors.push("governed request kind is invalid");
|
|
347
|
+
if (request.contract !== contractForKind(request.kind)) errors.push("governed request contract does not match request kind");
|
|
348
|
+
if (!request.requestId || safeFileStem(request.requestId) !== request.requestId) errors.push(`requestId must be path-safe: ${request.requestId}`);
|
|
349
|
+
errors.push(...safeOptionalId(request.goalId, "goalId"));
|
|
350
|
+
errors.push(...safeOptionalId(request.todoId, "todoId"));
|
|
351
|
+
if (!knownRoleIds(definition).has(request.requestedBy)) errors.push(`Unknown governed request requester '${request.requestedBy}'`);
|
|
352
|
+
if (request.kind === "OWNER_CHANGE_REQUEST") {
|
|
353
|
+
if (!request.ownerWorker || !knownRoleIds(definition).has(request.ownerWorker)) errors.push(`Unknown owner change request ownerWorker '${request.ownerWorker}'`);
|
|
354
|
+
if (request.requestedPaths.length === 0) errors.push("owner change request requestedPaths are required");
|
|
355
|
+
if (!request.changeHash || !SHA256_HEX.test(request.changeHash)) errors.push("owner change request changeHash must be sha256 hex");
|
|
356
|
+
if (!request.reasonHash || !SHA256_HEX.test(request.reasonHash)) errors.push("owner change request reasonHash must be sha256 hex");
|
|
357
|
+
if (request.validationPlanHash && !SHA256_HEX.test(request.validationPlanHash)) errors.push("owner change request validationPlanHash must be sha256 hex");
|
|
358
|
+
errors.push(...validatePathList(repoRoot, request.requestedPaths, "requestedPaths"));
|
|
359
|
+
}
|
|
360
|
+
if (!PRIORITIES.has(request.priority)) errors.push("governed request priority is invalid");
|
|
361
|
+
if (!RISKS.has(request.riskLevel)) errors.push("governed request riskLevel is invalid");
|
|
362
|
+
if (!SHA256_HEX.test(request.bodyHash)) errors.push("governed request bodyHash must be sha256 hex");
|
|
363
|
+
if (!SHA256_HEX.test(request.requestHash)) errors.push("governed request requestHash must be sha256 hex");
|
|
364
|
+
if (!SHA256_HEX.test(request.sourceOutputHash)) errors.push("governed request sourceOutputHash must be sha256 hex");
|
|
365
|
+
if (request.finalMarker !== finalMarkerForKind(request.kind)) errors.push(`governed request finalMarker must be ${finalMarkerForKind(request.kind)}`);
|
|
366
|
+
if (request.parentVisible !== true || request.requiresParentAction !== true || request.parentOwnedActions !== true || request.childDirectDispatch !== false || request.canonicalTodoMutation !== false || request.dispatchExecuted !== false) errors.push("governed request must be parent-visible, parent-owned, non-mutating, and non-dispatching");
|
|
367
|
+
if (request.bodyStored !== false || request.promptBodiesStored !== false || request.outputBodiesStored !== false) errors.push("governed request must be body-free");
|
|
368
|
+
errors.push(...validatePathList(repoRoot, request.allowedPaths, "allowedPaths"));
|
|
369
|
+
errors.push(...validateForbiddenPathList(request.forbiddenPaths, "forbiddenPaths"));
|
|
370
|
+
errors.push(...validateRefs(repoRoot, request.evidenceRefs, "evidenceRefs"));
|
|
371
|
+
errors.push(...validateRefs(repoRoot, request.artifactRefs, "artifactRefs"));
|
|
372
|
+
return errors;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function appendGovernedRequestsToGoalRoom(repoRoot: string, definition: TeamDefinition, goalId: string, extraction: GovernedRequestExtractionResult): GovernedRequestExtractionResult {
|
|
376
|
+
const goalRoomMessageIds: string[] = [];
|
|
377
|
+
const extractionErrors = [...extraction.extractionErrors];
|
|
378
|
+
for (const request of extraction.requests) {
|
|
379
|
+
const errors = validateGovernedRequest(repoRoot, definition, { ...request, goalId: request.goalId ?? goalId });
|
|
380
|
+
if (errors.length > 0) {
|
|
381
|
+
extractionErrors.push(...errors.map((error) => `${request.requestId}: ${error}`));
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
const message = appendGoalRoomMessage(repoRoot, definition, {
|
|
385
|
+
goal_id: request.goalId ?? goalId,
|
|
386
|
+
todo_id: request.todoId ?? undefined,
|
|
387
|
+
sender: request.requestedBy,
|
|
388
|
+
audience: "parent",
|
|
389
|
+
kind: request.kind,
|
|
390
|
+
priority: request.priority,
|
|
391
|
+
body_hash: request.bodyHash,
|
|
392
|
+
task_id: request.requestId,
|
|
393
|
+
evidence_refs: request.evidenceRefs,
|
|
394
|
+
artifact_refs: request.artifactRefs,
|
|
395
|
+
requires_parent_action: true,
|
|
396
|
+
metadata: {
|
|
397
|
+
governed_request_hash: request.requestHash,
|
|
398
|
+
governed_request_contract: request.contract,
|
|
399
|
+
owner_worker: request.ownerWorker,
|
|
400
|
+
requested_path_hashes: request.requestedPaths.map((path) => sha256(path)),
|
|
401
|
+
change_hash: request.changeHash,
|
|
402
|
+
reason_hash: request.reasonHash,
|
|
403
|
+
validation_plan_hash: request.validationPlanHash,
|
|
404
|
+
requested_action_hash: sha256(request.requestedAction),
|
|
405
|
+
risk_level_hash: sha256(request.riskLevel),
|
|
406
|
+
source_output_hash: request.sourceOutputHash,
|
|
407
|
+
child_direct_dispatch: false,
|
|
408
|
+
canonical_todo_mutation: false,
|
|
409
|
+
dispatch_executed: false,
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
if (typeof message.msgId === "string") goalRoomMessageIds.push(message.msgId);
|
|
413
|
+
}
|
|
414
|
+
return { ...extraction, extractionErrors, goalRoomMessageIds };
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export function governedRequestBodyFreeViolations(value: unknown): string[] {
|
|
418
|
+
const violations: string[] = [];
|
|
419
|
+
const visit = (item: unknown, path: string): void => {
|
|
420
|
+
if (!item || typeof item !== "object") return;
|
|
421
|
+
if (Array.isArray(item)) {
|
|
422
|
+
item.forEach((child, index) => visit(child, `${path}[${index}]`));
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
for (const [key, child] of Object.entries(item as Record<string, unknown>)) {
|
|
426
|
+
if (FORBIDDEN_PLAINTEXT_LABELS.has(key)) violations.push(`${path}.${key}`);
|
|
427
|
+
visit(child, `${path}.${key}`);
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
visit(value, "root");
|
|
431
|
+
return violations;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export function isGovernedRequest(value: unknown): value is GovernedRequestRecord {
|
|
435
|
+
return isRecord(value) && value.schema === "zob.governed-request.v1";
|
|
436
|
+
}
|