zob-harness 0.2.0 → 0.3.1
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 +47 -4
- 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 +35 -7
- package/.pi/extensions/zob-harness/src/{mission-control.ts → domains/coms/mission-control.ts} +12 -9
- 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 +51 -29
- 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 +53 -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 +27 -10
- 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 +148 -0
- package/.pi/skills/zob-coms-safety/SKILL.md +13 -0
- package/.pi/skills/zob-coms-v2-live/SKILL.md +11 -0
- package/.pi/skills/zob-factory/SKILL.md +21 -0
- package/.pi/skills/zob-harness/SKILL.md +14 -0
- package/.pi/skills/zob-split-refactor/SKILL.md +1 -1
- package/.pi/skills/zob-zagent-creator/SKILL.md +266 -12
- package/.pi/zagents/agent-factory-pacman-chief.json +22 -0
- package/.pi/zagents/agent-factory-pacman-engine-builder.json +21 -0
- package/.pi/zagents/agent-factory-pacman-frontend-builder.json +21 -0
- package/.pi/zagents/agent-factory-pacman-game-architect.json +21 -0
- package/.pi/zagents/agent-factory-pacman-game-designer.json +21 -0
- package/.pi/zagents/agent-factory-pacman-qa-oracle.json +21 -0
- 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/agent-factory-pacman-chief.md +53 -0
- package/.pi/zagents/prompts/agent-factory-pacman-engine-builder.md +41 -0
- package/.pi/zagents/prompts/agent-factory-pacman-frontend-builder.md +40 -0
- package/.pi/zagents/prompts/agent-factory-pacman-game-architect.md +41 -0
- package/.pi/zagents/prompts/agent-factory-pacman-game-designer.md +43 -0
- package/.pi/zagents/prompts/agent-factory-pacman-qa-oracle.md +51 -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/agent-factory-pacman-multiplayer-runtime.mjs +384 -0
- package/.pi/zteams/agent-factory-pacman-multiplayer.json +42 -0
- package/.pi/zteams/agent-factory-pacman-multiplayer.tmux.sh +256 -0
- package/.pi/zteams/agentic-spec-run.json +42 -0
- package/.pi/zteams/agentic-spec-run.tmux.sh +134 -0
- package/.pi/zteams/templates/agent-factory-pacman-chief-kickoff.template.md +71 -0
- package/.pi/zteams/templates/agent-factory-pacman-worker-kickoff.template.md +59 -0
- package/README.md +183 -110
- package/SOURCE_INDEX.md +5 -1
- package/examples/agent-factory-mission-control/AGENTS.md +10 -0
- package/examples/agent-factory-mission-control/README.md +17 -0
- package/examples/agent-factory-mission-control/apps/api/AGENTS.md +3 -0
- package/examples/agent-factory-mission-control/apps/dashboard/AGENTS.md +3 -0
- package/examples/agent-factory-mission-control/mission.md +3 -0
- package/examples/agent-factory-mission-control/output-contract.md +3 -0
- package/examples/agent-factory-mission-control/packages/domain/AGENTS.md +3 -0
- package/examples/agent-factory-mission-control/packages/snapshot-reader/AGENTS.md +3 -0
- package/examples/agent-factory-pacman-multiplayer/AGENTS.md +27 -0
- package/examples/agent-factory-pacman-multiplayer/README.md +84 -0
- package/examples/agent-factory-pacman-multiplayer/mission.md +43 -0
- package/examples/agent-factory-pacman-multiplayer/output-contract.md +58 -0
- package/examples/agent-factory-tmux-comms/README.md +146 -0
- package/examples/agent-factory-tmux-comms/chief-kickoff.template.md +54 -0
- package/examples/agent-factory-tmux-comms/simple-agent-factory.team.json +92 -0
- package/examples/agent-factory-tmux-comms/simple-agent-factory.tmux.sh +248 -0
- package/examples/agent-factory-tmux-comms/worker-kickoff.template.md +43 -0
- package/package.json +17 -3
- 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 +12 -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
|
@@ -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;
|
|
@@ -330,6 +331,12 @@ async function main() {
|
|
|
330
331
|
assert(useShared.ok === true && useShared.peer.zpeerRoomId === 'shared-room' && useShared.peer.zpeerAlias === 'sharedalpha', 'useZpeerRoom must switch active room and alias');
|
|
331
332
|
alpha = zpeer.useZpeerRoom(repoRoot, useShared.peer, 'room-one').peer;
|
|
332
333
|
|
|
334
|
+
zpeer.ensureZpeerFields(repoRoot, makePeer({ alias: 'beta', roomId: 'room-one', endpoint: join(root, 'dead-beta-ghost.sock'), endpointHash: hashing.sha256(join(root, 'dead-beta-ghost.sock')), sha256: hashing.sha256, heartbeatAt: oldHeartbeatAt }), 'room-one', 'beta');
|
|
335
|
+
const ghostDuplicateSummary = zpeer.buildZpeerRoomSummary(repoRoot, alpha);
|
|
336
|
+
assert(ghostDuplicateSummary.aliases.filter((alias) => alias === 'beta').length >= 2, 'ghost duplicate fixture must include stale/offline alias plus live alias');
|
|
337
|
+
assert(ghostDuplicateSummary.onlineAliases.filter((alias) => alias === 'beta').length === 1, 'only the live beta alias should be listed as online');
|
|
338
|
+
assert(!ghostDuplicateSummary.duplicateAliases.includes('beta'), 'offline alias ghosts must not be reported as live duplicate aliases');
|
|
339
|
+
|
|
333
340
|
const directPromptCountBefore = receivedPrompts.length;
|
|
334
341
|
const directResponseCountBefore = receivedResponses.length;
|
|
335
342
|
assert(alpha.team !== beta.team, 'same-room non-worker allowance fixture must cover cross-team peers');
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
|
|
4
4
|
const files = [
|
|
5
|
-
'.pi/extensions/zob-harness/src/coms-v2/zpeer.ts',
|
|
6
|
-
'.pi/extensions/zob-harness/src/coms-v2/registry.ts',
|
|
7
|
-
'.pi/extensions/zob-harness/src/coms-v2/zpeer-profile.ts',
|
|
8
|
-
'.pi/extensions/zob-harness/src/coms-v2/transcript-capture.ts',
|
|
5
|
+
'.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts',
|
|
6
|
+
'.pi/extensions/zob-harness/src/domains/coms/coms-v2/registry.ts',
|
|
7
|
+
'.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer-profile.ts',
|
|
8
|
+
'.pi/extensions/zob-harness/src/domains/coms/coms-v2/transcript-capture.ts',
|
|
9
9
|
'.pi/extensions/zob-harness/src/runtime/commands.ts',
|
|
10
10
|
'.pi/extensions/zob-harness/src/runtime/tools-coms.ts',
|
|
11
11
|
'.pi/extensions/zob-harness/src/runtime/events.ts',
|
|
12
12
|
'.pi/extensions/zob-harness/src/runtime/state.ts',
|
|
13
|
-
'.pi/extensions/zob-harness/src/goal-runtime.ts',
|
|
13
|
+
'.pi/extensions/zob-harness/src/runtime/goal-runtime.ts',
|
|
14
14
|
'.pi/extensions/zob-harness/src/runtime/widget.ts',
|
|
15
|
-
'.pi/extensions/zob-harness/src/mission-control.ts',
|
|
16
|
-
'.pi/extensions/zob-harness/src/schemas.ts',
|
|
17
|
-
'.pi/extensions/zob-harness/src/constants.ts',
|
|
15
|
+
'.pi/extensions/zob-harness/src/domains/coms/mission-control.ts',
|
|
16
|
+
'.pi/extensions/zob-harness/src/runtime/schemas.ts',
|
|
17
|
+
'.pi/extensions/zob-harness/src/core/constants.ts',
|
|
18
18
|
'.pi/capabilities/zob-public-runtime-capabilities.json',
|
|
19
19
|
];
|
|
20
20
|
const contents = Object.fromEntries(files.map((file) => [file, readFileSync(file, 'utf8')]));
|
|
@@ -30,13 +30,13 @@ for (const needle of ['parameters: ZpeerAskParams', 'sendZpeerPrompt(ctx.cwd', '
|
|
|
30
30
|
}
|
|
31
31
|
if (toolsComs.includes('emitZpeerAskEvent({ kind: "attempt", status: "agent-request"')) failures.push('zpeer_ask async must not emit pre-ACK attempt feed noise');
|
|
32
32
|
if (!toolsComs.includes('peerAliasInRoom(self, requestedRoomId)') || !toolsComs.includes('peerAliasInRoom(self, eventRoomId)')) failures.push('zpeer_ask feed events must use room-scoped sender alias for explicit roomId');
|
|
33
|
-
const schemas = contents['.pi/extensions/zob-harness/src/schemas.ts'];
|
|
33
|
+
const schemas = contents['.pi/extensions/zob-harness/src/runtime/schemas.ts'];
|
|
34
34
|
for (const needle of ['const ZpeerAskParams', 'targetAlias', 'message', 'roomId', 'Default async', '["async", "await", "long"]', 'timeoutMs', 'ZpeerAskParams']) {
|
|
35
35
|
if (!schemas.includes(needle)) failures.push(`zpeer_ask schema missing ${needle}`);
|
|
36
36
|
}
|
|
37
37
|
const registry = contents['.pi/capabilities/zob-public-runtime-capabilities.json'];
|
|
38
38
|
if (!registry.includes('"name": "zpeer_ask"') || !registry.includes('rate/loop guarded')) failures.push('capability registry missing zpeer_ask visibility/safety notes');
|
|
39
|
-
const constants = contents['.pi/extensions/zob-harness/src/constants.ts'];
|
|
39
|
+
const constants = contents['.pi/extensions/zob-harness/src/core/constants.ts'];
|
|
40
40
|
const zpeerComsAllowlistBlock = constants.match(/export const ZOB_COMS_TOOLS = \[[^\n]*\] as const;/)?.[0] ?? '';
|
|
41
41
|
if (!zpeerComsAllowlistBlock.includes('"zpeer_ask"')) failures.push('ZOB_COMS_TOOLS missing zpeer_ask active allowlist entry');
|
|
42
42
|
const modeBlocks = Object.fromEntries([...constants.matchAll(/\n (explore|plan|implement|oracle|orchestrator|factory): \[[^\n]*\],/g)].map((match) => [match[1], match[0]]));
|
|
@@ -51,9 +51,9 @@ for (const forbidden of ['transientPrompt:', 'transientResponse:', 'prompt:', 'o
|
|
|
51
51
|
if (appendBlocks.some((block) => block.includes(forbidden))) failures.push(`zpeer_ask appendEntry contains forbidden raw key/value ${forbidden}`);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const zpeer = contents['.pi/extensions/zob-harness/src/coms-v2/zpeer.ts'];
|
|
55
|
-
const liveRegistry = contents['.pi/extensions/zob-harness/src/coms-v2/registry.ts'];
|
|
56
|
-
const zpeerProfile = contents['.pi/extensions/zob-harness/src/coms-v2/zpeer-profile.ts'];
|
|
54
|
+
const zpeer = contents['.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts'];
|
|
55
|
+
const liveRegistry = contents['.pi/extensions/zob-harness/src/domains/coms/coms-v2/registry.ts'];
|
|
56
|
+
const zpeerProfile = contents['.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer-profile.ts'];
|
|
57
57
|
for (const needle of ['networkEnabled: false', 'localOnly: true', 'bodyStored: false', 'sendZobLocalEnvelope', 'taskHash', 'outputHash', 'ZpeerSendMode', 'status: "waiting"', 'status: "reply"', 'zpeerMembershipsForPeer', 'joinZpeerRoom', 'leaveZpeerRoom', 'useZpeerRoom', 'clearZpeerRoom', 'preservedSelf: true', 'roomId?: string', 'buildZpeerPeerRoomSummaries', 'active: membership.roomId === activeRoomId', 'peerRespondsToAliasPing', 'activeAliasCollision', 'zpeer-alias-ping']) {
|
|
58
58
|
if (!zpeer.includes(needle)) failures.push(`zpeer missing ${needle}`);
|
|
59
59
|
}
|
|
@@ -139,7 +139,7 @@ for (const needle of ['readZpeerNewCarryoverProfile(repoRoot)', 'const carryover
|
|
|
139
139
|
}
|
|
140
140
|
if (!events.includes('event.source === "extension" && !event.text.trim()') || !events.includes('action: "handled" as const')) failures.push('runtime must handle empty extension follow-ups without continuing the agent');
|
|
141
141
|
if (!events.includes('ZPeer async reply received from @') || !events.includes('{ triggerTurn: true, deliverAs: "followUp" }')) failures.push('runtime must resume an idle agent with a follow-up when an async ZPeer reply arrives');
|
|
142
|
-
for (const needle of ['ZPEER AWARENESS (transient, rebuilt each turn)', 'zpeer_ask with mode=\\"async\\"', 'Passive wait rule', 'stop the turn and remain idle', 'avoid spam', 'Raw ZPeer bodies are transient', 'registerMessageRenderer("zob-zpeer-event"', 'scheduleZpeerHeartbeat', 'clearZpeerHeartbeatTimer', 'refreshZpeerSelf(repoRoot', 'kind: "response_sent"', 'kind: "inbound"']) {
|
|
142
|
+
for (const needle of ['ZPEER AWARENESS (transient, rebuilt each turn)', 'buildZpeerPeerRoomSummaries(repoRoot, state.zobLive.peerCard)', '- rooms:', 'explicit roomId', 'zpeer_ask with mode=\\"async\\"', 'Passive wait rule', 'stop the turn and remain idle', 'avoid spam', 'Raw ZPeer bodies are transient', 'registerMessageRenderer("zob-zpeer-event"', 'scheduleZpeerHeartbeat', 'clearZpeerHeartbeatTimer', 'refreshZpeerSelf(repoRoot', 'kind: "response_sent"', 'kind: "inbound"']) {
|
|
143
143
|
if (!events.includes(needle)) failures.push(`runtime missing zpeer awareness/event support ${needle}`);
|
|
144
144
|
}
|
|
145
145
|
const responseSentBlock = events.match(/setZpeerLastEvent\(state, \{\s*kind: "response_sent"[\s\S]*?customType: "zob-zpeer-event"[\s\S]*?triggerTurn: false[\s\S]*?\}\);/)?.[0] ?? '';
|
|
@@ -150,7 +150,7 @@ for (const needle of ['roomId:', 'fromAlias:', 'toAlias:', 'status: "response_se
|
|
|
150
150
|
for (const forbidden of ['transientPrompt:', 'transientResponse:', 'prompt:', 'response:', 'body:', 'content: responseText', 'message:', 'text:', 'rationale:', 'diff:', 'patch:']) {
|
|
151
151
|
if (responseSentBlock.includes(forbidden)) failures.push(`response_sent feed card contains forbidden raw/body-like field ${forbidden}`);
|
|
152
152
|
}
|
|
153
|
-
const transcriptCapture = contents['.pi/extensions/zob-harness/src/coms-v2/transcript-capture.ts'];
|
|
153
|
+
const transcriptCapture = contents['.pi/extensions/zob-harness/src/domains/coms/coms-v2/transcript-capture.ts'];
|
|
154
154
|
const artifactBlock = transcriptCapture.match(/const artifact = \{[\s\S]*?\n \};/)?.[0] ?? '';
|
|
155
155
|
if (!artifactBlock) failures.push('redacted capture artifact shape not found');
|
|
156
156
|
for (const needle of ['rawBodiesStored: false', 'redactedBodiesStored: true', 'comsLedgerBodyStored: false', 'bodyStored: false', 'taskHash: input.taskHash', 'outputHash: input.outputHash']) {
|
|
@@ -175,7 +175,7 @@ if (!stateTs?.includes('ZobLiveLastEvent')) failures.push('runtime state missing
|
|
|
175
175
|
for (const needle of ['ZobPassivePeerWaitState', 'passivePeerWait?: ZobPassivePeerWaitState', 'schema: "zob.passive-peer-wait.v1"', 'suppressGoalContinuation: true', 'bodyStored: false', 'localOnly: true', 'networkEnabled: false']) {
|
|
176
176
|
if (!stateTs.includes(needle)) failures.push(`runtime state missing passive peer wait field ${needle}`);
|
|
177
177
|
}
|
|
178
|
-
const goalRuntime = contents['.pi/extensions/zob-harness/src/goal-runtime.ts'];
|
|
178
|
+
const goalRuntime = contents['.pi/extensions/zob-harness/src/runtime/goal-runtime.ts'];
|
|
179
179
|
for (const needle of ['state.zobLive.passivePeerWait?.suppressGoalContinuation === true', 'clearRuntimeGoalContinuationTimer(state)', 'return;']) {
|
|
180
180
|
if (!goalRuntime.includes(needle)) failures.push(`goal runtime missing passive peer continuation suppression ${needle}`);
|
|
181
181
|
}
|
|
@@ -189,7 +189,7 @@ for (const forbidden of ['transientPrompt:', 'transientResponse:', 'message:', '
|
|
|
189
189
|
for (const needle of ['clearPassivePeerWaitForResponse', 'envelope.type !== "response"', 'envelope.msgId === wait.msgId', 'state.zobLive.passivePeerWait = undefined', 'envelope.sender === wait.targetAlias']) {
|
|
190
190
|
if (!events.includes(needle)) failures.push(`runtime events missing passive wait response clear ${needle}`);
|
|
191
191
|
}
|
|
192
|
-
if (!contents['.pi/extensions/zob-harness/src/mission-control.ts'].includes('zpeerRooms')) failures.push('Mission Control missing zpeerRooms summary');
|
|
192
|
+
if (!contents['.pi/extensions/zob-harness/src/domains/coms/mission-control.ts'].includes('zpeerRooms')) failures.push('Mission Control missing zpeerRooms summary');
|
|
193
193
|
|
|
194
194
|
if (failures.length > 0) {
|
|
195
195
|
console.error(`zpeer static smoke FAIL\n- ${failures.join('\n- ')}`);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|