zob-harness 0.2.0 → 0.3.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/capabilities/zob-public-runtime-capabilities.json +4 -4
- package/.pi/extensions/zob-child-safety/AGENTS.md +12 -0
- package/.pi/extensions/zob-child-safety/index.ts +4 -105
- package/.pi/extensions/zob-child-safety/src/AGENTS.md +10 -0
- package/.pi/extensions/zob-child-safety/src/policy.ts +106 -0
- package/.pi/extensions/zob-harness/AGENTS.md +2 -0
- package/.pi/extensions/zob-harness/index.ts +94 -94
- package/.pi/extensions/zob-harness/src/AGENTS.md +4 -0
- package/.pi/extensions/zob-harness/src/core/AGENTS.md +24 -0
- package/.pi/extensions/zob-harness/src/{constants.ts → core/constants.ts} +10 -1
- package/.pi/extensions/zob-harness/src/core/utils/AGENTS.md +23 -0
- package/.pi/extensions/zob-harness/src/{utils → core/utils}/formatting.ts +1 -1
- package/.pi/extensions/zob-harness/src/{utils → core/utils}/records.ts +1 -1
- package/.pi/extensions/zob-harness/src/{utils → core/utils}/resources.ts +1 -1
- package/.pi/extensions/zob-harness/src/domains/AGENTS.md +23 -0
- package/.pi/extensions/zob-harness/src/domains/autonomy/AGENTS.md +21 -0
- package/.pi/extensions/zob-harness/src/{autonomous-runtime.ts → domains/autonomy/autonomous-runtime.ts} +22 -22
- package/.pi/extensions/zob-harness/src/{autonomy-readiness.ts → domains/autonomy/autonomy-readiness.ts} +18 -18
- package/.pi/extensions/zob-harness/src/{daemon-policy.ts → domains/autonomy/daemon-policy.ts} +6 -6
- package/.pi/extensions/zob-harness/src/{daemon-readiness.ts → domains/autonomy/daemon-readiness.ts} +7 -7
- package/.pi/extensions/zob-harness/src/{daemon-runtime.ts → domains/autonomy/daemon-runtime.ts} +2 -2
- package/.pi/extensions/zob-harness/src/{full-autonomy-test.ts → domains/autonomy/full-autonomy-test.ts} +4 -4
- package/.pi/extensions/zob-harness/src/{interactive-autonomy.ts → domains/autonomy/interactive-autonomy.ts} +2 -2
- package/.pi/extensions/zob-harness/src/{compute-profile.ts → domains/compute/compute-profile.ts} +3 -3
- package/.pi/extensions/zob-harness/src/{compute-workflow-shape.ts → domains/compute/compute-workflow-shape.ts} +3 -3
- package/.pi/extensions/zob-harness/src/domains/coms/AGENTS.md +21 -0
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/envelope.ts +2 -2
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/identity.ts +3 -3
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/ledger-bridge.ts +2 -2
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/local-transport.ts +1 -1
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/policy.ts +3 -3
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/presence.ts +1 -1
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/registry.ts +3 -3
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/response-capture.ts +1 -1
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/transcript-capture.ts +2 -2
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/zpeer-profile.ts +3 -3
- package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/zpeer.ts +3 -3
- package/.pi/extensions/zob-harness/src/{mission-control.ts → domains/coms/mission-control.ts} +8 -8
- package/.pi/extensions/zob-harness/src/{zagents.ts → domains/coms/zagents.ts} +86 -4
- package/.pi/extensions/zob-harness/src/domains/context/AGENTS.md +20 -0
- package/.pi/extensions/zob-harness/src/{context-gbrain.ts → domains/context/context-gbrain.ts} +4 -4
- package/.pi/extensions/zob-harness/src/domains/delegation/AGENTS.md +21 -0
- package/.pi/extensions/zob-harness/src/{agents.ts → domains/delegation/agents.ts} +2 -2
- package/.pi/extensions/zob-harness/src/{capabilities.ts → domains/delegation/capabilities.ts} +6 -6
- package/.pi/extensions/zob-harness/src/{child-runner.ts → domains/delegation/child-runner.ts} +8 -8
- package/.pi/extensions/zob-harness/src/{output-contracts.ts → domains/delegation/output-contracts.ts} +1 -1
- package/.pi/extensions/zob-harness/src/{prompt-packs.ts → domains/delegation/prompt-packs.ts} +4 -4
- package/.pi/extensions/zob-harness/src/domains/factory/AGENTS.md +21 -0
- package/.pi/extensions/zob-harness/src/{factory → domains/factory}/agentic-plan.ts +1 -1
- package/.pi/extensions/zob-harness/src/{factory-selector.ts → domains/factory/factory-selector.ts} +4 -4
- package/.pi/extensions/zob-harness/src/{factory → domains/factory}/quarantine.ts +5 -5
- package/.pi/extensions/zob-harness/src/{factory → domains/factory}/run.ts +5 -5
- package/.pi/extensions/zob-harness/src/{factory → domains/factory}/validation.ts +10 -10
- package/.pi/extensions/zob-harness/src/domains/git/AGENTS.md +20 -0
- package/.pi/extensions/zob-harness/src/{git-ops.ts → domains/git/git-ops.ts} +3 -3
- package/.pi/extensions/zob-harness/src/domains/goal/AGENTS.md +22 -0
- package/.pi/extensions/zob-harness/src/{goal-room.ts → domains/goal/goal-room.ts} +7 -7
- package/.pi/extensions/zob-harness/src/{goal-todo-imports.ts → domains/goal/goal-todo-imports.ts} +1 -1
- package/.pi/extensions/zob-harness/src/{goal-todo-types.ts → domains/goal/goal-todo-types.ts} +1 -1
- package/.pi/extensions/zob-harness/src/{goal-todos.ts → domains/goal/goal-todos.ts} +4 -4
- package/.pi/extensions/zob-harness/src/{goal.ts → domains/goal/goal.ts} +1 -1
- package/.pi/extensions/zob-harness/src/domains/governance/AGENTS.md +21 -0
- package/.pi/extensions/zob-harness/src/{budget-policy.ts → domains/governance/budget-policy.ts} +6 -6
- package/.pi/extensions/zob-harness/src/{governed-requests.ts → domains/governance/governed-requests.ts} +7 -7
- package/.pi/extensions/zob-harness/src/{launch-apply.ts → domains/governance/launch-apply.ts} +4 -4
- package/.pi/extensions/zob-harness/src/{merge-queue.ts → domains/governance/merge-queue.ts} +6 -6
- package/.pi/extensions/zob-harness/src/{rules.ts → domains/governance/rules.ts} +7 -7
- package/.pi/extensions/zob-harness/src/{safety.ts → domains/governance/safety.ts} +3 -3
- package/.pi/extensions/zob-harness/src/{sandbox.ts → domains/governance/sandbox.ts} +5 -5
- package/.pi/extensions/zob-harness/src/{worker-pool.ts → domains/governance/worker-pool.ts} +7 -7
- package/.pi/extensions/zob-harness/src/{workspace-claims.ts → domains/governance/workspace-claims.ts} +6 -6
- package/.pi/extensions/zob-harness/src/domains/models/AGENTS.md +20 -0
- package/.pi/extensions/zob-harness/src/{model-availability.ts → domains/models/model-availability.ts} +1 -1
- package/.pi/extensions/zob-harness/src/{model-routing.ts → domains/models/model-routing.ts} +6 -6
- package/.pi/extensions/zob-harness/src/domains/orchestration/AGENTS.md +21 -0
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/adaptive-delegation.ts +8 -8
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/adaptive-workflow.ts +4 -4
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/lead-plan.ts +5 -5
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/plan.ts +5 -5
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/room.ts +4 -4
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/run.ts +6 -6
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/supervised-readonly.ts +6 -6
- package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/widget-readers.ts +2 -2
- package/.pi/extensions/zob-harness/src/domains/project-dna/AGENTS.md +19 -0
- package/.pi/extensions/zob-harness/src/{project-dna.ts → domains/project-dna/project-dna.ts} +4 -4
- package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/candidate.ts +5 -5
- package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/coms.ts +3 -3
- package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/documentation.ts +4 -4
- package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/factory.ts +2 -2
- package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/temp-agent.ts +4 -4
- package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/write-lane.ts +3 -3
- package/.pi/extensions/zob-harness/src/domains/telemetry/AGENTS.md +19 -0
- package/.pi/extensions/zob-harness/src/{chronicle.ts → domains/telemetry/chronicle.ts} +3 -3
- package/.pi/extensions/zob-harness/src/{queue.ts → domains/telemetry/queue.ts} +7 -7
- package/.pi/extensions/zob-harness/src/{telemetry.ts → domains/telemetry/telemetry.ts} +4 -4
- package/.pi/extensions/zob-harness/src/{topology → domains/topology}/chains.ts +10 -10
- package/.pi/extensions/zob-harness/src/{topology → domains/topology}/coms.ts +3 -3
- package/.pi/extensions/zob-harness/src/{topology → domains/topology}/orchestration-profiles.ts +8 -8
- package/.pi/extensions/zob-harness/src/{topology → domains/topology}/teams.ts +8 -8
- package/.pi/extensions/zob-harness/src/runtime/adaptive-zmode.ts +2 -2
- package/.pi/extensions/zob-harness/src/runtime/auto-compaction.ts +2 -2
- package/.pi/extensions/zob-harness/src/runtime/commands.ts +49 -27
- package/.pi/extensions/zob-harness/src/runtime/compaction-policy.ts +2 -2
- package/.pi/extensions/zob-harness/src/runtime/delegation-feed.ts +1 -1
- package/.pi/extensions/zob-harness/src/runtime/delegation-monitor.ts +1 -1
- package/.pi/extensions/zob-harness/src/runtime/events.ts +52 -37
- package/.pi/extensions/zob-harness/src/{goal-runtime.ts → runtime/goal-runtime.ts} +9 -9
- package/.pi/extensions/zob-harness/src/runtime/goal-todo-overlay.ts +1 -1
- package/.pi/extensions/zob-harness/src/runtime/plan-capture.ts +2 -2
- package/.pi/extensions/zob-harness/src/runtime/state.ts +15 -13
- package/.pi/extensions/zob-harness/src/runtime/tools-autonomous.ts +2 -2
- package/.pi/extensions/zob-harness/src/runtime/tools-compute.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/tools-coms.ts +15 -12
- package/.pi/extensions/zob-harness/src/runtime/tools-context.ts +2 -2
- package/.pi/extensions/zob-harness/src/runtime/tools-delegation.ts +13 -13
- package/.pi/extensions/zob-harness/src/runtime/tools-factory.ts +19 -19
- package/.pi/extensions/zob-harness/src/runtime/tools-goal-room.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/tools-governed-requests.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/tools-merge-queue.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/tools-mission-control.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/tools-orchestration.ts +9 -9
- package/.pi/extensions/zob-harness/src/runtime/tools-project-dna.ts +2 -2
- package/.pi/extensions/zob-harness/src/runtime/tools-worker-pool.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/tools-workspace-claims.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/tools-zcommit.ts +3 -3
- package/.pi/extensions/zob-harness/src/runtime/widget.ts +25 -8
- package/.pi/extensions/zob-harness/src/runtime/zobHarness.ts +1 -1
- package/.pi/extensions/zob-harness/src/types.ts +2 -2
- package/.pi/extensions/zob-switch/AGENTS.md +9 -0
- package/.pi/extensions/zob-switch/index.ts +9 -121
- package/.pi/extensions/zob-switch/src/AGENTS.md +8 -0
- package/.pi/extensions/zob-switch/src/autocomplete.ts +12 -0
- package/.pi/extensions/zob-switch/src/paths.ts +8 -0
- package/.pi/extensions/zob-switch/src/settings.ts +25 -0
- package/.pi/extensions/zob-switch/src/snapshot.ts +34 -0
- package/.pi/extensions/zob-switch/src/state.ts +57 -0
- package/.pi/factories/agentic-spec-team/README.md +35 -0
- package/.pi/factories/agentic-spec-team/batch-manifest.json +11 -0
- package/.pi/factories/agentic-spec-team/example-agentic-spec-manifest.json +19 -0
- package/.pi/factories/agentic-spec-team/factory.json +98 -0
- package/.pi/factories/agentic-spec-team/pilot-manifest.json +11 -0
- package/.pi/factories/agentic-spec-team/schemas/final-report.schema.json +15 -0
- package/.pi/factories/agentic-spec-team/schemas/manifest.schema.json +14 -0
- package/.pi/factories/agentic-spec-team/schemas/question.schema.json +18 -0
- package/.pi/factories/agentic-spec-team/schemas/source-register.schema.json +11 -0
- package/.pi/factories/agentic-spec-team/schemas/traceability.schema.json +11 -0
- package/.pi/factories/agentic-spec-team/smoke-manifest.json +11 -0
- package/.pi/skills/zob-agentic-spec-team/SKILL.md +145 -0
- package/.pi/skills/zob-split-refactor/SKILL.md +1 -1
- package/.pi/skills/zob-zagent-creator/SKILL.md +256 -12
- package/.pi/zagents/bdd-writer.json +20 -0
- package/.pi/zagents/data-profile-analyst.json +20 -0
- package/.pi/zagents/domain-modeler.json +20 -0
- package/.pi/zagents/planner-handoff-writer.json +20 -0
- package/.pi/zagents/prompts/agentic-spec-run-role.md +30 -0
- package/.pi/zagents/source-intake-steward.json +20 -0
- package/.pi/zagents/spec-chief.json +21 -0
- package/.pi/zagents/spec-oracle.json +20 -0
- package/.pi/zagents/spec-writer.json +20 -0
- package/.pi/zagents/ux-flow-analyst.json +20 -0
- package/.pi/zteams/agentic-spec-run.json +42 -0
- package/.pi/zteams/agentic-spec-run.tmux.sh +134 -0
- package/SOURCE_INDEX.md +1 -1
- package/package.json +9 -1
- package/scripts/README.md +1 -1
- package/scripts/agentic-spec-team/validate-bdd.mjs +13 -0
- package/scripts/agentic-spec-team/validate-final-report.mjs +14 -0
- package/scripts/agentic-spec-team/validate-manifest.mjs +14 -0
- package/scripts/agentic-spec-team/validate-oracle-ready.mjs +13 -0
- package/scripts/agentic-spec-team/validate-question-loop.mjs +15 -0
- package/scripts/agentic-spec-team/validate-run.mjs +11 -0
- package/scripts/agentic-spec-team/validate-source-register.mjs +17 -0
- package/scripts/agentic-spec-team/validate-traceability.mjs +20 -0
- package/scripts/agentic-spec-team/validate-workgraph.mjs +13 -0
- package/scripts/autonomy/mission-readiness-secret-smoke.mjs +5 -5
- package/scripts/git-ops/commit-policy-smoke.mjs +5 -4
- package/scripts/goal-todo/child-goal-ref-smoke.mjs +2 -2
- package/scripts/path-policy/validate-smoke.mjs +3 -3
- package/scripts/project-dna/AGENTS.md +39 -0
- package/scripts/project-dna/{validate-scaffold.mjs → validation/validate-scaffold.mjs} +7 -7
- package/scripts/spec-run.mjs +365 -0
- package/scripts/worker-pool/static-smoke.mjs +5 -5
- package/scripts/zagent-static-smoke.mjs +35 -6
- package/scripts/zpeer-local-e2e-smoke.mjs +6 -5
- package/scripts/zpeer-static-smoke.mjs +17 -17
- /package/.pi/extensions/zob-harness/src/{types → core/types}/core.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{utils → core/utils}/hashing.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{utils → core/utils}/json.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{utils → core/utils}/paths.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/AGENTS.md +0 -0
- /package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/pending-replies.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/types.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/ledger.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/types.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/validate.ts +0 -0
- /package/.pi/extensions/zob-harness/src/{schemas-project-dna.ts → runtime/schemas-project-dna.ts} +0 -0
- /package/.pi/extensions/zob-harness/src/{schemas.ts → runtime/schemas.ts} +0 -0
- /package/scripts/project-dna/{bench-smoke.mjs → benchmark/bench-smoke.mjs} +0 -0
- /package/scripts/project-dna/{build-capsules.mjs → capsules/build-capsules.mjs} +0 -0
- /package/scripts/project-dna/{emit-golden-cases.mjs → emit/emit-golden-cases.mjs} +0 -0
- /package/scripts/project-dna/{emit-ontology.mjs → emit/emit-ontology.mjs} +0 -0
- /package/scripts/project-dna/{oracle-review-smoke.mjs → oracle/oracle-review-smoke.mjs} +0 -0
- /package/scripts/project-dna/{query-context.mjs → query/query-context.mjs} +0 -0
- /package/scripts/project-dna/{query-steward.mjs → query/query-steward.mjs} +0 -0
- /package/scripts/project-dna/{build-sample-spec.mjs → sample/build-sample-spec.mjs} +0 -0
- /package/scripts/project-dna/{generate-sample.mjs → sample/generate-sample.mjs} +0 -0
- /package/scripts/project-dna/{validate-sample-project.mjs → sample/validate-sample-project.mjs} +0 -0
- /package/scripts/project-dna/{scan.mjs → scan/scan.mjs} +0 -0
- /package/scripts/project-dna/{validate-scan-artifacts.mjs → scan/validate-scan-artifacts.mjs} +0 -0
- /package/scripts/project-dna/{validate-5of5.mjs → validation/validate-5of5.mjs} +0 -0
- /package/scripts/project-dna/{validate-golden-cases.mjs → validation/validate-golden-cases.mjs} +0 -0
- /package/scripts/project-dna/{validate-ontology.mjs → validation/validate-ontology.mjs} +0 -0
- /package/scripts/project-dna/{plan-workflow.mjs → workflow/plan-workflow.mjs} +0 -0
- /package/scripts/project-dna/{validate-workflow.mjs → workflow/validate-workflow.mjs} +0 -0
|
@@ -103,7 +103,7 @@ const requiredFiles = [
|
|
|
103
103
|
"scripts/project-dna/validate-golden-cases.mjs",
|
|
104
104
|
"scripts/project-dna/query-steward.mjs",
|
|
105
105
|
"scripts/project-dna/validate-5of5.mjs",
|
|
106
|
-
".pi/extensions/zob-harness/src/project-dna.ts",
|
|
106
|
+
".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts",
|
|
107
107
|
".pi/extensions/zob-harness/src/runtime/tools-project-dna.ts",
|
|
108
108
|
"scripts/project-dna/bench-smoke.mjs",
|
|
109
109
|
"scripts/project-dna/oracle-review-smoke.mjs",
|
|
@@ -331,12 +331,12 @@ assertIncludes(queryScript, "bounded_context_only", "scripts/project-dna/query-c
|
|
|
331
331
|
assertIncludes(queryScript, "agent_loads_entire_project: false", "scripts/project-dna/query-context.mjs");
|
|
332
332
|
assertIncludes(queryScript, "knowledge_backend_write_enabled: false", "scripts/project-dna/query-context.mjs");
|
|
333
333
|
|
|
334
|
-
const runtimeProjectDna = requireFile(".pi/extensions/zob-harness/src/project-dna.ts");
|
|
335
|
-
assertIncludes(runtimeProjectDna, "zob.project-dna-agentic-plan.v1", ".pi/extensions/zob-harness/src/project-dna.ts");
|
|
336
|
-
assertIncludes(runtimeProjectDna, "zob.project-dna-query-result.v1", ".pi/extensions/zob-harness/src/project-dna.ts");
|
|
337
|
-
assertIncludes(runtimeProjectDna, "zob.project-dna-federated-query-result.v1", ".pi/extensions/zob-harness/src/project-dna.ts");
|
|
338
|
-
assertIncludes(runtimeProjectDna, "knowledge_backend_write_enabled: false", ".pi/extensions/zob-harness/src/project-dna.ts");
|
|
339
|
-
assertIncludes(runtimeProjectDna, "durable_promotion_allowed: false", ".pi/extensions/zob-harness/src/project-dna.ts");
|
|
334
|
+
const runtimeProjectDna = requireFile(".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
|
|
335
|
+
assertIncludes(runtimeProjectDna, "zob.project-dna-agentic-plan.v1", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
|
|
336
|
+
assertIncludes(runtimeProjectDna, "zob.project-dna-query-result.v1", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
|
|
337
|
+
assertIncludes(runtimeProjectDna, "zob.project-dna-federated-query-result.v1", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
|
|
338
|
+
assertIncludes(runtimeProjectDna, "knowledge_backend_write_enabled: false", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
|
|
339
|
+
assertIncludes(runtimeProjectDna, "durable_promotion_allowed: false", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
|
|
340
340
|
|
|
341
341
|
const runtimeProjectDnaTools = requireFile(".pi/extensions/zob-harness/src/runtime/tools-project-dna.ts");
|
|
342
342
|
assertIncludes(runtimeProjectDnaTools, "zob_project_dna_plan_workflow", ".pi/extensions/zob-harness/src/runtime/tools-project-dna.ts");
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { existsSync, statSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
|
|
7
|
+
const RUNS_ROOT = "reports/agentic-spec-runs";
|
|
8
|
+
const TEAM_SCRIPT = ".pi/zteams/agentic-spec-run.tmux.sh";
|
|
9
|
+
const DEFAULT_AGENT = "spec-chief";
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const command = args[0] && !args[0].startsWith("--") ? args[0] : "help";
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const result = await dispatch(command, command === "help" ? args : args.slice(1));
|
|
15
|
+
if (result) print(result);
|
|
16
|
+
if (result?.no_ship) process.exitCode = 1;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
print({ schema: "agentic-spec-run.error.v1", status: "error", no_ship: true, message: error?.message || String(error) });
|
|
19
|
+
process.exitCode = 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function dispatch(cmd, values) {
|
|
23
|
+
if (cmd === "help" || values.includes("--help") || args.includes("--help")) return help();
|
|
24
|
+
if (cmd === "init") return initRun(parseOptions(values));
|
|
25
|
+
if (cmd === "auto-pilot") return autoPilot(parseOptions(values));
|
|
26
|
+
if (cmd === "send-kickoff") return sendKickoff(values[0], parseOptions(values.slice(1)));
|
|
27
|
+
if (cmd === "team-start") return teamStart(values[0]);
|
|
28
|
+
if (cmd === "team-status") return teamStatus(parseRunOrSession(values));
|
|
29
|
+
if (cmd === "team-attach") return teamAttach(values[0], values[1] || DEFAULT_AGENT);
|
|
30
|
+
if (cmd === "team-close") return teamClose(parseRunOrSession(values));
|
|
31
|
+
if (cmd === "wait") return waitForCompletion(values[0], parseOptions(values.slice(1)));
|
|
32
|
+
if (cmd === "validate") return validateRun(values[0]);
|
|
33
|
+
if (cmd === "questions") return listQuestions(values[0], parseOptions(values.slice(1)));
|
|
34
|
+
if (cmd === "answer") return answerQuestion(values[0], values[1], parseOptions(values.slice(2)));
|
|
35
|
+
if (cmd === "resume") return resumeRun(values[0]);
|
|
36
|
+
if (cmd === "status") return readRunStatus(values[0]);
|
|
37
|
+
return { ...help(), status: "blocked", no_ship: true, message: `unknown command: ${cmd}` };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function help() {
|
|
41
|
+
return {
|
|
42
|
+
schema: "agentic-spec-run.help.v1",
|
|
43
|
+
usage: [
|
|
44
|
+
"node scripts/spec-run.mjs init --mission <text>|--mission-file <path> --source <path> [--source <path>] [--name name] [--run-id id] [--owner owner] [--prepare-only]",
|
|
45
|
+
"node scripts/spec-run.mjs auto-pilot --mission <text>|--mission-file <path> --source <path> [--timeout-ms 14400000] [--poll-ms 30000] [--no-submit] [--no-wait] [--no-close]",
|
|
46
|
+
"node scripts/spec-run.mjs send-kickoff reports/agentic-spec-runs/<run_id> --session agentic-spec-run-<run_id> --agent spec-chief --submit",
|
|
47
|
+
"node scripts/spec-run.mjs answer <run_id> Q-001 --text '<answer>' --answered-by owner",
|
|
48
|
+
"node scripts/spec-run.mjs validate <run_id>",
|
|
49
|
+
],
|
|
50
|
+
output: "json",
|
|
51
|
+
v1_posture: "skill + factory + ZTeam + CLI; no runtime extension",
|
|
52
|
+
no_ship: false,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function initRun(opts) {
|
|
57
|
+
const sources = opts.source ?? [];
|
|
58
|
+
const mission = await resolveMission(opts);
|
|
59
|
+
if (!mission) return blocked("init", "missing mission; use --mission or --mission-file");
|
|
60
|
+
if (!sources.length) return blocked("init", "missing at least one --source path");
|
|
61
|
+
|
|
62
|
+
const runId = safeRunId(opts.runId || `${opts.name || "spec"}-${timestamp()}`);
|
|
63
|
+
const runDir = path.join(RUNS_ROOT, runId);
|
|
64
|
+
const createdAt = new Date().toISOString();
|
|
65
|
+
await mkdirs(runDir, ["analysis", "spec", "validation", "handoff", "oracle", "checkpoints"]);
|
|
66
|
+
|
|
67
|
+
const sourceRows = sources.map((source, index) => inspectSource(source, index));
|
|
68
|
+
const manifest = {
|
|
69
|
+
schema: "agentic-spec-run.manifest.v1",
|
|
70
|
+
run_id: runId,
|
|
71
|
+
name: opts.name || runId,
|
|
72
|
+
owner: opts.owner || "owner",
|
|
73
|
+
created_at: createdAt,
|
|
74
|
+
mission,
|
|
75
|
+
mission_file: opts.missionFile || null,
|
|
76
|
+
source_count: sourceRows.length,
|
|
77
|
+
source_refs: sourceRows.map((row) => row.source_id),
|
|
78
|
+
run_dir: runDir,
|
|
79
|
+
team_id: "agentic-spec-run",
|
|
80
|
+
entry_agent: DEFAULT_AGENT,
|
|
81
|
+
expected_session: sessionName(runId),
|
|
82
|
+
policies: {
|
|
83
|
+
source_policy: "citation_only_by_default",
|
|
84
|
+
raw_secret_storage: false,
|
|
85
|
+
human_questions_block_completion: true,
|
|
86
|
+
final_oracle_required: true,
|
|
87
|
+
traceability_required: true,
|
|
88
|
+
runtime_extension_v1: false,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
const teamPlan = {
|
|
92
|
+
schema: "agentic-spec.team-plan.v1",
|
|
93
|
+
run_id: runId,
|
|
94
|
+
session: sessionName(runId),
|
|
95
|
+
entry_agent: DEFAULT_AGENT,
|
|
96
|
+
agents: ["spec-chief", "source-intake-steward", "data-profile-analyst", "domain-modeler", "ux-flow-analyst", "spec-writer", "bdd-writer", "planner-handoff-writer", "spec-oracle"],
|
|
97
|
+
rooms: ["spec-control", "intake", "data", "domain", "ux", "writing", "validation", "handoff", "oracle"],
|
|
98
|
+
};
|
|
99
|
+
const status = {
|
|
100
|
+
schema: "agentic-spec-run.status.v1",
|
|
101
|
+
run_id: runId,
|
|
102
|
+
status: "ready",
|
|
103
|
+
phase: "init",
|
|
104
|
+
no_ship: false,
|
|
105
|
+
run_dir: runDir,
|
|
106
|
+
open_blocking_questions: 0,
|
|
107
|
+
final_oracle: "pending",
|
|
108
|
+
updated_at: createdAt,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
await writeJson(path.join(runDir, "run-manifest.json"), manifest);
|
|
112
|
+
await writeJson(path.join(runDir, "source-register.json"), { schema: "agentic-spec.source-register.v1", run_id: runId, sources: sourceRows });
|
|
113
|
+
await writeJson(path.join(runDir, "team-plan.json"), teamPlan);
|
|
114
|
+
await writeJson(path.join(runDir, "status.json"), status);
|
|
115
|
+
await fs.writeFile(path.join(runDir, "source-register.md"), renderSourceRegister(sourceRows), "utf8");
|
|
116
|
+
await fs.writeFile(path.join(runDir, "chief-kickoff.md"), renderKickoff(manifest, sourceRows), "utf8");
|
|
117
|
+
await fs.writeFile(path.join(runDir, "questions.md"), "# Open Questions\n\nNo questions recorded yet.\n", "utf8");
|
|
118
|
+
await fs.writeFile(path.join(runDir, "answers.md"), "# Answers\n\nNo answers recorded yet.\n", "utf8");
|
|
119
|
+
await fs.writeFile(path.join(runDir, "questions.jsonl"), "", "utf8");
|
|
120
|
+
await fs.writeFile(path.join(runDir, "answers.jsonl"), "", "utf8");
|
|
121
|
+
await fs.writeFile(path.join(runDir, "assumptions.md"), "# Assumptions\n\n", "utf8");
|
|
122
|
+
await fs.writeFile(path.join(runDir, "validation/traceability-matrix.md"), "# Traceability Matrix\n\n| Source | Fact / answer / assumption | Requirement | Acceptance criteria | Task | Oracle check |\n| --- | --- | --- | --- | --- | --- |\n", "utf8");
|
|
123
|
+
await writeJson(path.join(runDir, "validation/traceability-matrix.json"), { schema: "agentic-spec.traceability.v1", run_id: runId, rows: [] });
|
|
124
|
+
|
|
125
|
+
return { schema: "agentic-spec-run.init-result.v1", status: "ready", no_ship: false, run_id: runId, run_dir: runDir, prepare_only: opts.prepareOnly !== false, full_team_launched: false, expected_session: sessionName(runId) };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function autoPilot(opts) {
|
|
129
|
+
const timeoutMs = Number(opts.timeoutMs || 4 * 60 * 60 * 1000);
|
|
130
|
+
const pollMs = Number(opts.pollMs || 30 * 1000);
|
|
131
|
+
const submit = opts.submit !== false;
|
|
132
|
+
const wait = opts.wait !== false;
|
|
133
|
+
const close = opts.close !== false;
|
|
134
|
+
const init = await initRun({ ...opts, prepareOnly: true });
|
|
135
|
+
if (init.no_ship) return init;
|
|
136
|
+
const sessionGuard = validateSessionOverride(opts.session, sessionName(init.run_id));
|
|
137
|
+
if (sessionGuard.no_ship) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "blocked", no_ship: true, phase: "session-guard", init, session_guard: sessionGuard };
|
|
138
|
+
const team_start = teamStart(init.run_id);
|
|
139
|
+
if (team_start.no_ship) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "blocked", no_ship: true, phase: "team-start", init, team_start };
|
|
140
|
+
const kickoff = await sendKickoff(init.run_dir, { session: sessionGuard.session, agent: opts.agent || DEFAULT_AGENT, submit });
|
|
141
|
+
if (kickoff.no_ship) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "blocked", no_ship: true, phase: "send-kickoff", init, team_start, kickoff };
|
|
142
|
+
if (!wait) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "launched", no_ship: false, run_id: init.run_id, run_dir: init.run_dir, run_session: sessionGuard.session, waited: false, closed: false, next_command: `npm run spec-run -- team-status --session ${sessionGuard.session}` };
|
|
143
|
+
const completion = await waitForCompletion(init.run_id, { timeoutMs, pollMs });
|
|
144
|
+
if (completion.status !== "pass") return { schema: "agentic-spec-run.auto-pilot-result.v1", status: completion.status, no_ship: true, run_id: init.run_id, run_dir: init.run_dir, run_session: sessionGuard.session, completion, closed: false, close_skipped_reason: "completion_not_pass_no_ship_false" };
|
|
145
|
+
let closeResult = { status: "skipped", closed: false, reason: "--no-close" };
|
|
146
|
+
if (close) closeResult = teamClose({ runId: init.run_id, confirm: true, session: sessionGuard.session });
|
|
147
|
+
return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "pass", no_ship: false, run_id: init.run_id, run_dir: init.run_dir, run_session: sessionGuard.session, completion, close: closeResult, closed: closeResult.closed === true };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function sendKickoff(runDirOrId, opts) {
|
|
151
|
+
const runDir = resolveRunDir(runDirOrId);
|
|
152
|
+
const manifest = await readJson(path.join(runDir, "run-manifest.json"));
|
|
153
|
+
const kickoffPath = path.join(runDir, "chief-kickoff.md");
|
|
154
|
+
const session = opts.session || sessionName(manifest.run_id);
|
|
155
|
+
const guard = validateSessionOverride(session, sessionName(manifest.run_id));
|
|
156
|
+
if (guard.no_ship) return { schema: "agentic-spec-run.kickoff-result.v1", status: "blocked", no_ship: true, session_guard: guard };
|
|
157
|
+
const agent = opts.agent || DEFAULT_AGENT;
|
|
158
|
+
if (!opts.submit) return { schema: "agentic-spec-run.kickoff-result.v1", status: "pass", no_ship: false, submitted: false, run_id: manifest.run_id, run_dir: runDir, kickoff_ref: kickoffPath, session, agent };
|
|
159
|
+
const target = `${session}:${agent}`;
|
|
160
|
+
const body = await fs.readFile(kickoffPath, "utf8");
|
|
161
|
+
const payload = `Please execute this Agentic Spec kickoff. Read ${kickoffPath} and coordinate the run.\n\n${body}`;
|
|
162
|
+
const sent = spawnSync("tmux", ["send-keys", "-t", target, payload, "C-m"], { encoding: "utf8" });
|
|
163
|
+
if (sent.status !== 0) return { schema: "agentic-spec-run.kickoff-result.v1", status: "blocked", no_ship: true, submitted: false, reason: "tmux_send_failed", stderr: sent.stderr?.trim(), target };
|
|
164
|
+
return { schema: "agentic-spec-run.kickoff-result.v1", status: "pass", no_ship: false, submitted: true, run_id: manifest.run_id, run_dir: runDir, kickoff_ref: kickoffPath, session, agent };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function teamStart(runId) {
|
|
168
|
+
if (!runId) return blocked("team-start", "missing run_id");
|
|
169
|
+
return runTeamScript(["start-detached", runId], "agentic-spec-run.team-start-result.v1");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function teamStatus(spec) {
|
|
173
|
+
const session = spec.session || (spec.runId ? sessionName(spec.runId) : null);
|
|
174
|
+
if (!session) return blocked("team-status", "missing --session or run_id");
|
|
175
|
+
const runId = spec.runId || session.replace(/^agentic-spec-run-/u, "");
|
|
176
|
+
return runTeamScript(["status", runId], "agentic-spec-run.team-status-result.v1", { session });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function teamAttach(runId, agent) {
|
|
180
|
+
if (!runId) return blocked("team-attach", "missing run_id");
|
|
181
|
+
return runTeamScript(["attach", runId, agent || DEFAULT_AGENT], "agentic-spec-run.team-attach-result.v1");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function teamClose(spec) {
|
|
185
|
+
const session = spec.session || (spec.runId ? sessionName(spec.runId) : null);
|
|
186
|
+
const runId = spec.runId || session?.replace(/^agentic-spec-run-/u, "");
|
|
187
|
+
if (!runId || !session) return blocked("team-close", "missing --session or run_id");
|
|
188
|
+
const guard = validateSessionOverride(session, sessionName(runId));
|
|
189
|
+
if (guard.no_ship) return { schema: "agentic-spec-run.team-close-result.v1", status: "blocked", no_ship: true, closed: false, session_guard: guard };
|
|
190
|
+
if (!spec.confirm) return { schema: "agentic-spec-run.team-close-result.v1", status: "blocked", no_ship: true, closed: false, reason: "team-close requires --confirm" };
|
|
191
|
+
return runTeamScript(["close", runId], "agentic-spec-run.team-close-result.v1", { session, closed: true });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async function waitForCompletion(runId, opts) {
|
|
195
|
+
const runDir = resolveRunDir(runId);
|
|
196
|
+
const timeoutMs = Number(opts.timeoutMs || 4 * 60 * 60 * 1000);
|
|
197
|
+
const pollMs = Number(opts.pollMs || 30 * 1000);
|
|
198
|
+
const deadline = Date.now() + timeoutMs;
|
|
199
|
+
const checked = [];
|
|
200
|
+
while (Date.now() <= deadline) {
|
|
201
|
+
for (const file of [path.join(runDir, "final-report.json"), path.join(runDir, "status.json")]) {
|
|
202
|
+
const parsed = await readJsonIfExists(file);
|
|
203
|
+
if (!parsed) continue;
|
|
204
|
+
checked.push(file);
|
|
205
|
+
if (isPassingCompletion(parsed)) return { schema: "agentic-spec-run.wait-result.v1", status: "pass", no_ship: false, completion_ref: file, report: parsed };
|
|
206
|
+
if (isBlockingCompletion(parsed)) return { schema: "agentic-spec-run.wait-result.v1", status: "blocked", no_ship: true, completion_ref: file, report: parsed };
|
|
207
|
+
}
|
|
208
|
+
await sleep(pollMs);
|
|
209
|
+
}
|
|
210
|
+
return { schema: "agentic-spec-run.wait-result.v1", status: "timeout", no_ship: true, timeout_ms: timeoutMs, checked_refs: [...new Set(checked)] };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function validateRun(runIdOrDir) {
|
|
214
|
+
const runDir = resolveRunDir(runIdOrDir);
|
|
215
|
+
const required = ["run-manifest.json", "source-register.json", "source-register.md", "team-plan.json", "chief-kickoff.md", "status.json", "questions.md", "answers.md", "validation/traceability-matrix.json", "validation/traceability-matrix.md"];
|
|
216
|
+
const missing = required.filter((file) => !existsSync(path.join(runDir, file)));
|
|
217
|
+
const errors = [...missing.map((file) => `missing ${file}`)];
|
|
218
|
+
const manifest = await readJsonIfExists(path.join(runDir, "run-manifest.json"));
|
|
219
|
+
const sources = await readJsonIfExists(path.join(runDir, "source-register.json"));
|
|
220
|
+
const traceability = await readJsonIfExists(path.join(runDir, "validation/traceability-matrix.json"));
|
|
221
|
+
if (manifest?.schema !== "agentic-spec-run.manifest.v1") errors.push("manifest schema mismatch");
|
|
222
|
+
if (!Array.isArray(sources?.sources) || sources.sources.length < 1) errors.push("source-register must include at least one source");
|
|
223
|
+
if (!Array.isArray(traceability?.rows)) errors.push("traceability rows must be an array");
|
|
224
|
+
const questions = await readJsonlIfExists(path.join(runDir, "questions.jsonl"));
|
|
225
|
+
const openBlocking = questions.filter((q) => q?.blocking === true && q?.status !== "answered" && q?.status !== "closed");
|
|
226
|
+
if (openBlocking.length > 0) errors.push(`open blocking questions: ${openBlocking.map((q) => q.question_id).join(", ")}`);
|
|
227
|
+
return { schema: "agentic-spec-run.validation-result.v1", status: errors.length ? "fail" : "pass", no_ship: errors.length > 0, run_dir: runDir, errors, checked_files: required };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async function listQuestions(runId, opts) {
|
|
231
|
+
const runDir = resolveRunDir(runId);
|
|
232
|
+
const questions = await readJsonlIfExists(path.join(runDir, "questions.jsonl"));
|
|
233
|
+
const rows = opts.openOnly ? questions.filter((q) => q.status === "open") : questions;
|
|
234
|
+
return { schema: "agentic-spec-run.questions-result.v1", status: "pass", no_ship: false, run_id: path.basename(runDir), questions: rows };
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function answerQuestion(runId, questionId, opts) {
|
|
238
|
+
if (!runId || !questionId) return blocked("answer", "usage: answer <run_id> <question_id> --text '<answer>'");
|
|
239
|
+
if (!opts.text) return blocked("answer", "missing --text answer");
|
|
240
|
+
const runDir = resolveRunDir(runId);
|
|
241
|
+
const answer = {
|
|
242
|
+
schema: "agentic-spec.answer.v1",
|
|
243
|
+
question_id: questionId,
|
|
244
|
+
answered_by: opts.answeredBy || "owner",
|
|
245
|
+
answer_summary: opts.text,
|
|
246
|
+
selected_option: opts.option || null,
|
|
247
|
+
raw_answer_stored: false,
|
|
248
|
+
answered_at: new Date().toISOString(),
|
|
249
|
+
};
|
|
250
|
+
await fs.appendFile(path.join(runDir, "answers.jsonl"), `${JSON.stringify(answer)}\n`, "utf8");
|
|
251
|
+
await fs.appendFile(path.join(runDir, "answers.md"), `\n## ${questionId}\n\nAnswered by: ${answer.answered_by}\n\n${answer.answer_summary}\n`, "utf8");
|
|
252
|
+
const statusPath = path.join(runDir, "status.json");
|
|
253
|
+
const status = await readJsonIfExists(statusPath) || {};
|
|
254
|
+
status.status = "answer_recorded";
|
|
255
|
+
status.phase = "human-clarification";
|
|
256
|
+
status.no_ship = true;
|
|
257
|
+
status.updated_at = new Date().toISOString();
|
|
258
|
+
status.next_command = `npm run spec-run -- resume ${path.basename(runDir)}`;
|
|
259
|
+
await writeJson(statusPath, status);
|
|
260
|
+
return { schema: "agentic-spec-run.answer-result.v1", status: "pass", no_ship: false, run_id: path.basename(runDir), answer_ref: path.join(runDir, "answers.md"), next_command: status.next_command };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function resumeRun(runId) {
|
|
264
|
+
const runDir = resolveRunDir(runId);
|
|
265
|
+
const statusPath = path.join(runDir, "status.json");
|
|
266
|
+
const status = await readJsonIfExists(statusPath) || {};
|
|
267
|
+
status.status = "ready";
|
|
268
|
+
status.phase = "resume_after_human_answer";
|
|
269
|
+
status.no_ship = false;
|
|
270
|
+
status.updated_at = new Date().toISOString();
|
|
271
|
+
await writeJson(statusPath, status);
|
|
272
|
+
return { schema: "agentic-spec-run.resume-result.v1", status: "pass", no_ship: false, run_id: path.basename(runDir), status_ref: statusPath, next_step: `send kickoff or attach spec-chief in ${sessionName(path.basename(runDir))}` };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function readRunStatus(runId) {
|
|
276
|
+
const runDir = resolveRunDir(runId);
|
|
277
|
+
return await readJson(path.join(runDir, "status.json"));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function runTeamScript(teamArgs, schema, extra = {}) {
|
|
281
|
+
if (!existsSync(TEAM_SCRIPT)) return { schema, status: "blocked", no_ship: true, reason: `missing ${TEAM_SCRIPT}` };
|
|
282
|
+
const result = spawnSync("bash", [TEAM_SCRIPT, ...teamArgs], { encoding: "utf8", cwd: process.cwd(), env: process.env });
|
|
283
|
+
if (result.status !== 0) return { schema, status: "blocked", no_ship: true, stdout: result.stdout?.trim(), stderr: result.stderr?.trim(), ...extra };
|
|
284
|
+
return { schema, status: "pass", no_ship: false, stdout: result.stdout?.trim(), ...extra };
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function parseOptions(values) {
|
|
288
|
+
const opts = { source: [], submit: true, wait: true, close: true, prepareOnly: true };
|
|
289
|
+
for (let i = 0; i < values.length; i++) {
|
|
290
|
+
const arg = values[i];
|
|
291
|
+
if (arg === "--source") opts.source.push(values[++i]);
|
|
292
|
+
else if (arg === "--mission") opts.mission = values[++i];
|
|
293
|
+
else if (arg === "--mission-file") opts.missionFile = values[++i];
|
|
294
|
+
else if (arg === "--name") opts.name = values[++i];
|
|
295
|
+
else if (arg === "--run-id") opts.runId = values[++i];
|
|
296
|
+
else if (arg === "--owner") opts.owner = values[++i];
|
|
297
|
+
else if (arg === "--session") opts.session = values[++i];
|
|
298
|
+
else if (arg === "--agent") opts.agent = values[++i];
|
|
299
|
+
else if (arg === "--timeout-ms") opts.timeoutMs = values[++i];
|
|
300
|
+
else if (arg === "--poll-ms") opts.pollMs = values[++i];
|
|
301
|
+
else if (arg === "--answered-by") opts.answeredBy = values[++i];
|
|
302
|
+
else if (arg === "--text") opts.text = values[++i];
|
|
303
|
+
else if (arg === "--option") opts.option = values[++i];
|
|
304
|
+
else if (arg === "--prepare-only") opts.prepareOnly = true;
|
|
305
|
+
else if (arg === "--no-submit") opts.submit = false;
|
|
306
|
+
else if (arg === "--no-wait") opts.wait = false;
|
|
307
|
+
else if (arg === "--no-close") opts.close = false;
|
|
308
|
+
else if (arg === "--open-only") opts.openOnly = true;
|
|
309
|
+
else if (arg === "--confirm") opts.confirm = true;
|
|
310
|
+
}
|
|
311
|
+
return opts;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function parseRunOrSession(values) {
|
|
315
|
+
const opts = parseOptions(values);
|
|
316
|
+
const runId = values.find((value) => !value.startsWith("--") && ![opts.session].includes(value));
|
|
317
|
+
return { runId, session: opts.session, confirm: opts.confirm };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async function resolveMission(opts) {
|
|
321
|
+
if (opts.missionFile) return fs.readFile(opts.missionFile, "utf8");
|
|
322
|
+
return opts.mission || "";
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function inspectSource(source, index) {
|
|
326
|
+
const exists = existsSync(source);
|
|
327
|
+
const stat = exists ? statSync(source) : null;
|
|
328
|
+
return {
|
|
329
|
+
source_id: `SRC-${String(index + 1).padStart(3, "0")}`,
|
|
330
|
+
path: source,
|
|
331
|
+
exists,
|
|
332
|
+
kind: stat?.isDirectory() ? "directory" : stat?.isFile() ? "file" : "missing",
|
|
333
|
+
size_bytes: stat?.isFile() ? stat.size : null,
|
|
334
|
+
policy: "citation_only",
|
|
335
|
+
sensitivity: "unknown_until_intake",
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function renderSourceRegister(rows) {
|
|
340
|
+
return `# Source Register\n\n| Source | Path | Kind | Exists | Policy | Sensitivity |\n| --- | --- | --- | --- | --- | --- |\n${rows.map((row) => `| ${row.source_id} | ${row.path} | ${row.kind} | ${row.exists} | ${row.policy} | ${row.sensitivity} |`).join("\n")}\n`;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function renderKickoff(manifest, sources) {
|
|
344
|
+
return `# Agentic Spec Run Kickoff\n\nRun: ${manifest.run_id}\nSession: ${manifest.expected_session}\nEntry agent: ${manifest.entry_agent}\n\n## Mission\n\n${manifest.mission}\n\n## Sources\n\n${sources.map((row) => `- ${row.source_id}: ${row.path} (${row.kind}, policy=${row.policy})`).join("\n")}\n\n## Required outputs\n\n- source register and source quality report\n- data profile / domain model / UX flows as applicable\n- mission spec, requirements, BDD acceptance criteria\n- validation/traceability-matrix.md and .json\n- handoff/workgraph.md and implementation tasks\n- oracle/final-oracle-review.json and final-report.json\n\n## Rules\n\nSpec Chief is the only human interlocutor. Do not invent answers to blocking business questions. Completion requires oracle PASS and no_ship=false.\n`;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
async function mkdirs(root, children) {
|
|
348
|
+
await fs.mkdir(root, { recursive: true });
|
|
349
|
+
for (const child of children) await fs.mkdir(path.join(root, child), { recursive: true });
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function sessionName(runId) { return `agentic-spec-run-${safeRunId(runId)}`; }
|
|
353
|
+
function safeRunId(value) { return String(value || "").trim().replace(/[^A-Za-z0-9_-]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 120) || "spec-run"; }
|
|
354
|
+
function timestamp() { return new Date().toISOString().replace(/[-:TZ.]/gu, "").slice(0, 14); }
|
|
355
|
+
function resolveRunDir(runIdOrDir) { return String(runIdOrDir || "").startsWith(RUNS_ROOT) ? runIdOrDir : path.join(RUNS_ROOT, safeRunId(runIdOrDir)); }
|
|
356
|
+
function validateSessionOverride(requestedSession, expectedSession) { const session = requestedSession || expectedSession; return session === expectedSession ? { status: "pass", no_ship: false, session, expected_session: expectedSession } : { status: "blocked", no_ship: true, session, expected_session: expectedSession, reason: "session_must_equal_isolated_agentic_spec_run_session" }; }
|
|
357
|
+
function isPassingCompletion(value) { return value?.no_ship === false && ["pass", "complete", "completed"].includes(String(value?.status || value?.verdict || "").toLowerCase()); }
|
|
358
|
+
function isBlockingCompletion(value) { return value?.no_ship === true || ["blocked", "fail", "failed", "needs_human"].includes(String(value?.status || value?.verdict || "").toLowerCase()); }
|
|
359
|
+
function blocked(phase, reason) { return { schema: "agentic-spec-run.blocked.v1", status: "blocked", no_ship: true, phase, reason }; }
|
|
360
|
+
async function readJson(file) { return JSON.parse(await fs.readFile(file, "utf8")); }
|
|
361
|
+
async function readJsonIfExists(file) { try { return await readJson(file); } catch { return null; } }
|
|
362
|
+
async function readJsonlIfExists(file) { try { const text = await fs.readFile(file, "utf8"); return text.split(/\n/u).filter(Boolean).map((line) => JSON.parse(line)); } catch { return []; } }
|
|
363
|
+
async function writeJson(file, value) { await fs.writeFile(file, `${JSON.stringify(value, null, 2)}\n`, "utf8"); }
|
|
364
|
+
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
|
|
365
|
+
function print(value) { console.log(JSON.stringify(value, null, 2)); }
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
|
|
4
4
|
const files = {
|
|
5
|
-
workerPool: ".pi/extensions/zob-harness/src/worker-pool.ts",
|
|
5
|
+
workerPool: ".pi/extensions/zob-harness/src/domains/governance/worker-pool.ts",
|
|
6
6
|
runtime: ".pi/extensions/zob-harness/src/runtime/tools-worker-pool.ts",
|
|
7
|
-
goalRoom: ".pi/extensions/zob-harness/src/goal-room.ts",
|
|
8
|
-
constants: ".pi/extensions/zob-harness/src/constants.ts",
|
|
9
|
-
schemas: ".pi/extensions/zob-harness/src/schemas.ts",
|
|
10
|
-
governedRequests: ".pi/extensions/zob-harness/src/governed-requests.ts",
|
|
7
|
+
goalRoom: ".pi/extensions/zob-harness/src/domains/goal/goal-room.ts",
|
|
8
|
+
constants: ".pi/extensions/zob-harness/src/core/constants.ts",
|
|
9
|
+
schemas: ".pi/extensions/zob-harness/src/runtime/schemas.ts",
|
|
10
|
+
governedRequests: ".pi/extensions/zob-harness/src/domains/governance/governed-requests.ts",
|
|
11
11
|
governedRuntime: ".pi/extensions/zob-harness/src/runtime/tools-governed-requests.ts",
|
|
12
12
|
registry: ".pi/capabilities/zob-public-runtime-capabilities.json",
|
|
13
13
|
};
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
|
|
4
4
|
const files = [
|
|
5
|
-
'.pi/extensions/zob-harness/src/zagents.ts',
|
|
5
|
+
'.pi/extensions/zob-harness/src/domains/coms/zagents.ts',
|
|
6
6
|
'.pi/extensions/zob-harness/src/runtime/commands.ts',
|
|
7
7
|
'.pi/extensions/zob-harness/src/runtime/events.ts',
|
|
8
8
|
'.pi/extensions/zob-harness/src/runtime/state.ts',
|
|
9
9
|
'.pi/extensions/zob-harness/src/runtime/widget.ts',
|
|
10
|
-
'.pi/extensions/zob-harness/src/coms-v2/zpeer.ts',
|
|
10
|
+
'.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts',
|
|
11
11
|
'.pi/capabilities/zob-public-runtime-capabilities.json',
|
|
12
12
|
'.pi/skills/zob-zagent-creator/SKILL.md',
|
|
13
13
|
];
|
|
@@ -20,8 +20,8 @@ function requireIncludes(file, needles, label = file) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const zagents = contents['.pi/extensions/zob-harness/src/zagents.ts'];
|
|
24
|
-
requireIncludes('.pi/extensions/zob-harness/src/zagents.ts', [
|
|
23
|
+
const zagents = contents['.pi/extensions/zob-harness/src/domains/coms/zagents.ts'];
|
|
24
|
+
requireIncludes('.pi/extensions/zob-harness/src/domains/coms/zagents.ts', [
|
|
25
25
|
'const ZAGENTS_DIR = ".pi/zagents"',
|
|
26
26
|
'const ZTEAMS_DIR = ".pi/zteams"',
|
|
27
27
|
'const ZAGENT_PROMPTS_DIR = ".pi/zagents/prompts"',
|
|
@@ -32,7 +32,11 @@ requireIncludes('.pi/extensions/zob-harness/src/zagents.ts', [
|
|
|
32
32
|
'export function listZagentManifests',
|
|
33
33
|
'export function listZteamManifests',
|
|
34
34
|
'export function zteamAllowsZpeerContact',
|
|
35
|
+
'export function resolveZagentTeamMemberships',
|
|
36
|
+
'export function resolveZagentRuntimeRoomBindings',
|
|
35
37
|
'localOnly: true',
|
|
38
|
+
'zagent.model must be a safe Pi --model pattern',
|
|
39
|
+
'zagent.defaultMode must be one of',
|
|
36
40
|
'networkEnabled: false',
|
|
37
41
|
'bodyStored: false',
|
|
38
42
|
]);
|
|
@@ -54,6 +58,10 @@ requireIncludes('.pi/extensions/zob-harness/src/runtime/commands.ts', [
|
|
|
54
58
|
'normalizeZagentRoomBindings',
|
|
55
59
|
'readZagentPrompt',
|
|
56
60
|
'ZOB_ZAGENT_ID=${member.id} pi',
|
|
61
|
+
'--model ${model}',
|
|
62
|
+
'modelIdHashes: plan.modelIds.map((modelId) => sha256(modelId))',
|
|
63
|
+
'defaultModeHashes: plan.defaultModes.map((mode) => sha256(mode))',
|
|
64
|
+
'defaultMode=${defaultMode}',
|
|
57
65
|
'After each session starts, run /zagent use <id> to bind its ZPeer alias/rooms.',
|
|
58
66
|
'Project-local full-session ZAgents',
|
|
59
67
|
'Project-local ZTeams',
|
|
@@ -68,12 +76,15 @@ requireIncludes('.pi/extensions/zob-harness/src/runtime/events.ts', [
|
|
|
68
76
|
'process.env.ZOB_ZAGENT_ID?.trim()',
|
|
69
77
|
'loadZagentManifest(repoRoot, zagentId)',
|
|
70
78
|
'readZagentPrompt(repoRoot, manifest.promptRef)',
|
|
71
|
-
'
|
|
79
|
+
'resolveZagentRuntimeRoomBindings(repoRoot, manifest)',
|
|
72
80
|
'state.zagent = nextZagent',
|
|
81
|
+
'defaultMode: manifest.defaultMode',
|
|
73
82
|
'loadActiveZagentFromEnv(state, ctx.cwd)',
|
|
83
|
+
'state.zagent.defaultMode && state.zagent.defaultMode !== state.activeMode',
|
|
74
84
|
'ZAGENT RUNTIME ACTIVATION',
|
|
75
85
|
'ZAgents are full Pi sessions tied to ZPeer/live coordination, not delegate subagents.',
|
|
76
86
|
'team: zagent?.team ?? basePeer.team',
|
|
87
|
+
'teams: resolved.teamIds',
|
|
77
88
|
'roleId: zagent?.id ?? basePeer.roleId',
|
|
78
89
|
'agent: zagent?.id ?? basePeer.agent',
|
|
79
90
|
'team: zagent?.team ?? state.zobLive.peerCard.team',
|
|
@@ -84,14 +95,16 @@ requireIncludes('.pi/extensions/zob-harness/src/runtime/events.ts', [
|
|
|
84
95
|
requireIncludes('.pi/extensions/zob-harness/src/runtime/state.ts', [
|
|
85
96
|
'export interface ZagentRuntimeState',
|
|
86
97
|
'team?: string;',
|
|
98
|
+
'teams?: string[];',
|
|
87
99
|
'role?: string;',
|
|
88
100
|
'alias?: string;',
|
|
89
101
|
'rooms: ZAgentRoomBinding[];',
|
|
102
|
+
'defaultMode?: ModeName;',
|
|
90
103
|
'zagent: ZagentRuntimeState;',
|
|
91
104
|
'zagent: { rooms: [], errors: [] }',
|
|
92
105
|
], 'state');
|
|
93
106
|
|
|
94
|
-
requireIncludes('.pi/extensions/zob-harness/src/coms-v2/zpeer.ts', [
|
|
107
|
+
requireIncludes('.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts', [
|
|
95
108
|
'import { loadZteamManifest, zteamAllowsZpeerContact } from "../zagents.js"',
|
|
96
109
|
'const zteam = loadZteamManifest(repoRoot, self.team)',
|
|
97
110
|
'zteam fallback blocked',
|
|
@@ -138,8 +151,24 @@ requireIncludes('.pi/skills/zob-zagent-creator/SKILL.md', [
|
|
|
138
151
|
'/zteam launch-plan <team-id>',
|
|
139
152
|
'ZOB_ZAGENT_ID=<id> pi',
|
|
140
153
|
'do not automatically spawn processes',
|
|
154
|
+
'.pi/model-catalog.json',
|
|
155
|
+
'.pi/model-catalog.example.json',
|
|
156
|
+
'.pi/model-routing.json',
|
|
157
|
+
'costTier',
|
|
158
|
+
'qualityTier',
|
|
159
|
+
'ZOB_ZAGENT_ID=<id> pi --model <model>',
|
|
160
|
+
'Default ZOB mode selection',
|
|
161
|
+
'defaultMode',
|
|
162
|
+
'never choose `vanilla` by default',
|
|
141
163
|
'Do not add a scaffold slash command',
|
|
142
164
|
'J\'ai besoin d\'une team de trois agents',
|
|
165
|
+
'metadata.entryAgent',
|
|
166
|
+
'start [agent]',
|
|
167
|
+
'attach [agent]',
|
|
168
|
+
'window <agent>',
|
|
169
|
+
'list',
|
|
170
|
+
'resolve_target_agent',
|
|
171
|
+
'Unknown agent/window',
|
|
143
172
|
], 'zagent skill');
|
|
144
173
|
|
|
145
174
|
const scaffoldCommand = ['/zteam', 'scaffold'].join(' ');
|
|
@@ -96,12 +96,13 @@ async function main() {
|
|
|
96
96
|
if (existsSync(repoNodeModules)) symlinkSync(repoNodeModules, join(outDir, 'node_modules'), 'dir');
|
|
97
97
|
|
|
98
98
|
const compiledSrc = join(outDir, '.pi/extensions/zob-harness/src');
|
|
99
|
-
const
|
|
100
|
-
const
|
|
99
|
+
const compiledComsV2 = `${compiledSrc}/domains/coms/coms-v2`;
|
|
100
|
+
const zpeer = await import(`${compiledComsV2}/zpeer.js`);
|
|
101
|
+
const zpeerProfile = await import(`${compiledComsV2}/zpeer-profile.js`);
|
|
101
102
|
const toolsComs = await import(`${compiledSrc}/runtime/tools-coms.js`);
|
|
102
|
-
const localTransport = await import(`${
|
|
103
|
-
const envelope = await import(`${
|
|
104
|
-
const hashing = await import(`${compiledSrc}/utils/hashing.js`);
|
|
103
|
+
const localTransport = await import(`${compiledComsV2}/local-transport.js`);
|
|
104
|
+
const envelope = await import(`${compiledComsV2}/envelope.js`);
|
|
105
|
+
const hashing = await import(`${compiledSrc}/core/utils/hashing.js`);
|
|
105
106
|
|
|
106
107
|
process.env.ZOB_ZPEER_PROFILE_ID = 'profile-alpha';
|
|
107
108
|
delete process.env.ZPEER_PROFILE;
|