ultimate-pi 0.6.1 → 0.8.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/.agents/skills/harness-decisions/SKILL.md +20 -1
- package/.agents/skills/harness-eval/SKILL.md +11 -13
- package/.agents/skills/harness-orchestration/SKILL.md +36 -30
- package/.agents/skills/harness-plan/SKILL.md +13 -14
- package/.agents/skills/harness-sentrux-setup/SKILL.md +3 -4
- package/.pi/PACKAGING.md +1 -1
- package/.pi/agents/harness/adversary.md +20 -12
- package/.pi/agents/harness/evaluator.md +25 -14
- package/.pi/agents/harness/executor.md +27 -16
- package/.pi/agents/harness/incident-recorder.md +37 -0
- package/.pi/agents/harness/meta-optimizer.md +18 -15
- package/.pi/agents/harness/planner.md +27 -30
- package/.pi/agents/harness/tie-breaker.md +4 -2
- package/.pi/agents/harness/trace-librarian.md +18 -11
- package/.pi/agents/pi-pi/ext-expert.md +1 -1
- package/.pi/agents/pi-pi/keybinding-expert.md +1 -1
- package/.pi/agents/pi-pi/tui-expert.md +3 -3
- package/.pi/extensions/00-ultimate-pi-system-prompt.ts +194 -0
- package/.pi/extensions/budget-guard.ts +11 -3
- package/.pi/extensions/custom-footer.ts +8 -3
- package/.pi/extensions/custom-header.ts +2 -2
- package/.pi/extensions/debate-orchestrator.ts +11 -3
- package/.pi/extensions/dotenv-loader.ts +1 -1
- package/.pi/extensions/drift-monitor.ts +1 -1
- package/.pi/extensions/harness-ask-user.ts +1 -1
- package/.pi/extensions/harness-live-widget.ts +11 -4
- package/.pi/extensions/harness-run-context.ts +745 -0
- package/.pi/extensions/harness-telemetry.ts +1 -1
- package/.pi/extensions/harness-web-guard.ts +1 -1
- package/.pi/extensions/harness-web-tools.ts +1 -1
- package/.pi/extensions/lib/ask-user/dialog.ts +2 -2
- package/.pi/extensions/lib/ask-user/fallback.ts +1 -1
- package/.pi/extensions/lib/ask-user/render.ts +3 -3
- package/.pi/extensions/lib/harness-subagents/agent-loader.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/agent-parser.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/blackboard-tool.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/harness-subagent-policy.ts +134 -0
- package/.pi/extensions/lib/harness-subagents/vendored/agent-manager.ts +2 -2
- package/.pi/extensions/lib/harness-subagents/vendored/agent-runner.ts +9 -5
- package/.pi/extensions/lib/harness-subagents/vendored/context.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/vendored/env.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/vendored/index.ts +2 -2
- package/.pi/extensions/lib/harness-subagents/vendored/output-file.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/vendored/schedule.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/vendored/settings.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/vendored/skill-loader.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/vendored/types.ts +2 -2
- package/.pi/extensions/lib/harness-subagents/vendored/ui/agent-widget.ts +1 -1
- package/.pi/extensions/lib/harness-subagents/vendored/ui/conversation-viewer.ts +2 -2
- package/.pi/extensions/lib/harness-subagents/vendored/ui/schedule-menu.ts +1 -1
- package/.pi/extensions/observation-bus.ts +8 -10
- package/.pi/extensions/pi-model-router-harness.ts +1 -1
- package/.pi/extensions/policy-gate.ts +136 -84
- package/.pi/extensions/provider-payload-sanitize.ts +1 -1
- package/.pi/extensions/review-integrity.ts +76 -22
- package/.pi/extensions/sentrux-rules-sync.ts +1 -1
- package/.pi/extensions/soundboard.ts +1 -1
- package/.pi/extensions/test-diff-integrity.ts +1 -1
- package/.pi/extensions/trace-recorder.ts +81 -21
- package/.pi/extensions/ultimate-pi-vcc.ts +1 -1
- package/.pi/harness/README.md +2 -0
- package/.pi/harness/agents.manifest.json +17 -13
- package/.pi/harness/docs/adrs/0009-sentrux-rules-lifecycle.md +1 -1
- package/.pi/harness/docs/adrs/0031-harness-run-context.md +41 -0
- package/.pi/harness/docs/adrs/0032-harness-command-orchestration.md +37 -0
- package/.pi/harness/docs/adrs/README.md +2 -0
- package/.pi/harness/evals/smoke/run-context.fixture.json +17 -0
- package/.pi/harness/specs/harness-run-context.schema.json +80 -0
- package/.pi/harness/specs/harness-spawn-context.schema.json +65 -0
- package/.pi/lib/harness-agent-output.ts +41 -0
- package/.pi/lib/harness-run-context.ts +1139 -0
- package/.pi/lib/harness-ui-state.ts +12 -1
- package/.pi/prompts/harness-abort.md +9 -6
- package/.pi/prompts/harness-auto.md +36 -61
- package/.pi/prompts/harness-critic.md +17 -32
- package/.pi/prompts/harness-eval.md +22 -30
- package/.pi/prompts/harness-incident.md +17 -34
- package/.pi/prompts/harness-plan.md +32 -36
- package/.pi/prompts/harness-review.md +18 -33
- package/.pi/prompts/harness-router-tune.md +16 -38
- package/.pi/prompts/harness-run.md +23 -40
- package/.pi/prompts/harness-setup.md +7 -27
- package/.pi/prompts/harness-trace.md +15 -34
- package/.pi/scripts/harness-generate-model-router.mjs +16 -13
- package/.pi/scripts/harness-verify.mjs +34 -0
- package/.pi/scripts/vendor-sync-pi-model-router.sh +10 -10
- package/CHANGELOG.md +34 -1
- package/README.md +31 -15
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/package.json +14 -9
- package/vendor/pi-model-router/UPSTREAM_PIN.md +1 -1
- package/vendor/pi-model-router/extensions/commands.ts +2 -2
- package/vendor/pi-model-router/extensions/config.ts +2 -2
- package/vendor/pi-model-router/extensions/index.ts +1 -1
- package/vendor/pi-model-router/extensions/provider.ts +2 -2
- package/vendor/pi-model-router/extensions/routing.ts +2 -2
- package/vendor/pi-model-router/extensions/types.ts +1 -1
- package/vendor/pi-model-router/extensions/ui.ts +1 -1
- package/vendor/pi-model-router/package.json +4 -4
- package/vendor/pi-vcc/index.ts +1 -1
- package/vendor/pi-vcc/package.json +1 -1
- package/vendor/pi-vcc/src/commands/pi-vcc.ts +1 -1
- package/vendor/pi-vcc/src/commands/vcc-recall.ts +1 -1
- package/vendor/pi-vcc/src/core/content.ts +1 -1
- package/vendor/pi-vcc/src/core/load-messages.ts +1 -1
- package/vendor/pi-vcc/src/core/normalize.ts +1 -1
- package/vendor/pi-vcc/src/core/render-entries.ts +1 -1
- package/vendor/pi-vcc/src/core/report.ts +1 -1
- package/vendor/pi-vcc/src/core/search-entries.ts +1 -1
- package/vendor/pi-vcc/src/core/summarize.ts +1 -1
- package/vendor/pi-vcc/src/hooks/before-compact.ts +2 -2
- package/vendor/pi-vcc/src/tools/recall.ts +1 -1
- package/vendor/pi-vcc/src/types.ts +1 -1
- package/vendor/pi-vcc/tests/fixtures.ts +1 -1
- package/vendor/pi-vcc/tests/render-entries.test.ts +1 -1
- package/vendor/pi-vcc/tests/search-entries.test.ts +1 -1
- package/vendor/pi-vcc/tests/support/load-session.ts +2 -2
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - `HARNESS_VCC_DEBUG` — set `true` to write `/tmp/pi-vcc-debug.json` on compaction
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type { ExtensionAPI } from "@
|
|
12
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
13
13
|
import registerVcc from "../../vendor/pi-vcc/index.js";
|
|
14
14
|
|
|
15
15
|
export default function ultimatePiVcc(pi: ExtensionAPI): void {
|
package/.pi/harness/README.md
CHANGED
|
@@ -29,6 +29,8 @@ Governance/runtime enforcement for this harness is implemented as Pi extensions
|
|
|
29
29
|
under `.pi/extensions/` and auto-loaded through the package `pi.extensions`
|
|
30
30
|
manifest (`package.json`).
|
|
31
31
|
|
|
32
|
+
- `harness-run-context.ts` - active run + plan injection; short commands without run/plan args
|
|
33
|
+
- `harness-live-widget.ts` - footer status (phase, plan ready, next command; no run id in UI)
|
|
32
34
|
- `policy-gate.ts` - phase state machine + plan-before-mutate enforcement
|
|
33
35
|
- `budget-guard.ts` - hard-stop token budget checks + budget exhausted artifacts
|
|
34
36
|
- `trace-recorder.ts` - append-only run traces + HarnessRunRecord + compact index
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.0.0",
|
|
3
3
|
"package": "ultimate-pi",
|
|
4
|
-
"package_version": "0.
|
|
5
|
-
"generated_at": "2026-05-
|
|
4
|
+
"package_version": "0.7.0",
|
|
5
|
+
"generated_at": "2026-05-17T08:24:57.263Z",
|
|
6
6
|
"agents": {
|
|
7
7
|
"pi-pi/agent-expert": {
|
|
8
8
|
"path": ".pi/agents/pi-pi/agent-expert.md",
|
|
9
|
-
"sha256": "
|
|
9
|
+
"sha256": "86561eb092b92fa43f221bfc6305de8d5afe10d43c5f577b9bf15a71bda051c6"
|
|
10
10
|
},
|
|
11
11
|
"pi-pi/cli-expert": {
|
|
12
12
|
"path": ".pi/agents/pi-pi/cli-expert.md",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
},
|
|
19
19
|
"pi-pi/ext-expert": {
|
|
20
20
|
"path": ".pi/agents/pi-pi/ext-expert.md",
|
|
21
|
-
"sha256": "
|
|
21
|
+
"sha256": "47c64a9e2cffe00a50cac5541b0edc89fe8bcbd66ec3bb302eecc10d405a977f"
|
|
22
22
|
},
|
|
23
23
|
"pi-pi/keybinding-expert": {
|
|
24
24
|
"path": ".pi/agents/pi-pi/keybinding-expert.md",
|
|
25
|
-
"sha256": "
|
|
25
|
+
"sha256": "bb83f5fd2178075c8374ef28c360339f7de9faeedf811670b43a536c5f65c58e"
|
|
26
26
|
},
|
|
27
27
|
"pi-pi/pi-orchestrator": {
|
|
28
28
|
"path": ".pi/agents/pi-pi/pi-orchestrator.md",
|
|
@@ -42,27 +42,31 @@
|
|
|
42
42
|
},
|
|
43
43
|
"pi-pi/tui-expert": {
|
|
44
44
|
"path": ".pi/agents/pi-pi/tui-expert.md",
|
|
45
|
-
"sha256": "
|
|
45
|
+
"sha256": "a619b2ee3d3d94fe599abb61db0904f90d30335ec426851c3f1efdf2e5ce5390"
|
|
46
46
|
},
|
|
47
47
|
"harness/adversary": {
|
|
48
48
|
"path": ".pi/agents/harness/adversary.md",
|
|
49
|
-
"sha256": "
|
|
49
|
+
"sha256": "b965f90610ca942d08b656f1aee839266d08a92beb174b8761dd5e840694a899"
|
|
50
50
|
},
|
|
51
51
|
"harness/evaluator": {
|
|
52
52
|
"path": ".pi/agents/harness/evaluator.md",
|
|
53
|
-
"sha256": "
|
|
53
|
+
"sha256": "6c0de777a10de26dba4a6feb5641495fa5c2d31072a8b0e597a5ecc9921f129f"
|
|
54
54
|
},
|
|
55
55
|
"harness/executor": {
|
|
56
56
|
"path": ".pi/agents/harness/executor.md",
|
|
57
|
-
"sha256": "
|
|
57
|
+
"sha256": "5af3ec2be4d64a738834e36d480a36c2bee4359e8cd5a2e1aac49be4cff79589"
|
|
58
|
+
},
|
|
59
|
+
"harness/incident-recorder": {
|
|
60
|
+
"path": ".pi/agents/harness/incident-recorder.md",
|
|
61
|
+
"sha256": "2de405f77b62dde38f331665bff220a3ef131c3c1cd42eebee364000fc83352b"
|
|
58
62
|
},
|
|
59
63
|
"harness/meta-optimizer": {
|
|
60
64
|
"path": ".pi/agents/harness/meta-optimizer.md",
|
|
61
|
-
"sha256": "
|
|
65
|
+
"sha256": "ef2fb950e18e3a6439e91a68f764fc7ec922cd2d6b35de8f656f376854974d04"
|
|
62
66
|
},
|
|
63
67
|
"harness/planner": {
|
|
64
68
|
"path": ".pi/agents/harness/planner.md",
|
|
65
|
-
"sha256": "
|
|
69
|
+
"sha256": "3052e0b4ca504c7aa025b1926228e34adfe7f1c42d66a24db43fc6a1abb9968d"
|
|
66
70
|
},
|
|
67
71
|
"harness/sentrux-bootstrap": {
|
|
68
72
|
"path": ".pi/agents/harness/sentrux-bootstrap.md",
|
|
@@ -70,11 +74,11 @@
|
|
|
70
74
|
},
|
|
71
75
|
"harness/tie-breaker": {
|
|
72
76
|
"path": ".pi/agents/harness/tie-breaker.md",
|
|
73
|
-
"sha256": "
|
|
77
|
+
"sha256": "651f50b9e2c7903c542700e94908b1fcd026ebed12aa1f1d6ec481df3567e34f"
|
|
74
78
|
},
|
|
75
79
|
"harness/trace-librarian": {
|
|
76
80
|
"path": ".pi/agents/harness/trace-librarian.md",
|
|
77
|
-
"sha256": "
|
|
81
|
+
"sha256": "d63fe08a2ea0466c0fd89fff4da03ac1d9d3580c306381cee251c89d4e8fdb97"
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
84
|
}
|
|
@@ -15,7 +15,7 @@ Sentrux enforces architecture via [`.sentrux/rules.toml`](https://sentrux.dev/do
|
|
|
15
15
|
4. **Re-sync command:** `node "$UP_PKG/.pi/scripts/sentrux-rules-sync.mjs" --force` or `harness-sentrux-bootstrap.mjs --force` (resolve `$UP_PKG` via [.pi/scripts/README.md](../../../scripts/README.md)).
|
|
16
16
|
5. **Pi command:** `/harness-sentrux-sync` via `sentrux-rules-sync.ts` extension.
|
|
17
17
|
6. **When to sync:**
|
|
18
|
-
- `/harness-setup` Step 4.
|
|
18
|
+
- `/harness-setup` Step 4.2 (after sentrux CLI install in Step 2.8)
|
|
19
19
|
- After editing `architecture.manifest.json`
|
|
20
20
|
- On `agent_end` when harness phase is `plan` or `merge`
|
|
21
21
|
- `node "$UP_PKG/.pi/scripts/harness-verify.mjs"` fails if manifest hash ≠ last sync (`--check`)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# ADR 0031: Harness active run context
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted
|
|
4
|
+
- **Date:** 2026-05-17
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Manual harness steps required copying `run_id` and `plan-packet.json` paths between commands. `trace-recorder` minted a new `run_id` on every `agent_start`, splitting artifacts across phases. The live widget exposed raw trace ids.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
|
|
12
|
+
1. Add `.pi/lib/harness-run-context.ts` and `harness-run-context.ts` extension as the single source of truth for active runs.
|
|
13
|
+
2. Persist mirrors:
|
|
14
|
+
- `.pi/harness/runs/<run_id>/run-context.json`
|
|
15
|
+
- `.pi/harness/active-run.json` (cross-session pointer for forked eval)
|
|
16
|
+
3. Canonical plan path: `.pi/harness/runs/<run_id>/plan-packet.json` — injected via `[HarnessActivePlan]`; no `--plan` on the happy path.
|
|
17
|
+
4. **Hook order:** `harness-run-context` `before_agent_start` allocates/reuses `run_id` before `trace-recorder` `agent_start`. Trace writes phase files `trace-<phase>.json` plus rollup `trace.json`.
|
|
18
|
+
5. PostHog `harness_run_started` at most once per logical `run_id`.
|
|
19
|
+
6. Short commands: `/harness-run`, `/harness-eval`, etc. without args; recovery via `/harness-run-status`, `/harness-use-run`.
|
|
20
|
+
7. After execute, handoff recommends **`/harness-eval`** in the same session; review commands spawn isolated subagents (see ADR 0032). `active-run.json` still supports cross-session recovery when Pi was closed mid-run.
|
|
21
|
+
8. `hasApprovedPlanSignal` uses user-visible prompt only; execute requires `plan_ready` from disk validation **and** recorded `ask_user` approval (or `harness-plan-approval` entry).
|
|
22
|
+
9. **Plan-phase writes:** policy-gate allows `write`/`edit` only on canonical `.pi/harness/runs/<run_id>/plan-packet.json` after approval; all other paths stay blocked until execute phase.
|
|
23
|
+
10. **Approval-before-persist:** agents present the full plan, call `ask_user` (Approve / Request changes / Cancel), then write the packet. `--quick` narrows planning only — it does not skip approval.
|
|
24
|
+
11. **`/harness-auto`:** after an approved plan-packet write, policy phase promotes to `execute` in the same agent turn so implementation can proceed without a separate `/harness-run` message.
|
|
25
|
+
|
|
26
|
+
## Consequences
|
|
27
|
+
|
|
28
|
+
### Positive
|
|
29
|
+
|
|
30
|
+
- One logical run per manual/auto pipeline; forensics and telemetry align.
|
|
31
|
+
- Users never copy run ids or plan paths in normal workflows.
|
|
32
|
+
|
|
33
|
+
### Negative
|
|
34
|
+
|
|
35
|
+
- Extension ordering and disk reconciliation must stay correct when adding new harness commands.
|
|
36
|
+
|
|
37
|
+
## References
|
|
38
|
+
|
|
39
|
+
- `.pi/lib/harness-run-context.ts`
|
|
40
|
+
- `.pi/extensions/harness-run-context.ts`
|
|
41
|
+
- `.pi/harness/specs/harness-run-context.schema.json`
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# ADR 0032: Harness slash commands as agent orchestrators
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted
|
|
4
|
+
- **Date:** 2026-05-17
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Harness slash prompts duplicated logic already defined in `harness/*` agents. Commands did not invoke the `Agent` tool. Review docs told users to fork a new Pi session even though subagents already provide isolated context.
|
|
9
|
+
|
|
10
|
+
## Decision
|
|
11
|
+
|
|
12
|
+
1. **Slash commands** parse args, spawn the matching `harness/*` agent, run all `ask_user` gates, perform policy-gated writes, and emit handoff blocks.
|
|
13
|
+
2. **Agents** perform multi-turn reads and emit structured JSON drafts; they do not approve plans or write canonical run artifacts (except executor mutations in scope).
|
|
14
|
+
3. **HarnessSpawnContext** JSON (`.pi/harness/specs/harness-spawn-context.schema.json`) is required in every spawn prompt because subagents do not receive `[HarnessActivePlan]` injection.
|
|
15
|
+
4. **Review isolation** uses `Agent` spawn with `inherit_context: false`, not session fork. `review-integrity` allows `Agent` / `get_subagent_result` for `harness/evaluator`, `harness/adversary`, and `harness/tie-breaker`.
|
|
16
|
+
5. **Subagent policy** (`harness-subagent-policy.ts`) blocks mutating tools for planner/evaluator/adversary and related read-only agents; executor keeps write tools and `extensions: true`.
|
|
17
|
+
6. **Planner** has `disallowed_tools: ask_user`; clarification options return in JSON for the parent orchestrator.
|
|
18
|
+
|
|
19
|
+
## Consequences
|
|
20
|
+
|
|
21
|
+
### Positive
|
|
22
|
+
|
|
23
|
+
- Single source of truth for phase logic in agent files; prompts stay thin.
|
|
24
|
+
- L4 review isolation without manual session management.
|
|
25
|
+
|
|
26
|
+
### Negative
|
|
27
|
+
|
|
28
|
+
- Orchestrator must parse subagent JSON reliably and pass complete spawn context.
|
|
29
|
+
- Scope enforcement remains prompt-driven for executor until optional path allowlist.
|
|
30
|
+
|
|
31
|
+
## References
|
|
32
|
+
|
|
33
|
+
- `.pi/prompts/harness-*.md`
|
|
34
|
+
- `.pi/agents/harness/*.md`
|
|
35
|
+
- `.pi/extensions/lib/harness-subagents/harness-subagent-policy.ts`
|
|
36
|
+
- `.pi/extensions/review-integrity.ts`
|
|
37
|
+
- `.pi/lib/harness-agent-output.ts`
|
|
@@ -16,6 +16,8 @@ Team-shared ADRs for the ultimate-pi harness live under `.pi/harness/docs/adrs/`
|
|
|
16
16
|
| [0008](0008-harness-posthog-telemetry.md) | Harness PostHog telemetry | Accepted |
|
|
17
17
|
| [0009](0009-sentrux-rules-lifecycle.md) | Sentrux rules.toml lifecycle | Accepted |
|
|
18
18
|
| [0030](0030-inhouse-vcc-compaction.md) | In-house VCC compaction (vendored pi-vcc) | Accepted |
|
|
19
|
+
| [0031](0031-harness-run-context.md) | Harness active run context | Accepted |
|
|
20
|
+
| [0032](0032-harness-command-orchestration.md) | Harness commands as agent orchestrators | Accepted |
|
|
19
21
|
|
|
20
22
|
## Template
|
|
21
23
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1.0.0",
|
|
3
|
+
"run_id": "smoke-session-1",
|
|
4
|
+
"pi_session_id": "smoke-session",
|
|
5
|
+
"project_root": "/tmp/ultimate-pi-smoke",
|
|
6
|
+
"phase": "plan",
|
|
7
|
+
"plan_id": null,
|
|
8
|
+
"plan_packet_path": "/tmp/ultimate-pi-smoke/.pi/harness/runs/smoke-session-1/plan-packet.json",
|
|
9
|
+
"plan_ready": false,
|
|
10
|
+
"task_summary": "smoke task",
|
|
11
|
+
"status": "active",
|
|
12
|
+
"last_completed_step": null,
|
|
13
|
+
"last_outcome": null,
|
|
14
|
+
"next_recommended_command": "/harness-plan \"smoke task\"",
|
|
15
|
+
"owner_pi_session_id": "smoke-session",
|
|
16
|
+
"updated_at": "2026-05-17T00:00:00.000Z"
|
|
17
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ultimate-pi.local/.pi/harness/specs/harness-run-context.schema.json",
|
|
4
|
+
"title": "HarnessRunContext",
|
|
5
|
+
"description": "Session- and disk-backed active harness run pointer.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schema_version",
|
|
10
|
+
"run_id",
|
|
11
|
+
"pi_session_id",
|
|
12
|
+
"project_root",
|
|
13
|
+
"phase",
|
|
14
|
+
"plan_ready",
|
|
15
|
+
"status",
|
|
16
|
+
"owner_pi_session_id",
|
|
17
|
+
"updated_at"
|
|
18
|
+
],
|
|
19
|
+
"properties": {
|
|
20
|
+
"schema_version": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"const": "1.0.0"
|
|
23
|
+
},
|
|
24
|
+
"run_id": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"minLength": 1
|
|
27
|
+
},
|
|
28
|
+
"pi_session_id": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"minLength": 1
|
|
31
|
+
},
|
|
32
|
+
"project_root": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"minLength": 1
|
|
35
|
+
},
|
|
36
|
+
"phase": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"enum": ["plan", "execute", "evaluate", "adversary", "merge"]
|
|
39
|
+
},
|
|
40
|
+
"plan_id": {
|
|
41
|
+
"type": ["string", "null"]
|
|
42
|
+
},
|
|
43
|
+
"plan_packet_path": {
|
|
44
|
+
"type": ["string", "null"]
|
|
45
|
+
},
|
|
46
|
+
"plan_ready": {
|
|
47
|
+
"type": "boolean"
|
|
48
|
+
},
|
|
49
|
+
"task_summary": {
|
|
50
|
+
"type": ["string", "null"]
|
|
51
|
+
},
|
|
52
|
+
"status": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"enum": ["active", "aborted", "completed"]
|
|
55
|
+
},
|
|
56
|
+
"last_completed_step": {
|
|
57
|
+
"type": ["string", "null"]
|
|
58
|
+
},
|
|
59
|
+
"last_outcome": {
|
|
60
|
+
"type": ["string", "null"]
|
|
61
|
+
},
|
|
62
|
+
"next_recommended_command": {
|
|
63
|
+
"type": ["string", "null"]
|
|
64
|
+
},
|
|
65
|
+
"owner_pi_session_id": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"minLength": 1
|
|
68
|
+
},
|
|
69
|
+
"updated_at": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"format": "date-time"
|
|
72
|
+
},
|
|
73
|
+
"harness_run_started_emitted": {
|
|
74
|
+
"type": "boolean"
|
|
75
|
+
},
|
|
76
|
+
"turn_override_run_id": {
|
|
77
|
+
"type": ["string", "null"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ultimate-pi.local/.pi/harness/specs/harness-spawn-context.schema.json",
|
|
4
|
+
"title": "HarnessSpawnContext",
|
|
5
|
+
"description": "Structured context passed from harness slash-command orchestrators to harness/* subagents.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schema_version", "agent", "mode"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema_version": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"const": "1.0.0"
|
|
13
|
+
},
|
|
14
|
+
"agent": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"minLength": 1,
|
|
17
|
+
"description": "Target subagent id, e.g. harness/planner"
|
|
18
|
+
},
|
|
19
|
+
"mode": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": [
|
|
22
|
+
"create",
|
|
23
|
+
"revise",
|
|
24
|
+
"execute",
|
|
25
|
+
"benchmark",
|
|
26
|
+
"verdict",
|
|
27
|
+
"adversary",
|
|
28
|
+
"trace",
|
|
29
|
+
"incident",
|
|
30
|
+
"tune"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"run_id": {
|
|
34
|
+
"type": "string"
|
|
35
|
+
},
|
|
36
|
+
"plan_packet_path": {
|
|
37
|
+
"type": "string"
|
|
38
|
+
},
|
|
39
|
+
"run_dir": {
|
|
40
|
+
"type": "string"
|
|
41
|
+
},
|
|
42
|
+
"task_summary": {
|
|
43
|
+
"type": "string"
|
|
44
|
+
},
|
|
45
|
+
"risk_level": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"enum": ["low", "med", "high"]
|
|
48
|
+
},
|
|
49
|
+
"quick": {
|
|
50
|
+
"type": "boolean"
|
|
51
|
+
},
|
|
52
|
+
"acceptance_checks": {
|
|
53
|
+
"type": "array",
|
|
54
|
+
"items": { "type": "string" }
|
|
55
|
+
},
|
|
56
|
+
"artifact_paths": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"additionalProperties": { "type": "string" }
|
|
59
|
+
},
|
|
60
|
+
"handoff_summary": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "Prior phase bullet summary for chained spawns (harness-auto)"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse structured JSON blocks from harness subagent assistant output.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const JSON_FENCE_RE = /```(?:json)?\s*([\s\S]*?)```/i;
|
|
6
|
+
|
|
7
|
+
export function extractJsonBlock(text: string): string | null {
|
|
8
|
+
const trimmed = text.trim();
|
|
9
|
+
if (trimmed.startsWith("{")) {
|
|
10
|
+
return trimmed;
|
|
11
|
+
}
|
|
12
|
+
const match = JSON_FENCE_RE.exec(text);
|
|
13
|
+
if (match?.[1]) {
|
|
14
|
+
return match[1].trim();
|
|
15
|
+
}
|
|
16
|
+
const lastBrace = trimmed.lastIndexOf("{");
|
|
17
|
+
const lastClose = trimmed.lastIndexOf("}");
|
|
18
|
+
if (lastBrace >= 0 && lastClose > lastBrace) {
|
|
19
|
+
return trimmed.slice(lastBrace, lastClose + 1);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function parseHarnessAgentJson<T extends Record<string, unknown>>(
|
|
25
|
+
text: string,
|
|
26
|
+
): { ok: true; value: T } | { ok: false; error: string } {
|
|
27
|
+
const block = extractJsonBlock(text);
|
|
28
|
+
if (!block) {
|
|
29
|
+
return { ok: false, error: "no JSON block found in subagent output" };
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const value = JSON.parse(block) as T;
|
|
33
|
+
if (!value || typeof value !== "object") {
|
|
34
|
+
return { ok: false, error: "parsed value is not an object" };
|
|
35
|
+
}
|
|
36
|
+
return { ok: true, value };
|
|
37
|
+
} catch (err) {
|
|
38
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39
|
+
return { ok: false, error: message };
|
|
40
|
+
}
|
|
41
|
+
}
|