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,217 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
|
+
|
|
6
|
+
const repoRoot = process.cwd();
|
|
7
|
+
|
|
8
|
+
const LEGACY_CASES = [
|
|
9
|
+
{
|
|
10
|
+
id: "factory-schema-validation",
|
|
11
|
+
query: "factory schema validation",
|
|
12
|
+
required_citation_includes: ["factory.json", "schemas/"],
|
|
13
|
+
required_files_to_read_first: ["factory.json"],
|
|
14
|
+
expected_patterns: [],
|
|
15
|
+
required_safety: ["bounded_context_only", "citation_required", "no_knowledge_backend_write"],
|
|
16
|
+
score_threshold: 5,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "config-or-testing-gap",
|
|
20
|
+
query: "testing config pattern",
|
|
21
|
+
required_citation_includes: ["README.md"],
|
|
22
|
+
required_files_to_read_first: ["README.md"],
|
|
23
|
+
expected_patterns: [],
|
|
24
|
+
required_safety: ["bounded_context_only", "citation_required", "no_knowledge_backend_write"],
|
|
25
|
+
score_threshold: 5,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "manifest-compute-profile",
|
|
29
|
+
query: "manifest compute profile caps",
|
|
30
|
+
required_citation_includes: ["example-project-dna-manifest.json"],
|
|
31
|
+
required_files_to_read_first: ["example-project-dna-manifest.json"],
|
|
32
|
+
expected_patterns: [],
|
|
33
|
+
required_safety: ["bounded_context_only", "citation_required", "no_knowledge_backend_write"],
|
|
34
|
+
score_threshold: 5,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "context-pack-schema",
|
|
38
|
+
query: "context pack schema citations loading rules",
|
|
39
|
+
required_citation_includes: ["schemas/context-pack.schema.json"],
|
|
40
|
+
required_files_to_read_first: ["schemas/context-pack.schema.json"],
|
|
41
|
+
expected_patterns: [],
|
|
42
|
+
required_safety: ["bounded_context_only", "citation_required", "no_knowledge_backend_write"],
|
|
43
|
+
score_threshold: 5,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
function usage() {
|
|
48
|
+
console.error(`Usage:
|
|
49
|
+
node scripts/project-dna/bench-smoke.mjs --scan-dir <repo-relative-scan-dir> [--out <repo-relative-json>]
|
|
50
|
+
|
|
51
|
+
Runs a deterministic ProjectDNA retrieval/sample smoke benchmark. Does not call LLMs or external knowledge backend.`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseArgs(argv) {
|
|
55
|
+
const out = {};
|
|
56
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
57
|
+
const arg = argv[i];
|
|
58
|
+
if (arg === "--scan-dir") out.scanDir = argv[++i];
|
|
59
|
+
else if (arg === "--out") out.out = argv[++i];
|
|
60
|
+
else if (arg === "--help" || arg === "-h") out.help = true;
|
|
61
|
+
else throw new Error(`unknown argument: ${arg}`);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function resolveRepoPath(input, label, allowMissing = false) {
|
|
67
|
+
if (!input || isAbsolute(input)) throw new Error(`${label} must be repo-relative`);
|
|
68
|
+
const resolved = resolve(repoRoot, input);
|
|
69
|
+
const rel = relative(repoRoot, resolved);
|
|
70
|
+
if (rel.startsWith("..") || rel === "") throw new Error(`${label} must stay inside repo and not be repo root`);
|
|
71
|
+
if (!allowMissing && !existsSync(resolved)) throw new Error(`${label} not found: ${input}`);
|
|
72
|
+
return resolved;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function runNode(args) {
|
|
76
|
+
return execFileSync(process.execPath, args, { cwd: repoRoot, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function readJson(path) {
|
|
80
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function optionalJson(path) {
|
|
84
|
+
return existsSync(path) ? readJson(path) : undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function loadCases(scanDir) {
|
|
88
|
+
const suite = optionalJson(join(scanDir, "golden-cases-smoke.json")) ?? optionalJson(join(repoRoot, ".pi/factories/project-dna/golden-cases-smoke.json"));
|
|
89
|
+
if (suite?.schema === "zob.project-dna-golden-suite.v1" && Array.isArray(suite.cases) && suite.cases.length > 0) {
|
|
90
|
+
return { benchmarkKind: "golden-agentic-5of5-smoke", suiteId: suite.suite_id, cases: suite.cases };
|
|
91
|
+
}
|
|
92
|
+
return { benchmarkKind: "legacy-hardcoded-smoke", suiteId: null, cases: LEGACY_CASES };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function queryCase(scanDirRel, testCase, index) {
|
|
96
|
+
const outRel = `${scanDirRel.replace(/\/$/, "")}/bench/${String(index + 1).padStart(2, "0")}-${testCase.id}.json`;
|
|
97
|
+
const stewardReportArgs = index === 0 ? ["--steward-report-out", `${scanDirRel.replace(/\/$/, "")}/query-steward-smoke.json`] : [];
|
|
98
|
+
const stdout = runNode([
|
|
99
|
+
"scripts/project-dna/query-context.mjs",
|
|
100
|
+
"--scan-dir", scanDirRel,
|
|
101
|
+
"--query", testCase.query,
|
|
102
|
+
"--golden-case-id", testCase.id,
|
|
103
|
+
"--max-files", "12",
|
|
104
|
+
"--out", outRel,
|
|
105
|
+
...stewardReportArgs,
|
|
106
|
+
]);
|
|
107
|
+
const result = readJson(join(repoRoot, outRel));
|
|
108
|
+
const citations = result.citations ?? [];
|
|
109
|
+
const filesToReadFirst = (result.files_to_read_first ?? []).map((file) => String(file.path ?? ""));
|
|
110
|
+
const patternHits = (result.pattern_hits ?? []).map((pattern) => String(pattern.id ?? ""));
|
|
111
|
+
const errors = [];
|
|
112
|
+
if (result.schema !== "zob.project-dna-query-result.v1") errors.push("query result schema mismatch");
|
|
113
|
+
if (result.query_stored !== false || result.raw_query_persisted !== false) errors.push("query result must not persist raw query");
|
|
114
|
+
if (result.query_steward?.used !== true) errors.push("query steward must be used");
|
|
115
|
+
if (result.query_steward?.raw_query_persisted !== false) errors.push("query steward must not persist raw query");
|
|
116
|
+
if (result.query_steward?.controlled_expansion_terms_stored !== false) errors.push("query steward must not persist raw expansion terms");
|
|
117
|
+
if (result.loading_rules?.bounded_context_only !== true) errors.push("query result must be bounded_context_only");
|
|
118
|
+
if (result.loading_rules?.citation_required !== true) errors.push("query result must require citations");
|
|
119
|
+
if (result.loading_rules?.agent_loads_entire_project !== false) errors.push("query result must not load whole project");
|
|
120
|
+
if (result.safety?.knowledge_backend_write_enabled !== false) errors.push("query result must keep knowledge_backend_write_enabled=false");
|
|
121
|
+
for (const needle of testCase.required_citation_includes ?? []) {
|
|
122
|
+
if (!citations.some((citation) => String(citation).includes(needle))) errors.push(`missing citation containing ${needle}`);
|
|
123
|
+
}
|
|
124
|
+
for (const needle of testCase.required_files_to_read_first ?? []) {
|
|
125
|
+
if (!filesToReadFirst.some((file) => file.includes(needle))) errors.push(`missing files_to_read_first containing ${needle}`);
|
|
126
|
+
}
|
|
127
|
+
for (const pattern of testCase.expected_patterns ?? []) {
|
|
128
|
+
if (!patternHits.includes(pattern)) errors.push(`missing expected pattern hit ${pattern}`);
|
|
129
|
+
}
|
|
130
|
+
const score = errors.length === 0 ? 5 : Math.max(0, 5 - errors.length);
|
|
131
|
+
if (score < Number(testCase.score_threshold ?? 5)) errors.push(`score ${score} below threshold ${testCase.score_threshold ?? 5}`);
|
|
132
|
+
return {
|
|
133
|
+
id: testCase.id,
|
|
134
|
+
status: errors.length === 0 ? "passed" : "failed",
|
|
135
|
+
score,
|
|
136
|
+
threshold: Number(testCase.score_threshold ?? 5),
|
|
137
|
+
errors,
|
|
138
|
+
queryResultPath: outRel,
|
|
139
|
+
citationCount: citations.length,
|
|
140
|
+
citations_checked: citations,
|
|
141
|
+
filesToReadFirstCount: filesToReadFirst.length,
|
|
142
|
+
patternHitCount: patternHits.length,
|
|
143
|
+
stewardIntent: result.query_steward?.intent_id ?? null,
|
|
144
|
+
stdoutFirstLine: stdout.split("\n")[0] ?? "",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function main() {
|
|
149
|
+
const args = parseArgs(process.argv.slice(2));
|
|
150
|
+
if (args.help || !args.scanDir) {
|
|
151
|
+
usage();
|
|
152
|
+
if (!args.help) process.exit(2);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const scanDir = resolveRepoPath(args.scanDir, "--scan-dir");
|
|
156
|
+
const scanDirRel = relative(repoRoot, scanDir).split(sep).join("/");
|
|
157
|
+
const outPath = resolveRepoPath(args.out ?? `${scanDirRel}/bench/benchmark-smoke.json`, "--out", true);
|
|
158
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
159
|
+
|
|
160
|
+
const errors = [];
|
|
161
|
+
const commandResults = [];
|
|
162
|
+
try {
|
|
163
|
+
commandResults.push({ command: `node scripts/project-dna/validate-scan-artifacts.mjs --scan-dir ${scanDirRel}`, output: runNode(["scripts/project-dna/validate-scan-artifacts.mjs", "--scan-dir", scanDirRel]).split("\n")[0] });
|
|
164
|
+
} catch (error) {
|
|
165
|
+
errors.push(`scan validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const sampleDirRel = `${scanDirRel}/quarantine/sample-project`;
|
|
169
|
+
if (existsSync(join(repoRoot, sampleDirRel))) {
|
|
170
|
+
try {
|
|
171
|
+
commandResults.push({ command: `node scripts/project-dna/validate-sample-project.mjs --sample-dir ${sampleDirRel}`, output: runNode(["scripts/project-dna/validate-sample-project.mjs", "--sample-dir", sampleDirRel]).split("\n")[0] });
|
|
172
|
+
} catch (error) {
|
|
173
|
+
errors.push(`sample validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
errors.push(`sample dir missing for benchmark: ${sampleDirRel}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const suite = loadCases(scanDir);
|
|
180
|
+
const cases = suite.cases.map((testCase, index) => queryCase(scanDirRel, testCase, index));
|
|
181
|
+
for (const testCase of cases) for (const error of testCase.errors) errors.push(`${testCase.id}: ${error}`);
|
|
182
|
+
|
|
183
|
+
const result = {
|
|
184
|
+
schema: "zob.project-dna-benchmark-smoke.v1",
|
|
185
|
+
benchmark_kind: suite.benchmarkKind,
|
|
186
|
+
suite_id: suite.suiteId,
|
|
187
|
+
scan_dir: scanDirRel,
|
|
188
|
+
status: errors.length === 0 ? "passed" : "failed",
|
|
189
|
+
cases,
|
|
190
|
+
command_results: commandResults,
|
|
191
|
+
errors,
|
|
192
|
+
metrics: {
|
|
193
|
+
cases_total: cases.length,
|
|
194
|
+
cases_passed: cases.filter((testCase) => testCase.status === "passed").length,
|
|
195
|
+
citation_total: cases.reduce((sum, testCase) => sum + testCase.citationCount, 0),
|
|
196
|
+
average_score: cases.length > 0 ? Number((cases.reduce((sum, testCase) => sum + testCase.score, 0) / cases.length).toFixed(2)) : 0,
|
|
197
|
+
},
|
|
198
|
+
gates: {
|
|
199
|
+
deterministic_only: true,
|
|
200
|
+
llm_judge_used: false,
|
|
201
|
+
source_project_modified: false,
|
|
202
|
+
knowledge_backend_write_enabled: false,
|
|
203
|
+
promotion_allowed: false,
|
|
204
|
+
human_approval_required: true,
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
writeFileSync(outPath, `${JSON.stringify(result, null, 2)}\n`, "utf8");
|
|
208
|
+
console.log(JSON.stringify(result, null, 2));
|
|
209
|
+
if (errors.length > 0) process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
main();
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error(JSON.stringify({ schema: "zob.project-dna-benchmark-smoke-error.v1", error: error instanceof Error ? error.message : String(error), source_project_modified: false, knowledge_backend_write_enabled: false }, null, 2));
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
|
|
5
|
+
const repoRoot = process.cwd();
|
|
6
|
+
|
|
7
|
+
function usage() {
|
|
8
|
+
console.error(`Usage:
|
|
9
|
+
node scripts/project-dna/build-capsules.mjs --scan-dir <repo-relative-scan-dir> [--out-dir <repo-relative-output-dir>]
|
|
10
|
+
|
|
11
|
+
Builds pointer capsules from ProjectDNA scan metadata. Does not read source project files.`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function parseArgs(argv) {
|
|
15
|
+
const out = {};
|
|
16
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
17
|
+
const arg = argv[i];
|
|
18
|
+
if (arg === "--scan-dir") out.scanDir = argv[++i];
|
|
19
|
+
else if (arg === "--out-dir") out.outDir = argv[++i];
|
|
20
|
+
else if (arg === "--help" || arg === "-h") out.help = true;
|
|
21
|
+
else throw new Error(`unknown argument: ${arg}`);
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function resolveRepoDir(input, label) {
|
|
27
|
+
if (!input || isAbsolute(input)) throw new Error(`${label} must be repo-relative`);
|
|
28
|
+
const resolved = resolve(repoRoot, input);
|
|
29
|
+
const rel = relative(repoRoot, resolved);
|
|
30
|
+
if (rel.startsWith("..") || rel === "") throw new Error(`${label} must stay inside repo and not be repo root`);
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readJson(dir, name) {
|
|
35
|
+
const path = join(dir, name);
|
|
36
|
+
if (!existsSync(path)) throw new Error(`missing scan artifact: ${name}`);
|
|
37
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function citationList(citations = []) {
|
|
41
|
+
const unique = [...new Set(citations.filter(Boolean))];
|
|
42
|
+
if (unique.length === 0) return "- Gap: no citations available.";
|
|
43
|
+
return unique.map((citation) => `- \`${citation}\``).join("\n");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function filesByKind(fileMap, kind) {
|
|
47
|
+
return (fileMap.files ?? []).filter((file) => file.kind === kind);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function filesAsPointers(files, limit = 12) {
|
|
51
|
+
if (files.length === 0) return "- Gap: no matching files detected.";
|
|
52
|
+
return files.slice(0, limit).map((file) => {
|
|
53
|
+
const citation = file.citations?.[0] ?? file.path;
|
|
54
|
+
return `- \`${citation}\` — ${file.kind}${file.imports?.length ? `; imports: ${file.imports.slice(0, 5).join(", ")}` : ""}`;
|
|
55
|
+
}).join("\n");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function writeCapsule(outDir, name, content) {
|
|
59
|
+
writeFileSync(join(outDir, name), `${content.trim()}\n`, "utf8");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function capsuleHeader(title, sourceId) {
|
|
63
|
+
return `# ${title}\n\nSource: \`${sourceId}\`\n\nStatus: generated pointer capsule from ProjectDNA scan metadata. Treat citations as navigation hints, not full truth. Read cited files before implementation.\n`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function main() {
|
|
67
|
+
const args = parseArgs(process.argv.slice(2));
|
|
68
|
+
if (args.help || !args.scanDir) {
|
|
69
|
+
usage();
|
|
70
|
+
if (!args.help) process.exit(2);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const scanDir = resolveRepoDir(args.scanDir, "--scan-dir");
|
|
74
|
+
const outDir = resolveRepoDir(args.outDir ?? `${args.scanDir.replace(/\/$/, "")}/capsules`, "--out-dir");
|
|
75
|
+
const outRel = relative(repoRoot, outDir).split(sep).join("/");
|
|
76
|
+
mkdirSync(outDir, { recursive: true });
|
|
77
|
+
|
|
78
|
+
const fingerprint = readJson(scanDir, "project-fingerprint.json");
|
|
79
|
+
const dependencyMap = readJson(scanDir, "dependency-map.json");
|
|
80
|
+
const fileMap = readJson(scanDir, "file-map.json");
|
|
81
|
+
const architectureMap = readJson(scanDir, "architecture-map.json");
|
|
82
|
+
const contextPack = readJson(scanDir, "context-pack-smoke.json");
|
|
83
|
+
const graph = readJson(scanDir, "code-knowledge-graph.json");
|
|
84
|
+
const sourceId = fingerprint.source_id;
|
|
85
|
+
|
|
86
|
+
const capsules = [];
|
|
87
|
+
|
|
88
|
+
const architecture = `${capsuleHeader("Architecture overview", sourceId)}
|
|
89
|
+
## Look here first
|
|
90
|
+
|
|
91
|
+
${citationList(contextPack.citations)}
|
|
92
|
+
|
|
93
|
+
## Detected stack/tools
|
|
94
|
+
|
|
95
|
+
- package manager: ${dependencyMap.package_manager ?? "not detected"}
|
|
96
|
+
- runtime dependencies: ${(dependencyMap.runtime_dependencies ?? []).slice(0, 20).join(", ") || "none detected"}
|
|
97
|
+
- dev dependencies: ${(dependencyMap.dev_dependencies ?? []).slice(0, 20).join(", ") || "none detected"}
|
|
98
|
+
|
|
99
|
+
## Detected patterns
|
|
100
|
+
|
|
101
|
+
${(architectureMap.patterns ?? []).length ? architectureMap.patterns.map((pattern) => `- ${pattern.id} (${pattern.confidence}) — evidence: ${(pattern.evidence ?? []).slice(0, 4).map((item) => `\`${item}\``).join(", ")}`).join("\n") : "- Gap: no high-confidence architecture patterns detected."}
|
|
102
|
+
|
|
103
|
+
## Graph summary
|
|
104
|
+
|
|
105
|
+
- nodes: ${(graph.nodes ?? []).length}
|
|
106
|
+
- edges: ${(graph.edges ?? []).length}
|
|
107
|
+
|
|
108
|
+
## Gaps
|
|
109
|
+
|
|
110
|
+
${(architectureMap.gaps ?? []).map((gap) => `- ${gap}`).join("\n") || "- No scan-level gaps reported."}
|
|
111
|
+
`;
|
|
112
|
+
writeCapsule(outDir, "architecture.md", architecture);
|
|
113
|
+
capsules.push("architecture.md");
|
|
114
|
+
|
|
115
|
+
const folderStructure = `${capsuleHeader("Folder structure", sourceId)}
|
|
116
|
+
## Top-level directories/files
|
|
117
|
+
|
|
118
|
+
${(architectureMap.top_level_directories ?? []).map((dir) => `- \`${dir}\``).join("\n") || "- Gap: no files detected."}
|
|
119
|
+
|
|
120
|
+
## File pointers by kind
|
|
121
|
+
|
|
122
|
+
${Object.entries(architectureMap.kind_counts ?? {}).sort(([a], [b]) => a.localeCompare(b)).map(([kind, count]) => `- ${kind}: ${count}`).join("\n") || "- Gap: no kind counts available."}
|
|
123
|
+
`;
|
|
124
|
+
writeCapsule(outDir, "folder-structure.md", folderStructure);
|
|
125
|
+
capsules.push("folder-structure.md");
|
|
126
|
+
|
|
127
|
+
const testing = `${capsuleHeader("Testing pointers", sourceId)}
|
|
128
|
+
## Test files
|
|
129
|
+
|
|
130
|
+
${filesAsPointers(filesByKind(fileMap, "test"))}
|
|
131
|
+
|
|
132
|
+
## Observed rule
|
|
133
|
+
|
|
134
|
+
- Use these citations to infer test placement/style; do not infer missing test conventions from generic framework docs.
|
|
135
|
+
`;
|
|
136
|
+
writeCapsule(outDir, "testing.md", testing);
|
|
137
|
+
capsules.push("testing.md");
|
|
138
|
+
|
|
139
|
+
const config = `${capsuleHeader("Config pointers", sourceId)}
|
|
140
|
+
## Config files
|
|
141
|
+
|
|
142
|
+
${filesAsPointers(filesByKind(fileMap, "config"))}
|
|
143
|
+
|
|
144
|
+
## Observed rule
|
|
145
|
+
|
|
146
|
+
- Prefer cited config files over ad-hoc direct client/secret construction.
|
|
147
|
+
`;
|
|
148
|
+
writeCapsule(outDir, "config.md", config);
|
|
149
|
+
capsules.push("config.md");
|
|
150
|
+
|
|
151
|
+
const services = `${capsuleHeader("Service-layer pointers", sourceId)}
|
|
152
|
+
## Service files
|
|
153
|
+
|
|
154
|
+
${filesAsPointers(filesByKind(fileMap, "service"))}
|
|
155
|
+
|
|
156
|
+
## Route/controller files
|
|
157
|
+
|
|
158
|
+
${filesAsPointers(filesByKind(fileMap, "route"))}
|
|
159
|
+
|
|
160
|
+
## Observed rule
|
|
161
|
+
|
|
162
|
+
- If both route and service files exist, inspect cited pairs before adding business logic.
|
|
163
|
+
`;
|
|
164
|
+
writeCapsule(outDir, "services.md", services);
|
|
165
|
+
capsules.push("services.md");
|
|
166
|
+
|
|
167
|
+
const queues = `${capsuleHeader("Queue / worker pointers", sourceId)}
|
|
168
|
+
## Queue files
|
|
169
|
+
|
|
170
|
+
${filesAsPointers(filesByKind(fileMap, "queue"))}
|
|
171
|
+
|
|
172
|
+
## Worker files
|
|
173
|
+
|
|
174
|
+
${filesAsPointers(filesByKind(fileMap, "worker"))}
|
|
175
|
+
|
|
176
|
+
## Tool evidence
|
|
177
|
+
|
|
178
|
+
${(dependencyMap.tool_roles ?? []).filter((tool) => tool.role === "queue").map((tool) => `- ${tool.name}: ${tool.role}`).join("\n") || "- Gap: no queue dependency detected."}
|
|
179
|
+
|
|
180
|
+
## Observed rule
|
|
181
|
+
|
|
182
|
+
- Only use this capsule when cited queue/worker files exist; otherwise report a gap instead of inventing a queue pattern.
|
|
183
|
+
`;
|
|
184
|
+
writeCapsule(outDir, "queues.md", queues);
|
|
185
|
+
capsules.push("queues.md");
|
|
186
|
+
|
|
187
|
+
const summary = {
|
|
188
|
+
schema: "zob.project-dna-capsule-build-summary.v1",
|
|
189
|
+
source_id: sourceId,
|
|
190
|
+
scan_dir: relative(repoRoot, scanDir).split(sep).join("/"),
|
|
191
|
+
out_dir: outRel,
|
|
192
|
+
capsules,
|
|
193
|
+
source_files_read: false,
|
|
194
|
+
scan_metadata_only: true,
|
|
195
|
+
source_project_modified: false,
|
|
196
|
+
knowledge_backend_write_enabled: false,
|
|
197
|
+
};
|
|
198
|
+
writeFileSync(join(outDir, "capsule-summary.json"), `${JSON.stringify(summary, null, 2)}\n`, "utf8");
|
|
199
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
main();
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.error(JSON.stringify({ schema: "zob.project-dna-capsule-build-error.v1", error: error instanceof Error ? error.message : String(error), source_project_modified: false, knowledge_backend_write_enabled: false }, null, 2));
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
|
|
5
|
+
const repoRoot = process.cwd();
|
|
6
|
+
|
|
7
|
+
function usage() {
|
|
8
|
+
console.error(`Usage:
|
|
9
|
+
node scripts/project-dna/build-sample-spec.mjs --scan-dir <repo-relative-scan-dir> [--neutral-domain <domain>] [--out <repo-relative-json>]
|
|
10
|
+
|
|
11
|
+
Builds a neutral ProjectDNA sample specification from scan metadata. It does not generate sample code.`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function parseArgs(argv) {
|
|
15
|
+
const out = {};
|
|
16
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
17
|
+
const arg = argv[i];
|
|
18
|
+
if (arg === "--scan-dir") out.scanDir = argv[++i];
|
|
19
|
+
else if (arg === "--neutral-domain") out.neutralDomain = argv[++i];
|
|
20
|
+
else if (arg === "--out") out.out = argv[++i];
|
|
21
|
+
else if (arg === "--help" || arg === "-h") out.help = true;
|
|
22
|
+
else throw new Error(`unknown argument: ${arg}`);
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function resolveRepoPath(input, label) {
|
|
28
|
+
if (!input || isAbsolute(input)) throw new Error(`${label} must be repo-relative`);
|
|
29
|
+
const resolved = resolve(repoRoot, input);
|
|
30
|
+
const rel = relative(repoRoot, resolved);
|
|
31
|
+
if (rel.startsWith("..") || rel === "") throw new Error(`${label} must stay inside repo and not be repo root`);
|
|
32
|
+
return resolved;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function readJson(dir, name) {
|
|
36
|
+
const path = join(dir, name);
|
|
37
|
+
if (!existsSync(path)) throw new Error(`missing scan artifact: ${name}`);
|
|
38
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function unique(values) {
|
|
42
|
+
return [...new Set(values.filter(Boolean))].sort();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function main() {
|
|
46
|
+
const args = parseArgs(process.argv.slice(2));
|
|
47
|
+
if (args.help || !args.scanDir) {
|
|
48
|
+
usage();
|
|
49
|
+
if (!args.help) process.exit(2);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const scanDir = resolveRepoPath(args.scanDir, "--scan-dir");
|
|
54
|
+
const outPath = resolveRepoPath(args.out ?? `${args.scanDir.replace(/\/$/, "")}/sample-spec.json`, "--out");
|
|
55
|
+
const fingerprint = readJson(scanDir, "project-fingerprint.json");
|
|
56
|
+
const dependencyMap = readJson(scanDir, "dependency-map.json");
|
|
57
|
+
const fileMap = readJson(scanDir, "file-map.json");
|
|
58
|
+
const architectureMap = readJson(scanDir, "architecture-map.json");
|
|
59
|
+
const contextPack = readJson(scanDir, "context-pack-smoke.json");
|
|
60
|
+
|
|
61
|
+
const kinds = new Set((fileMap.files ?? []).map((file) => file.kind));
|
|
62
|
+
const requiredModules = ["config"];
|
|
63
|
+
if (kinds.has("route") || kinds.has("entrypoint")) requiredModules.push("api");
|
|
64
|
+
if (kinds.has("service")) requiredModules.push("services");
|
|
65
|
+
if (kinds.has("queue") || kinds.has("worker")) requiredModules.push("queues", "workers");
|
|
66
|
+
if (kinds.has("database")) requiredModules.push("database");
|
|
67
|
+
if (kinds.has("test")) requiredModules.push("tests");
|
|
68
|
+
if (requiredModules.length === 1) requiredModules.push("example-module", "tests");
|
|
69
|
+
|
|
70
|
+
const toolRoles = dependencyMap.tool_roles ?? [];
|
|
71
|
+
const preserve = unique([
|
|
72
|
+
dependencyMap.package_manager ? `package-manager:${dependencyMap.package_manager}` : undefined,
|
|
73
|
+
...toolRoles.map((tool) => `tool-role:${tool.name}:${tool.role}`),
|
|
74
|
+
...Object.keys(architectureMap.kind_counts ?? {}).map((kind) => `file-kind:${kind}`),
|
|
75
|
+
...((architectureMap.patterns ?? []).map((pattern) => `pattern:${pattern.id}`)),
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
const sampleSpec = {
|
|
79
|
+
schema: "zob.project-dna-sample-spec.v1",
|
|
80
|
+
source_id: fingerprint.source_id,
|
|
81
|
+
sample_name: `${fingerprint.source_id}-dna-sample`,
|
|
82
|
+
neutral_domain: args.neutralDomain ?? "task-tracker",
|
|
83
|
+
generation_status: "spec_only_no_code_generated",
|
|
84
|
+
target_stack_policy: "preserve_detected_stack_where_safe",
|
|
85
|
+
copy_policy: "structure_and_patterns_only",
|
|
86
|
+
preserve,
|
|
87
|
+
remove: [
|
|
88
|
+
"real product concepts",
|
|
89
|
+
"company/user/customer names",
|
|
90
|
+
"business-specific logic",
|
|
91
|
+
"private data",
|
|
92
|
+
"secrets and credentials",
|
|
93
|
+
"fragile external integrations",
|
|
94
|
+
"large verbatim source files"
|
|
95
|
+
],
|
|
96
|
+
required_modules: unique(requiredModules),
|
|
97
|
+
suggested_files: unique(requiredModules).map((module) => ({
|
|
98
|
+
module,
|
|
99
|
+
path: module === "api" ? "src/api/routes.ts" : module === "tests" ? "test/sample.test.ts" : `src/${module}/index.ts`,
|
|
100
|
+
purpose: `neutral ${module} example preserving observed ProjectDNA conventions where cited`,
|
|
101
|
+
})),
|
|
102
|
+
citations: unique([...(contextPack.citations ?? []), ...(architectureMap.citations ?? [])]).slice(0, 30),
|
|
103
|
+
validation: {
|
|
104
|
+
required: true,
|
|
105
|
+
suggested_commands: ["install", "lint/typecheck if configured", "test if configured", "build if configured"],
|
|
106
|
+
no_ship_if_fails: true,
|
|
107
|
+
},
|
|
108
|
+
promotion: {
|
|
109
|
+
writeback_policy: "proposal_only",
|
|
110
|
+
oracle_required: true,
|
|
111
|
+
human_approval_required: true,
|
|
112
|
+
},
|
|
113
|
+
safety: {
|
|
114
|
+
source_files_read: false,
|
|
115
|
+
scan_metadata_only: true,
|
|
116
|
+
sample_code_generated: false,
|
|
117
|
+
source_project_modified: false,
|
|
118
|
+
knowledge_backend_write_enabled: false,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
writeFileSync(outPath, `${JSON.stringify(sampleSpec, null, 2)}\n`, "utf8");
|
|
123
|
+
console.log(JSON.stringify({
|
|
124
|
+
schema: "zob.project-dna-sample-spec-build-summary.v1",
|
|
125
|
+
source_id: fingerprint.source_id,
|
|
126
|
+
out: relative(repoRoot, outPath).split(sep).join("/"),
|
|
127
|
+
neutral_domain: sampleSpec.neutral_domain,
|
|
128
|
+
required_modules: sampleSpec.required_modules,
|
|
129
|
+
sample_code_generated: false,
|
|
130
|
+
source_project_modified: false,
|
|
131
|
+
knowledge_backend_write_enabled: false,
|
|
132
|
+
}, null, 2));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
main();
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error(JSON.stringify({ schema: "zob.project-dna-sample-spec-error.v1", error: error instanceof Error ? error.message : String(error), source_project_modified: false, knowledge_backend_write_enabled: false }, null, 2));
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
4
|
+
|
|
5
|
+
const repoRoot = process.cwd();
|
|
6
|
+
|
|
7
|
+
function usage() {
|
|
8
|
+
console.error(`Usage:
|
|
9
|
+
node scripts/project-dna/emit-golden-cases.mjs --scan-dir <repo-relative-scan-dir> [--source <repo-relative-json>] [--out <repo-relative-json>]
|
|
10
|
+
|
|
11
|
+
Copies ProjectDNA golden cases into a reports scan directory. No source scan, no backend write.`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function parseArgs(argv) {
|
|
15
|
+
const out = { source: ".pi/factories/project-dna/golden-cases-smoke.json" };
|
|
16
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
17
|
+
const arg = argv[i];
|
|
18
|
+
if (arg === "--scan-dir") out.scanDir = argv[++i];
|
|
19
|
+
else if (arg === "--source") out.source = argv[++i];
|
|
20
|
+
else if (arg === "--out") out.out = argv[++i];
|
|
21
|
+
else if (arg === "--help" || arg === "-h") out.help = true;
|
|
22
|
+
else throw new Error(`unknown argument: ${arg}`);
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function resolveRepoPath(input, label, allowMissing = false) {
|
|
28
|
+
if (!input || isAbsolute(input)) throw new Error(`${label} must be repo-relative`);
|
|
29
|
+
const resolved = resolve(repoRoot, input);
|
|
30
|
+
const rel = relative(repoRoot, resolved);
|
|
31
|
+
if (rel.startsWith("..") || rel === "") throw new Error(`${label} must stay inside repo and not be repo root`);
|
|
32
|
+
if (!allowMissing && !existsSync(resolved)) throw new Error(`${label} not found: ${input}`);
|
|
33
|
+
return resolved;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function assertReportPath(input, label) {
|
|
37
|
+
const normalized = input.split(sep).join("/");
|
|
38
|
+
if (!normalized.startsWith("reports/project-dna-scans/")) throw new Error(`${label} must stay under reports/project-dna-scans`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function main() {
|
|
42
|
+
const args = parseArgs(process.argv.slice(2));
|
|
43
|
+
if (args.help || !args.scanDir) {
|
|
44
|
+
usage();
|
|
45
|
+
if (!args.help) process.exit(2);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
assertReportPath(args.scanDir, "--scan-dir");
|
|
49
|
+
const scanDir = resolveRepoPath(args.scanDir, "--scan-dir", true);
|
|
50
|
+
const sourcePath = resolveRepoPath(args.source, "--source");
|
|
51
|
+
const outRel = args.out ?? `${args.scanDir.replace(/\/$/, "")}/golden-cases-smoke.json`;
|
|
52
|
+
assertReportPath(outRel, "--out");
|
|
53
|
+
const outPath = resolveRepoPath(outRel, "--out", true);
|
|
54
|
+
if (!relative(scanDir, outPath) || relative(scanDir, outPath).startsWith("..")) throw new Error("--out must stay inside --scan-dir");
|
|
55
|
+
const suite = JSON.parse(readFileSync(sourcePath, "utf8"));
|
|
56
|
+
if (suite.schema !== "zob.project-dna-golden-suite.v1") throw new Error("golden case suite schema mismatch");
|
|
57
|
+
const emitted = {
|
|
58
|
+
...suite,
|
|
59
|
+
emitted_from: relative(repoRoot, sourcePath).split(sep).join("/"),
|
|
60
|
+
scan_dir: relative(repoRoot, scanDir).split(sep).join("/"),
|
|
61
|
+
source_project_modified: false,
|
|
62
|
+
knowledge_backend_write_enabled: false,
|
|
63
|
+
durable_promotion_allowed: false,
|
|
64
|
+
};
|
|
65
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
66
|
+
writeFileSync(outPath, `${JSON.stringify(emitted, null, 2)}\n`, "utf8");
|
|
67
|
+
console.log(JSON.stringify({ schema: "zob.project-dna-golden-cases-emission.v1", out: relative(repoRoot, outPath).split(sep).join("/"), case_count: emitted.cases.length, source_project_modified: false, knowledge_backend_write_enabled: false }, null, 2));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
main();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(JSON.stringify({ schema: "zob.project-dna-golden-cases-emission-error.v1", error: error instanceof Error ? error.message : String(error), source_project_modified: false, knowledge_backend_write_enabled: false }, null, 2));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|