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,297 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_RULES } from "./constants.js";
|
|
5
|
+
import type { TeamDefinition } from "./types.js";
|
|
6
|
+
import { sha256 } from "./utils/hashing.js";
|
|
7
|
+
import { readJsonl } from "./utils/json.js";
|
|
8
|
+
import { pathMatches, resolveRepoPath, safeFileStem } from "./utils/paths.js";
|
|
9
|
+
import { isRecord } from "./utils/records.js";
|
|
10
|
+
|
|
11
|
+
export type WorkspaceClaimMode = "read" | "write";
|
|
12
|
+
export type WorkspaceClaimStatus = "active" | "blocked_conflict";
|
|
13
|
+
|
|
14
|
+
export interface WorkspaceClaimInput {
|
|
15
|
+
run_id: string;
|
|
16
|
+
claimant: string;
|
|
17
|
+
paths: string[];
|
|
18
|
+
mode?: WorkspaceClaimMode;
|
|
19
|
+
purpose_hash: string;
|
|
20
|
+
todo_id?: string;
|
|
21
|
+
sandbox_run_id?: string;
|
|
22
|
+
lease_ms?: number;
|
|
23
|
+
allow_conflicts?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface WorkspaceReleaseInput {
|
|
27
|
+
claim_id: string;
|
|
28
|
+
released_by: string;
|
|
29
|
+
reason_hash?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface WorkspaceClaimsListInput {
|
|
33
|
+
run_id?: string;
|
|
34
|
+
claimant?: string;
|
|
35
|
+
include_expired?: boolean;
|
|
36
|
+
include_released?: boolean;
|
|
37
|
+
limit?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface WorkspaceClaimRecord {
|
|
41
|
+
schema: "zob.workspace-claim.v1";
|
|
42
|
+
claimId: string;
|
|
43
|
+
runId: string;
|
|
44
|
+
claimant: string;
|
|
45
|
+
todoId: string | null;
|
|
46
|
+
sandboxRunId: string | null;
|
|
47
|
+
mode: WorkspaceClaimMode;
|
|
48
|
+
status: WorkspaceClaimStatus;
|
|
49
|
+
paths: string[];
|
|
50
|
+
pathHashes: string[];
|
|
51
|
+
purposeHash: string;
|
|
52
|
+
leaseMs: number;
|
|
53
|
+
claimedAt: string;
|
|
54
|
+
expiresAt: string;
|
|
55
|
+
conflicts: WorkspaceConflictWarning[];
|
|
56
|
+
active: boolean;
|
|
57
|
+
parentOwnedResolutionRequired: boolean;
|
|
58
|
+
productionWritesPerformed: false;
|
|
59
|
+
autoApply: false;
|
|
60
|
+
bodyStored: false;
|
|
61
|
+
promptBodiesStored: false;
|
|
62
|
+
outputBodiesStored: false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface WorkspaceReleaseRecord {
|
|
66
|
+
schema: "zob.workspace-release.v1";
|
|
67
|
+
releaseId: string;
|
|
68
|
+
claimId: string;
|
|
69
|
+
releasedBy: string;
|
|
70
|
+
reasonHash: string | null;
|
|
71
|
+
releasedAt: string;
|
|
72
|
+
bodyStored: false;
|
|
73
|
+
promptBodiesStored: false;
|
|
74
|
+
outputBodiesStored: false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface WorkspaceConflictWarning {
|
|
78
|
+
schema: "zob.workspace-conflict-warning.v1";
|
|
79
|
+
claimId: string;
|
|
80
|
+
conflictingClaimIds: string[];
|
|
81
|
+
overlappingPaths: string[];
|
|
82
|
+
conflictHash: string;
|
|
83
|
+
parentOwnedResolutionRequired: true;
|
|
84
|
+
writesBlocked: true;
|
|
85
|
+
bodyStored: false;
|
|
86
|
+
promptBodiesStored: false;
|
|
87
|
+
outputBodiesStored: false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const SHA256_HEX = /^[a-f0-9]{64}$/i;
|
|
91
|
+
const DEFAULT_LEASE_MS = 60 * 60 * 1000;
|
|
92
|
+
const MAX_LEASE_MS = 24 * 60 * 60 * 1000;
|
|
93
|
+
|
|
94
|
+
function workspaceClaimsDir(repoRoot: string): string {
|
|
95
|
+
return join(repoRoot, ".pi", "workspace-claims");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function claimsPath(repoRoot: string): string {
|
|
99
|
+
return join(workspaceClaimsDir(repoRoot), "claims.jsonl");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function releasesPath(repoRoot: string): string {
|
|
103
|
+
return join(workspaceClaimsDir(repoRoot), "releases.jsonl");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function eventsPath(repoRoot: string): string {
|
|
107
|
+
return join(workspaceClaimsDir(repoRoot), "events.jsonl");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function knownRoleIds(definition: TeamDefinition): Set<string> {
|
|
111
|
+
return new Set([definition.orchestrator.id, ...definition.leads.map((lead) => lead.id), ...definition.workers.map((worker) => worker.id), "parent", "mission-control"]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function appendWorkspaceClaimEvent(repoRoot: string, event: Record<string, unknown>): void {
|
|
115
|
+
mkdirSync(workspaceClaimsDir(repoRoot), { recursive: true });
|
|
116
|
+
appendFileSync(eventsPath(repoRoot), `${JSON.stringify({ ...event, timestamp: new Date().toISOString(), bodyStored: false, promptBodiesStored: false, outputBodiesStored: false })}\n`, "utf8");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function validateClaimInput(repoRoot: string, definition: TeamDefinition, input: WorkspaceClaimInput): string[] {
|
|
120
|
+
const errors: string[] = [];
|
|
121
|
+
if (!input.run_id || safeFileStem(input.run_id) !== input.run_id) errors.push(`run_id must be path-safe: ${input.run_id}`);
|
|
122
|
+
if (input.todo_id && safeFileStem(input.todo_id) !== input.todo_id) errors.push(`todo_id must be path-safe: ${input.todo_id}`);
|
|
123
|
+
if (input.sandbox_run_id && safeFileStem(input.sandbox_run_id) !== input.sandbox_run_id) errors.push(`sandbox_run_id must be path-safe: ${input.sandbox_run_id}`);
|
|
124
|
+
if (!knownRoleIds(definition).has(input.claimant)) errors.push(`Unknown workspace claim claimant '${input.claimant}'`);
|
|
125
|
+
if (input.mode !== undefined && input.mode !== "read" && input.mode !== "write") errors.push("workspace claim mode must be read|write");
|
|
126
|
+
if (!SHA256_HEX.test(input.purpose_hash)) errors.push("workspace claim purpose_hash must be sha256 hex");
|
|
127
|
+
if (!Array.isArray(input.paths) || input.paths.length === 0) errors.push("workspace claim requires at least one path");
|
|
128
|
+
if (input.paths.length > 50) errors.push("workspace claim paths are capped at 50");
|
|
129
|
+
for (const path of input.paths ?? []) {
|
|
130
|
+
if (typeof path !== "string" || path.trim().length === 0) {
|
|
131
|
+
errors.push("workspace claim contains an empty path");
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const resolved = resolveRepoPath(repoRoot, path);
|
|
135
|
+
errors.push(...resolved.errors.map((error) => `workspace claim path: ${error}`));
|
|
136
|
+
for (const protectedPattern of DEFAULT_RULES.zeroAccessPaths) {
|
|
137
|
+
if (pathMatches(path, protectedPattern, repoRoot, repoRoot)) errors.push(`workspace claim path references zero-access path: ${protectedPattern}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (input.lease_ms !== undefined && (!Number.isFinite(input.lease_ms) || input.lease_ms <= 0 || input.lease_ms > MAX_LEASE_MS)) errors.push("workspace claim lease_ms must be positive and <= 24h");
|
|
141
|
+
return errors;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function normalizedPath(repoRoot: string, path: string): string {
|
|
145
|
+
return resolveRepoPath(repoRoot, path).path.replace(/\/+$/g, "");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function pathsOverlap(repoRoot: string, left: string, right: string): boolean {
|
|
149
|
+
const a = normalizedPath(repoRoot, left);
|
|
150
|
+
const b = normalizedPath(repoRoot, right);
|
|
151
|
+
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function isReleased(claimId: string, releases: WorkspaceReleaseRecord[]): boolean {
|
|
155
|
+
return releases.some((release) => release.claimId === claimId);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function isExpired(claim: WorkspaceClaimRecord, nowMs = Date.now()): boolean {
|
|
159
|
+
const expiresAt = Date.parse(claim.expiresAt);
|
|
160
|
+
return Number.isFinite(expiresAt) && expiresAt <= nowMs;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function readClaims(repoRoot: string): WorkspaceClaimRecord[] {
|
|
164
|
+
return readJsonl(claimsPath(repoRoot)).filter(isWorkspaceClaimRecord).map((record) => record as unknown as WorkspaceClaimRecord);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function readReleases(repoRoot: string): WorkspaceReleaseRecord[] {
|
|
168
|
+
return readJsonl(releasesPath(repoRoot)).filter(isWorkspaceReleaseRecord).map((record) => record as unknown as WorkspaceReleaseRecord);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function activeClaims(repoRoot: string, nowMs = Date.now()): WorkspaceClaimRecord[] {
|
|
172
|
+
const releases = readReleases(repoRoot);
|
|
173
|
+
return readClaims(repoRoot).filter((claim) => claim.status === "active" && !isExpired(claim, nowMs) && !isReleased(claim.claimId, releases));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function conflictWarnings(repoRoot: string, claimId: string, paths: string[], mode: WorkspaceClaimMode): WorkspaceConflictWarning[] {
|
|
177
|
+
if (mode !== "write") return [];
|
|
178
|
+
const conflicts = activeClaims(repoRoot).flatMap((claim) => {
|
|
179
|
+
const overlaps = paths.filter((path) => claim.paths.some((claimedPath) => pathsOverlap(repoRoot, path, claimedPath)));
|
|
180
|
+
if (overlaps.length === 0) return [];
|
|
181
|
+
return [{ claim, overlaps }];
|
|
182
|
+
});
|
|
183
|
+
if (conflicts.length === 0) return [];
|
|
184
|
+
const overlappingPaths = [...new Set(conflicts.flatMap((conflict) => conflict.overlaps))].sort();
|
|
185
|
+
const conflictingClaimIds = conflicts.map((conflict) => conflict.claim.claimId).sort();
|
|
186
|
+
return [{
|
|
187
|
+
schema: "zob.workspace-conflict-warning.v1",
|
|
188
|
+
claimId,
|
|
189
|
+
conflictingClaimIds,
|
|
190
|
+
overlappingPaths,
|
|
191
|
+
conflictHash: sha256(JSON.stringify({ claimId, conflictingClaimIds, overlappingPaths })),
|
|
192
|
+
parentOwnedResolutionRequired: true,
|
|
193
|
+
writesBlocked: true,
|
|
194
|
+
bodyStored: false,
|
|
195
|
+
promptBodiesStored: false,
|
|
196
|
+
outputBodiesStored: false,
|
|
197
|
+
}];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function createWorkspaceClaim(repoRoot: string, definition: TeamDefinition, input: WorkspaceClaimInput): WorkspaceClaimRecord {
|
|
201
|
+
const errors = validateClaimInput(repoRoot, definition, input);
|
|
202
|
+
if (errors.length > 0) throw new Error(errors.join("; "));
|
|
203
|
+
const now = Date.now();
|
|
204
|
+
const leaseMs = Math.floor(input.lease_ms ?? DEFAULT_LEASE_MS);
|
|
205
|
+
const claimId = `wclaim_${sha256(`${input.run_id}:${input.claimant}:${input.paths.join("|")}:${input.purpose_hash}:${now}`).slice(0, 16)}`;
|
|
206
|
+
const mode = input.mode ?? "write";
|
|
207
|
+
const conflicts = conflictWarnings(repoRoot, claimId, input.paths, mode);
|
|
208
|
+
const blocked = conflicts.length > 0 && input.allow_conflicts !== true;
|
|
209
|
+
const record: WorkspaceClaimRecord = {
|
|
210
|
+
schema: "zob.workspace-claim.v1",
|
|
211
|
+
claimId,
|
|
212
|
+
runId: input.run_id,
|
|
213
|
+
claimant: input.claimant,
|
|
214
|
+
todoId: input.todo_id ?? null,
|
|
215
|
+
sandboxRunId: input.sandbox_run_id ?? null,
|
|
216
|
+
mode,
|
|
217
|
+
status: blocked ? "blocked_conflict" : "active",
|
|
218
|
+
paths: [...new Set(input.paths)].sort(),
|
|
219
|
+
pathHashes: [...new Set(input.paths)].sort().map((path) => sha256(path)),
|
|
220
|
+
purposeHash: input.purpose_hash,
|
|
221
|
+
leaseMs,
|
|
222
|
+
claimedAt: new Date(now).toISOString(),
|
|
223
|
+
expiresAt: new Date(now + leaseMs).toISOString(),
|
|
224
|
+
conflicts,
|
|
225
|
+
active: !blocked,
|
|
226
|
+
parentOwnedResolutionRequired: blocked,
|
|
227
|
+
productionWritesPerformed: false,
|
|
228
|
+
autoApply: false,
|
|
229
|
+
bodyStored: false,
|
|
230
|
+
promptBodiesStored: false,
|
|
231
|
+
outputBodiesStored: false,
|
|
232
|
+
};
|
|
233
|
+
mkdirSync(workspaceClaimsDir(repoRoot), { recursive: true });
|
|
234
|
+
if (!blocked) appendFileSync(claimsPath(repoRoot), `${JSON.stringify(record)}\n`, "utf8");
|
|
235
|
+
appendWorkspaceClaimEvent(repoRoot, { event: blocked ? "conflict_blocked" : "claim_active", claimId, runId: record.runId, claimant: record.claimant, mode: record.mode, paths: record.paths, conflicts, productionWritesPerformed: false, autoApply: false });
|
|
236
|
+
return record;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function releaseWorkspaceClaim(repoRoot: string, definition: TeamDefinition, input: WorkspaceReleaseInput): WorkspaceReleaseRecord {
|
|
240
|
+
if (!input.claim_id || safeFileStem(input.claim_id) !== input.claim_id) throw new Error(`claim_id must be path-safe: ${input.claim_id}`);
|
|
241
|
+
if (!knownRoleIds(definition).has(input.released_by)) throw new Error(`Unknown workspace release actor '${input.released_by}'`);
|
|
242
|
+
if (input.reason_hash !== undefined && !SHA256_HEX.test(input.reason_hash)) throw new Error("workspace release reason_hash must be sha256 hex");
|
|
243
|
+
const claim = readClaims(repoRoot).find((candidate) => candidate.claimId === input.claim_id);
|
|
244
|
+
if (!claim) throw new Error(`workspace claim not found: ${input.claim_id}`);
|
|
245
|
+
const record: WorkspaceReleaseRecord = {
|
|
246
|
+
schema: "zob.workspace-release.v1",
|
|
247
|
+
releaseId: `wrelease_${sha256(`${input.claim_id}:${input.released_by}:${Date.now()}`).slice(0, 16)}`,
|
|
248
|
+
claimId: input.claim_id,
|
|
249
|
+
releasedBy: input.released_by,
|
|
250
|
+
reasonHash: input.reason_hash ?? null,
|
|
251
|
+
releasedAt: new Date().toISOString(),
|
|
252
|
+
bodyStored: false,
|
|
253
|
+
promptBodiesStored: false,
|
|
254
|
+
outputBodiesStored: false,
|
|
255
|
+
};
|
|
256
|
+
mkdirSync(workspaceClaimsDir(repoRoot), { recursive: true });
|
|
257
|
+
appendFileSync(releasesPath(repoRoot), `${JSON.stringify(record)}\n`, "utf8");
|
|
258
|
+
appendWorkspaceClaimEvent(repoRoot, { event: "claim_released", claimId: record.claimId, releaseId: record.releaseId, releasedBy: record.releasedBy });
|
|
259
|
+
return record;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function listWorkspaceClaims(repoRoot: string, input: WorkspaceClaimsListInput = {}): WorkspaceClaimRecord[] {
|
|
263
|
+
const releases = readReleases(repoRoot);
|
|
264
|
+
const limit = Math.max(1, Math.min(100, Math.floor(input.limit ?? 20)));
|
|
265
|
+
return readClaims(repoRoot)
|
|
266
|
+
.filter((claim) => !input.run_id || claim.runId === input.run_id)
|
|
267
|
+
.filter((claim) => !input.claimant || claim.claimant === input.claimant)
|
|
268
|
+
.filter((claim) => input.include_expired === true || !isExpired(claim))
|
|
269
|
+
.filter((claim) => input.include_released === true || !isReleased(claim.claimId, releases))
|
|
270
|
+
.slice(-limit);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function workspaceClaimBodyFreeViolations(value: unknown): string[] {
|
|
274
|
+
const forbidden = new Set(["body", "task", "prompt", "output", "content", "patch", "diff"]);
|
|
275
|
+
const violations: string[] = [];
|
|
276
|
+
const visit = (item: unknown, path: string): void => {
|
|
277
|
+
if (!item || typeof item !== "object") return;
|
|
278
|
+
if (Array.isArray(item)) {
|
|
279
|
+
item.forEach((child, index) => visit(child, `${path}[${index}]`));
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
for (const [key, child] of Object.entries(item as Record<string, unknown>)) {
|
|
283
|
+
if (forbidden.has(key)) violations.push(`${path}.${key}`);
|
|
284
|
+
visit(child, `${path}.${key}`);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
visit(value, "root");
|
|
288
|
+
return violations;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function isWorkspaceClaimRecord(value: unknown): value is WorkspaceClaimRecord {
|
|
292
|
+
return isRecord(value) && value.schema === "zob.workspace-claim.v1" && typeof value.claimId === "string" && typeof value.runId === "string" && Array.isArray(value.paths) && value.bodyStored === false && value.productionWritesPerformed === false && value.autoApply === false;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function isWorkspaceReleaseRecord(value: unknown): value is WorkspaceReleaseRecord {
|
|
296
|
+
return isRecord(value) && value.schema === "zob.workspace-release.v1" && typeof value.claimId === "string" && value.bodyStored === false;
|
|
297
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
|
|
5
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import type { AutocompleteItem } from "@earendil-works/pi-tui";
|
|
7
|
+
|
|
8
|
+
const SETTINGS_PATH = join(".pi", "settings.json");
|
|
9
|
+
const SNAPSHOT_PATH = join(".pi", "tmp", "zob-switch", "settings-snapshot.json");
|
|
10
|
+
const SWITCH_EXTENSION = "extensions/zob-switch/index.ts";
|
|
11
|
+
const HARNESS_EXTENSION = "extensions/zob-harness/index.ts";
|
|
12
|
+
const ZOB_PROMPTS = "prompts";
|
|
13
|
+
const ZOB_SKILLS = "skills";
|
|
14
|
+
|
|
15
|
+
type JsonObject = Record<string, unknown>;
|
|
16
|
+
|
|
17
|
+
type Snapshot = {
|
|
18
|
+
schema: "zob.harness-switch.settings-snapshot.v1";
|
|
19
|
+
savedAt: string;
|
|
20
|
+
settings: JsonObject;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function isObject(value: unknown): value is JsonObject {
|
|
24
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function asStringArray(value: unknown): string[] {
|
|
28
|
+
return Array.isArray(value) ? value.filter((entry): entry is string => typeof entry === "string") : [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function uniqueWithRequiredFirst(values: string[], requiredFirst: string[]): string[] {
|
|
32
|
+
const result: string[] = [];
|
|
33
|
+
for (const value of [...requiredFirst, ...values]) {
|
|
34
|
+
if (!result.includes(value)) result.push(value);
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function withoutValues(values: string[], remove: string[]): string[] {
|
|
40
|
+
return values.filter((value) => !remove.includes(value));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function hasValue(settings: JsonObject, key: "extensions" | "prompts" | "skills", value: string): boolean {
|
|
44
|
+
return asStringArray(settings[key]).includes(value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function readSettings(cwd: string): Promise<JsonObject> {
|
|
48
|
+
const raw = await readFile(join(cwd, SETTINGS_PATH), "utf8");
|
|
49
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
50
|
+
if (!isObject(parsed)) throw new Error(`${SETTINGS_PATH} must contain a JSON object`);
|
|
51
|
+
return parsed;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function writeSettings(cwd: string, settings: JsonObject): Promise<void> {
|
|
55
|
+
await writeFile(join(cwd, SETTINGS_PATH), `${JSON.stringify(settings, null, 2)}\n`, "utf8");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function writeSnapshot(cwd: string, settings: JsonObject): Promise<void> {
|
|
59
|
+
const snapshot: Snapshot = {
|
|
60
|
+
schema: "zob.harness-switch.settings-snapshot.v1",
|
|
61
|
+
savedAt: new Date().toISOString(),
|
|
62
|
+
settings,
|
|
63
|
+
};
|
|
64
|
+
const snapshotPath = join(cwd, SNAPSHOT_PATH);
|
|
65
|
+
await mkdir(dirname(snapshotPath), { recursive: true });
|
|
66
|
+
await writeFile(snapshotPath, `${JSON.stringify(snapshot, null, 2)}\n`, "utf8");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function readSnapshot(cwd: string): Promise<Snapshot | null> {
|
|
70
|
+
const snapshotPath = join(cwd, SNAPSHOT_PATH);
|
|
71
|
+
if (!existsSync(snapshotPath)) return null;
|
|
72
|
+
const parsed = JSON.parse(await readFile(snapshotPath, "utf8")) as unknown;
|
|
73
|
+
if (!isObject(parsed) || parsed.schema !== "zob.harness-switch.settings-snapshot.v1" || !isObject(parsed.settings)) {
|
|
74
|
+
throw new Error(`${SNAPSHOT_PATH} is not a valid ZOB switch snapshot`);
|
|
75
|
+
}
|
|
76
|
+
return parsed as Snapshot;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function shouldWriteOffSnapshot(current: JsonObject, snapshot: Snapshot | null): boolean {
|
|
80
|
+
return snapshot === null || hasValue(current, "extensions", HARNESS_EXTENSION);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function buildOffSettings(current: JsonObject): JsonObject {
|
|
84
|
+
return {
|
|
85
|
+
...current,
|
|
86
|
+
extensions: uniqueWithRequiredFirst(withoutValues(asStringArray(current.extensions), [HARNESS_EXTENSION]), [SWITCH_EXTENSION]),
|
|
87
|
+
prompts: withoutValues(asStringArray(current.prompts), [ZOB_PROMPTS]),
|
|
88
|
+
skills: withoutValues(asStringArray(current.skills), [ZOB_SKILLS]),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function buildOnSettings(base: JsonObject, usedSnapshot: boolean): JsonObject {
|
|
93
|
+
return {
|
|
94
|
+
...base,
|
|
95
|
+
extensions: uniqueWithRequiredFirst(asStringArray(base.extensions), [SWITCH_EXTENSION, HARNESS_EXTENSION]),
|
|
96
|
+
prompts: usedSnapshot ? asStringArray(base.prompts) : uniqueWithRequiredFirst(asStringArray(base.prompts), [ZOB_PROMPTS]),
|
|
97
|
+
skills: usedSnapshot ? asStringArray(base.skills) : uniqueWithRequiredFirst(asStringArray(base.skills), [ZOB_SKILLS]),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function statusFor(settings: JsonObject, snapshotPresent: boolean): string {
|
|
102
|
+
const switchConfigured = hasValue(settings, "extensions", SWITCH_EXTENSION);
|
|
103
|
+
const harnessConfigured = hasValue(settings, "extensions", HARNESS_EXTENSION);
|
|
104
|
+
const promptsConfigured = hasValue(settings, "prompts", ZOB_PROMPTS);
|
|
105
|
+
const skillsConfigured = hasValue(settings, "skills", ZOB_SKILLS);
|
|
106
|
+
const state = switchConfigured && harnessConfigured && promptsConfigured && skillsConfigured
|
|
107
|
+
? "on"
|
|
108
|
+
: switchConfigured && !harnessConfigured && !promptsConfigured && !skillsConfigured
|
|
109
|
+
? "off"
|
|
110
|
+
: "partial";
|
|
111
|
+
return [
|
|
112
|
+
`ZOB Harness switch: ${state}`,
|
|
113
|
+
`switch extension: ${switchConfigured ? "configured" : "missing"}`,
|
|
114
|
+
`harness extension: ${harnessConfigured ? "configured" : "missing"}`,
|
|
115
|
+
`prompts: ${promptsConfigured ? "configured" : "missing"}`,
|
|
116
|
+
`skills: ${skillsConfigured ? "configured" : "missing"}`,
|
|
117
|
+
`snapshot: ${snapshotPresent ? "present" : "missing"}`,
|
|
118
|
+
].join("\n");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function argumentCompletions(prefix: string): AutocompleteItem[] | null {
|
|
122
|
+
const query = prefix.trim().toLowerCase();
|
|
123
|
+
const items: AutocompleteItem[] = [
|
|
124
|
+
{ value: "on", label: "on", description: "restore ZOB Harness from snapshot/defaults and reload" },
|
|
125
|
+
{ value: "off", label: "off", description: "snapshot settings, unload ZOB Harness resources, and reload" },
|
|
126
|
+
{ value: "status", label: "status", description: "show switch/harness/prompts/skills/snapshot state" },
|
|
127
|
+
];
|
|
128
|
+
const filtered = query ? items.filter((item) => item.value.startsWith(query)) : items;
|
|
129
|
+
return filtered.length > 0 ? filtered : null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export default function zobSwitch(pi: ExtensionAPI): void {
|
|
133
|
+
pi.registerCommand("zob", {
|
|
134
|
+
description: "Switch ZOB Harness on/off or show status: /zob on|off|status",
|
|
135
|
+
getArgumentCompletions: argumentCompletions,
|
|
136
|
+
handler: async (args, ctx) => {
|
|
137
|
+
const action = args.trim().toLowerCase();
|
|
138
|
+
const projectSettingsAvailable = existsSync(join(ctx.cwd, SETTINGS_PATH));
|
|
139
|
+
if (!projectSettingsAvailable) {
|
|
140
|
+
const globalMessage = [
|
|
141
|
+
"ZOB Harness switch: global package loaded",
|
|
142
|
+
"project switch: unavailable in this cwd (no .pi/settings.json)",
|
|
143
|
+
"global disable: use `pi remove /Users/cgarrot/zob/zob-harness` outside Pi if needed",
|
|
144
|
+
].join("\n");
|
|
145
|
+
ctx.ui.notify(action === "" || action === "status" ? globalMessage : `${globalMessage}\n/zob on|off only edits project-local .pi/settings.json when present.`, action === "" || action === "status" ? "info" : "warning");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (action === "off") {
|
|
150
|
+
const current = await readSettings(ctx.cwd);
|
|
151
|
+
const snapshot = await readSnapshot(ctx.cwd);
|
|
152
|
+
if (shouldWriteOffSnapshot(current, snapshot)) {
|
|
153
|
+
await writeSnapshot(ctx.cwd, current);
|
|
154
|
+
}
|
|
155
|
+
await writeSettings(ctx.cwd, buildOffSettings(current));
|
|
156
|
+
ctx.ui.notify("ZOB Harness switched off. Reloading Pi resources...", "info");
|
|
157
|
+
await ctx.reload();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (action === "on") {
|
|
162
|
+
const snapshot = await readSnapshot(ctx.cwd);
|
|
163
|
+
const base = snapshot?.settings ?? await readSettings(ctx.cwd);
|
|
164
|
+
await writeSettings(ctx.cwd, buildOnSettings(base, Boolean(snapshot)));
|
|
165
|
+
ctx.ui.notify(`ZOB Harness switched on${snapshot ? " from snapshot" : " with safe defaults"}. Reloading Pi resources...`, "info");
|
|
166
|
+
await ctx.reload();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (action === "" || action === "status") {
|
|
171
|
+
const settings = await readSettings(ctx.cwd);
|
|
172
|
+
const snapshot = await readSnapshot(ctx.cwd);
|
|
173
|
+
ctx.ui.notify(statusFor(settings, Boolean(snapshot)), "info");
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
ctx.ui.notify("Usage: /zob on|off|status", "error");
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"factory": "budget-preflight-dry-run",
|
|
3
|
+
"description": "Batch manifest for gated budget preflight dry-run coverage across safe local source, runtime, smoke, and operating-model evidence. Agentic batch requires completed pilot proof, persisted pilot oracle review, explicit concurrency cap, and batch gate validation.",
|
|
4
|
+
"items": [
|
|
5
|
+
{
|
|
6
|
+
"id": "budget-helper-source-batch",
|
|
7
|
+
"path": ".pi/extensions/zob-harness/src/chronicle.ts",
|
|
8
|
+
"metadata": {
|
|
9
|
+
"source": "local-source",
|
|
10
|
+
"batch": true,
|
|
11
|
+
"focus": "evaluateBudgetPreflightDryRun and chronicle completion gates"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "factory-runtime-batch",
|
|
16
|
+
"path": ".pi/extensions/zob-harness/src/runtime/tools-factory.ts",
|
|
17
|
+
"metadata": {
|
|
18
|
+
"source": "local-source",
|
|
19
|
+
"batch": true,
|
|
20
|
+
"focus": "agentic factory runtime sentinels and chronicle failure handling"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "factory-validation-batch",
|
|
25
|
+
"path": ".pi/extensions/zob-harness/src/factory/validation.ts",
|
|
26
|
+
"metadata": {
|
|
27
|
+
"source": "local-source",
|
|
28
|
+
"batch": true,
|
|
29
|
+
"focus": "batch gate validation for pilot, oracle, and concurrency prerequisites"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "harness-smoke-batch",
|
|
34
|
+
"path": "scripts/harness-smoke.mjs",
|
|
35
|
+
"metadata": {
|
|
36
|
+
"source": "local-smoke",
|
|
37
|
+
"batch": true,
|
|
38
|
+
"focus": "smoke assertions for factory gates and no-execution safety"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "operating-model-batch",
|
|
43
|
+
"path": "docs/OPERATING_MODEL.md",
|
|
44
|
+
"metadata": {
|
|
45
|
+
"source": "local-doc",
|
|
46
|
+
"batch": true,
|
|
47
|
+
"focus": "operating model for advisory budgets, gates, and no body storage"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"expectedArtifacts": [
|
|
52
|
+
"patterns.canonical.json",
|
|
53
|
+
"risks.canonical.json",
|
|
54
|
+
"workflow-rules.md",
|
|
55
|
+
"agent-instructions.md",
|
|
56
|
+
"quality-gates.json",
|
|
57
|
+
"dashboard-summary.md"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "budget-preflight-dry-run",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Smoke-first read-only lot for validating deterministic budget preflight dry-run behavior without enforcement or execution.",
|
|
5
|
+
"defaultMode": "smoke",
|
|
6
|
+
"requiredStages": [
|
|
7
|
+
"manifest_loaded",
|
|
8
|
+
"agentic_plan_written",
|
|
9
|
+
"item_processed",
|
|
10
|
+
"patterns_canonicalized",
|
|
11
|
+
"risks_canonicalized",
|
|
12
|
+
"quality_gates_written",
|
|
13
|
+
"validation",
|
|
14
|
+
"sentinel"
|
|
15
|
+
],
|
|
16
|
+
"expectedArtifacts": [
|
|
17
|
+
"patterns.canonical.json",
|
|
18
|
+
"risks.canonical.json",
|
|
19
|
+
"workflow-rules.md",
|
|
20
|
+
"agent-instructions.md",
|
|
21
|
+
"quality-gates.json",
|
|
22
|
+
"dashboard-summary.md"
|
|
23
|
+
],
|
|
24
|
+
"stages": [
|
|
25
|
+
{
|
|
26
|
+
"name": "map-budget-preflight-helper",
|
|
27
|
+
"type": "map",
|
|
28
|
+
"agent": "explore",
|
|
29
|
+
"outputContract": "explore.v1",
|
|
30
|
+
"requiredTools": ["read", "grep", "find", "ls"],
|
|
31
|
+
"expectedOutcome": "Map the local budget preflight dry-run helper and smoke coverage for pass/fail caps, advisory metadata, and no-execution flags.",
|
|
32
|
+
"promptTemplate": "Analyze budget preflight dry-run item {item.id} at {item.path}. Verify the helper is deterministic and read-only, reports maxCostUsd, maxRuns, maxDurationMs, and maxParallelChildren, exposes advisory wouldExceed/strictEnabled:false metadata, and exposes dryRun/no-execution flags. Return literal_request, actual_need, success_looks_like, files, answer, gaps, next_steps, evidence, risks/blockers, compliance, and deliverable_delivered.",
|
|
33
|
+
"mustDo": [
|
|
34
|
+
"Read the item path before conclusions.",
|
|
35
|
+
"Cite helper and smoke assertion evidence.",
|
|
36
|
+
"Keep the result focused on dry-run preflight only."
|
|
37
|
+
],
|
|
38
|
+
"mustNotDo": [
|
|
39
|
+
"No edits.",
|
|
40
|
+
"No secrets.",
|
|
41
|
+
"No budget enforcement.",
|
|
42
|
+
"No child dispatch.",
|
|
43
|
+
"No daemons, model routing, pilot, batch, browser, write-adapter, or cloud actions."
|
|
44
|
+
],
|
|
45
|
+
"context": "Factory {factory.name} run {run.id}; map stage for {item.id} at {item.path}. Outputs directory: {outputs.dir}."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "reduce-budget-preflight-evidence",
|
|
49
|
+
"type": "reduce",
|
|
50
|
+
"agent": "synthesis",
|
|
51
|
+
"outputContract": "synthesis.v1",
|
|
52
|
+
"requiredTools": ["read", "grep", "find", "ls"],
|
|
53
|
+
"expectedOutcome": "Synthesize pass/fail cap and no-execution evidence into a smoke-first readiness verdict.",
|
|
54
|
+
"promptTemplate": "Synthesize budget preflight dry-run map outputs for factory {factory.name} run {run.id}. Read outputs from {outputs.dir}. Produce consensus, conflicts, missing_evidence, recommended_next_action, tasks_to_rerun, evidence, risks/blockers, compliance, and deliverable_delivered. Confirm this remains dry-run advisory behavior only.",
|
|
55
|
+
"mustDo": [
|
|
56
|
+
"Confirm all four cap checks are represented.",
|
|
57
|
+
"Confirm mode:advisory, wouldExceed, strictEnabled:false, budgetEnforced:false, dryRun, modelRouterUsed:false, daemonStarted:false, childDispatchAllowed:false, and noExecution:true are represented.",
|
|
58
|
+
"Identify missing smoke evidence if present."
|
|
59
|
+
],
|
|
60
|
+
"mustNotDo": [
|
|
61
|
+
"No edits outside the run directory.",
|
|
62
|
+
"No invented evidence.",
|
|
63
|
+
"No secrets.",
|
|
64
|
+
"No budget enforcement.",
|
|
65
|
+
"No child dispatch.",
|
|
66
|
+
"No daemons, model routing, pilot, batch, browser, write-adapter, or cloud actions."
|
|
67
|
+
],
|
|
68
|
+
"context": "Factory {factory.name} reduce stage for run {run.id}."
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "validate-budget-preflight-dry-run",
|
|
72
|
+
"type": "validate",
|
|
73
|
+
"agent": "oracle-merge",
|
|
74
|
+
"outputContract": "oracle-merge.v1",
|
|
75
|
+
"requiredTools": ["read", "grep", "find", "ls"],
|
|
76
|
+
"expectedOutcome": "Validate budget preflight dry-run lot artifacts and produce PASS/FAIL/WARN with no_ship decision.",
|
|
77
|
+
"promptTemplate": "Validate factory {factory.name} run {run.id}. Check manifest, outputs, checkpoints, validation.json, final-report.md, telemetry.json, and DONE.sentinel under {run.dir}. Return verdict, confidence, no_ship, blockers, notes, evidence, merged_lanes, risks/blockers, compliance, and deliverable_delivered.",
|
|
78
|
+
"mustDo": [
|
|
79
|
+
"Fail if sentinel or validation evidence is missing.",
|
|
80
|
+
"Fail if the lot implies real budget enforcement or child execution.",
|
|
81
|
+
"Cite exact artifact paths."
|
|
82
|
+
],
|
|
83
|
+
"mustNotDo": [
|
|
84
|
+
"No patches.",
|
|
85
|
+
"No commits.",
|
|
86
|
+
"No secrets.",
|
|
87
|
+
"No budget enforcement.",
|
|
88
|
+
"No child dispatch.",
|
|
89
|
+
"No daemons, model routing, pilot, batch, browser, write-adapter, or cloud actions."
|
|
90
|
+
],
|
|
91
|
+
"context": "Factory {factory.name} validation stage for run {run.id}."
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"factory": "budget-preflight-dry-run",
|
|
3
|
+
"description": "Pilot manifest for budget preflight dry-run coverage across safe local source and smoke evidence. Agentic pilot requires completed smoke proof, persisted oracle review, and explicit pilot gate validation; agentic batch requires a separate pilot oracle review, concurrency cap, and batch manifest.",
|
|
4
|
+
"items": [
|
|
5
|
+
{
|
|
6
|
+
"id": "budget-helper-source",
|
|
7
|
+
"path": ".pi/extensions/zob-harness/src/chronicle.ts",
|
|
8
|
+
"metadata": {
|
|
9
|
+
"source": "local-source",
|
|
10
|
+
"pilot": true,
|
|
11
|
+
"focus": "evaluateBudgetPreflightDryRun helper"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "budget-helper-export",
|
|
16
|
+
"path": ".pi/extensions/zob-harness/index.ts",
|
|
17
|
+
"metadata": {
|
|
18
|
+
"source": "local-source",
|
|
19
|
+
"pilot": true,
|
|
20
|
+
"focus": "exported budget preflight helper"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "budget-helper-smoke",
|
|
25
|
+
"path": "scripts/harness-smoke.mjs",
|
|
26
|
+
"metadata": {
|
|
27
|
+
"source": "local-smoke",
|
|
28
|
+
"pilot": true,
|
|
29
|
+
"focus": "pass/fail cap smoke assertions"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "budget-helper-operating-model",
|
|
34
|
+
"path": "docs/OPERATING_MODEL.md",
|
|
35
|
+
"metadata": {
|
|
36
|
+
"source": "local-doc",
|
|
37
|
+
"pilot": true,
|
|
38
|
+
"focus": "budget advisory/no enforcement operating model"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"expectedArtifacts": [
|
|
43
|
+
"patterns.canonical.json",
|
|
44
|
+
"risks.canonical.json",
|
|
45
|
+
"workflow-rules.md",
|
|
46
|
+
"agent-instructions.md",
|
|
47
|
+
"quality-gates.json",
|
|
48
|
+
"dashboard-summary.md"
|
|
49
|
+
]
|
|
50
|
+
}
|