ultimate-pi 0.18.1 → 0.19.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.
Files changed (284) hide show
  1. package/.agents/skills/harness-debate-plan/SKILL.md +1 -1
  2. package/.agents/skills/harness-decisions/SKILL.md +1 -2
  3. package/.agents/skills/harness-governor/SKILL.md +6 -5
  4. package/.pi/PACKAGING.md +4 -4
  5. package/.pi/SYSTEM.md +54 -120
  6. package/.pi/agents/harness/incident-recorder.md +0 -1
  7. package/.pi/agents/harness/planning/decompose.md +0 -2
  8. package/.pi/agents/harness/planning/execution-plan-author.md +0 -2
  9. package/.pi/agents/harness/planning/hypothesis-validator.md +0 -2
  10. package/.pi/agents/harness/planning/hypothesis.md +0 -2
  11. package/.pi/agents/harness/planning/implementation-researcher.md +0 -2
  12. package/.pi/agents/harness/planning/plan-adversary.md +0 -2
  13. package/.pi/agents/harness/planning/plan-evaluator.md +1 -3
  14. package/.pi/agents/harness/planning/planning-context.md +0 -2
  15. package/.pi/agents/harness/planning/review-integrator.md +0 -2
  16. package/.pi/agents/harness/planning/sprint-contract-auditor.md +0 -2
  17. package/.pi/agents/harness/planning/stack-researcher.md +0 -2
  18. package/.pi/agents/harness/reviewing/adversary.md +0 -2
  19. package/.pi/agents/harness/reviewing/evaluator.md +0 -2
  20. package/.pi/agents/harness/reviewing/tie-breaker.md +0 -2
  21. package/.pi/agents/harness/running/executor.md +0 -2
  22. package/.pi/agents/harness/sentrux-bootstrap.md +0 -1
  23. package/.pi/agents/harness/sentrux-steward.md +0 -2
  24. package/.pi/agents/harness/trace-librarian.md +0 -1
  25. package/.pi/extensions/00-posthog-network-bootstrap.ts +1 -1
  26. package/.pi/extensions/agt-kill-switch.ts +57 -0
  27. package/.pi/extensions/agt-prompt-guard.ts +32 -0
  28. package/.pi/extensions/custom-footer.ts +46 -145
  29. package/.pi/extensions/custom-header.ts +1 -1
  30. package/.pi/extensions/custom-system-prompt.ts +1 -1
  31. package/.pi/extensions/debate-orchestrator.ts +6 -6
  32. package/.pi/extensions/harness-ask-user.ts +7 -7
  33. package/.pi/extensions/harness-debate-tools.ts +26 -42
  34. package/.pi/extensions/harness-lens.ts +94 -0
  35. package/.pi/extensions/harness-plan-approval.ts +11 -11
  36. package/.pi/extensions/harness-run-context.ts +1070 -876
  37. package/.pi/extensions/harness-subagent-governance.ts +8 -0
  38. package/.pi/extensions/harness-subagent-submit.ts +34 -163
  39. package/.pi/extensions/harness-subagents.ts +3 -3
  40. package/.pi/extensions/harness-telemetry.ts +2 -2
  41. package/.pi/extensions/harness-web-tools.ts +2 -2
  42. package/.pi/extensions/policy-gate.ts +25 -5
  43. package/.pi/extensions/sentrux-rules-sync.ts +1 -1
  44. package/.pi/extensions/subagent-governance.ts +92 -0
  45. package/.pi/extensions/trace-recorder.ts +1 -1
  46. package/.pi/extensions/{ultimate-pi-vcc.ts → vcc-compaction.ts} +1 -1
  47. package/.pi/harness/README.md +6 -2
  48. package/.pi/harness/agents.manifest.json +22 -25
  49. package/.pi/harness/agents.policy.yaml +275 -0
  50. package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +1 -1
  51. package/.pi/harness/docs/adrs/0035-plan-phase-review-gate.md +1 -1
  52. package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
  53. package/.pi/harness/docs/adrs/0046-agt-policy-engine.md +51 -0
  54. package/.pi/harness/docs/adrs/0047-agt-layered-security.md +39 -0
  55. package/.pi/harness/docs/adrs/0048-tool-call-hook-order.md +25 -0
  56. package/.pi/harness/docs/adrs/0049-agents-policy-manifest.md +36 -0
  57. package/.pi/harness/docs/adrs/README.md +5 -0
  58. package/.pi/harness/evolution/README.md +1 -2
  59. package/.pi/harness/examples/agents.policy.project.yaml +19 -0
  60. package/.pi/harness/examples/policies/custom-deny-bash.yaml +9 -0
  61. package/.pi/harness/policies/bash-denylists.yaml +5 -0
  62. package/.pi/harness/policies/defaults.yaml +51 -0
  63. package/.pi/harness/policies/orchestrator.yaml +18 -0
  64. package/.pi/harness/policies/phases.yaml +10 -0
  65. package/.pi/harness/policies/roles.yaml +5 -0
  66. package/.pi/harness/policies/web-guard.yaml +5 -0
  67. package/.pi/harness/policies/workflow-sequences.yaml +9 -0
  68. package/.pi/harness/sentrux/architecture.manifest.json +26 -4
  69. package/.pi/harness/specs/observation.schema.json +2 -1
  70. package/.pi/lib/agents-policy.d.mts +70 -0
  71. package/.pi/lib/agents-policy.mjs +325 -0
  72. package/.pi/lib/agents-policy.ts +19 -0
  73. package/.pi/lib/agt/audit-run-sink.ts +52 -0
  74. package/.pi/lib/agt/build-evaluation-context.ts +285 -0
  75. package/.pi/lib/agt/config.ts +28 -0
  76. package/.pi/lib/agt/delegation.ts +69 -0
  77. package/.pi/lib/agt/evaluate-policy.ts +56 -0
  78. package/.pi/lib/agt/identity-registry.ts +41 -0
  79. package/.pi/lib/agt/index.ts +55 -0
  80. package/.pi/lib/agt/kill-switch-state.ts +11 -0
  81. package/.pi/lib/agt/legacy-evaluate.ts +101 -0
  82. package/.pi/lib/agt/policy-engine.ts +154 -0
  83. package/.pi/lib/agt/rings.ts +21 -0
  84. package/.pi/lib/agt/sre-hooks.ts +45 -0
  85. package/.pi/lib/agt/trust-run-store.ts +26 -0
  86. package/.pi/lib/agt/workflow-history.ts +29 -0
  87. package/.pi/lib/agt-governance-active.ts +14 -0
  88. package/.pi/lib/agt-tool-guard.ts +78 -0
  89. package/.pi/lib/ask-user/dialog.ts +314 -0
  90. package/.pi/{extensions/lib → lib}/debate-bus-core.ts +10 -10
  91. package/.pi/{extensions/lib → lib}/debate-bus-state.ts +1 -1
  92. package/.pi/{extensions/lib → lib}/extension-load-guard.ts +13 -2
  93. package/.pi/lib/harness-agt-tool-guard.ts +5 -0
  94. package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +1 -1
  95. package/.pi/lib/harness-debate-core-deps.ts +14 -0
  96. package/.pi/lib/harness-debate-workflow-deps.ts +43 -0
  97. package/.pi/lib/harness-lens/.gitattributes +1 -0
  98. package/.pi/lib/harness-lens/clients/edit-autopatch.ts +88 -0
  99. package/.pi/lib/harness-lens/clients/file-kinds.ts +380 -0
  100. package/.pi/lib/harness-lens/clients/file-time.ts +215 -0
  101. package/.pi/lib/harness-lens/clients/file-utils.ts +484 -0
  102. package/.pi/lib/harness-lens/clients/format-service.ts +276 -0
  103. package/.pi/lib/harness-lens/clients/formatters.ts +1000 -0
  104. package/.pi/lib/harness-lens/clients/git-guard.ts +31 -0
  105. package/.pi/lib/harness-lens/clients/indent-retarget.ts +90 -0
  106. package/.pi/lib/harness-lens/clients/installer/index.ts +2368 -0
  107. package/.pi/lib/harness-lens/clients/latency-logger.ts +80 -0
  108. package/.pi/lib/harness-lens/clients/lens-config.ts +43 -0
  109. package/.pi/lib/harness-lens/clients/lens-events.ts +164 -0
  110. package/.pi/lib/harness-lens/clients/lsp/aggregation.ts +91 -0
  111. package/.pi/lib/harness-lens/clients/lsp/client.ts +1466 -0
  112. package/.pi/lib/harness-lens/clients/lsp/config.ts +216 -0
  113. package/.pi/lib/harness-lens/clients/lsp/edits.ts +297 -0
  114. package/.pi/lib/harness-lens/clients/lsp/index.ts +1355 -0
  115. package/.pi/lib/harness-lens/clients/lsp/interactive-install.ts +424 -0
  116. package/.pi/lib/harness-lens/clients/lsp/language.ts +223 -0
  117. package/.pi/lib/harness-lens/clients/lsp/launch.ts +939 -0
  118. package/.pi/lib/harness-lens/clients/lsp/lsp-index.ts +11 -0
  119. package/.pi/lib/harness-lens/clients/lsp/path-utils.ts +12 -0
  120. package/.pi/lib/harness-lens/clients/lsp/server-strategies.ts +81 -0
  121. package/.pi/lib/harness-lens/clients/lsp/server.ts +1971 -0
  122. package/.pi/lib/harness-lens/clients/path-utils.ts +182 -0
  123. package/.pi/lib/harness-lens/clients/pipeline.ts +360 -0
  124. package/.pi/lib/harness-lens/clients/project-profile.ts +117 -0
  125. package/.pi/lib/harness-lens/clients/runtime-agent-end.ts +112 -0
  126. package/.pi/lib/harness-lens/clients/runtime-config.ts +33 -0
  127. package/.pi/lib/harness-lens/clients/runtime-coordinator.ts +186 -0
  128. package/.pi/lib/harness-lens/clients/runtime-tool-result.ts +171 -0
  129. package/.pi/lib/harness-lens/clients/safe-spawn.ts +339 -0
  130. package/.pi/lib/harness-lens/clients/secrets-scanner.ts +214 -0
  131. package/.pi/lib/harness-lens/clients/tool-policy.ts +2072 -0
  132. package/.pi/lib/harness-lens/clients/types.ts +59 -0
  133. package/.pi/lib/harness-lens/clients/widget-state.ts +283 -0
  134. package/.pi/lib/harness-lens/index.ts +532 -0
  135. package/.pi/lib/harness-lens/tools/lsp-diagnostics.ts +706 -0
  136. package/.pi/lib/harness-lens/tools/lsp-navigation.ts +1246 -0
  137. package/.pi/{extensions/lib → lib}/harness-posthog.ts +3 -0
  138. package/.pi/lib/harness-run-context-responses.ts +9 -0
  139. package/.pi/lib/harness-run-context.ts +0 -2
  140. package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +1 -0
  141. package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +1 -1
  142. package/.pi/lib/harness-subagent-auth.ts +51 -0
  143. package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +10 -7
  144. package/.pi/{extensions/lib → lib}/harness-subagent-submit-pipeline.ts +3 -3
  145. package/.pi/lib/harness-subagent-submit-register.ts +163 -0
  146. package/.pi/{extensions/lib → lib}/harness-subagent-submit-registry.ts +1 -37
  147. package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +53 -14
  148. package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
  149. package/.pi/{extensions/lib → lib}/plan-approval/create-plan.ts +2 -2
  150. package/.pi/{extensions/lib → lib}/plan-approval/format-plan.ts +2 -2
  151. package/.pi/{extensions/lib → lib}/plan-approval/plan-review.ts +162 -201
  152. package/.pi/{extensions/lib → lib}/plan-approval/render.ts +1 -1
  153. package/.pi/{extensions/lib → lib}/plan-approval/resolve-disk.ts +2 -2
  154. package/.pi/{extensions/lib → lib}/plan-approval/types.ts +1 -1
  155. package/.pi/{extensions/lib → lib}/plan-approval/validate.ts +3 -3
  156. package/.pi/{extensions/lib → lib}/plan-debate-envelope.ts +1 -1
  157. package/.pi/{extensions/lib → lib}/plan-debate-gate.ts +1 -1
  158. package/.pi/{extensions/lib → lib}/plan-debate-lane.ts +1 -4
  159. package/.pi/{extensions/lib → lib}/plan-messenger.ts +1 -1
  160. package/.pi/prompts/harness-plan.md +1 -1
  161. package/.pi/prompts/harness-setup.md +37 -64
  162. package/.pi/scripts/README.md +2 -5
  163. package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
  164. package/.pi/scripts/harness-agents-manifest.mjs +60 -3
  165. package/.pi/scripts/harness-agt-doctor.ts +36 -0
  166. package/.pi/scripts/harness-cli-verify.sh +9 -2
  167. package/.pi/scripts/harness-verify.mjs +113 -39
  168. package/.pi/scripts/harness-web-policy-guard.mjs +2 -2
  169. package/.pi/scripts/validate-plan-dag.mjs +65 -74
  170. package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +2 -2
  171. package/.pi/scripts/vendor-sync-pi-vcc.sh +1 -1
  172. package/.pi/skills/architecture/broker-domain/SKILL.md +65 -0
  173. package/.pi/skills/architecture/cqrs/SKILL.md +63 -0
  174. package/.pi/skills/architecture/event-driven/SKILL.md +60 -0
  175. package/.pi/skills/architecture/hexagonal-ports-adapters/SKILL.md +66 -0
  176. package/.pi/skills/architecture/layered/SKILL.md +68 -0
  177. package/.pi/skills/architecture/microkernel/SKILL.md +62 -0
  178. package/.pi/skills/architecture/microservices/SKILL.md +64 -0
  179. package/.pi/skills/architecture/modular-monolith/SKILL.md +65 -0
  180. package/.pi/skills/architecture/orchestration-driven-soa/SKILL.md +61 -0
  181. package/.pi/skills/architecture/pipeline/SKILL.md +63 -0
  182. package/.pi/skills/architecture/service-based/SKILL.md +64 -0
  183. package/.pi/skills/architecture/service-mesh/SKILL.md +60 -0
  184. package/.pi/skills/architecture/space-based/SKILL.md +60 -0
  185. package/.pi/skills/ast-grep/SKILL.md +40 -321
  186. package/.pi/skills/delivery/debugging-discipline/SKILL.md +36 -0
  187. package/.pi/skills/delivery/documentation-update/SKILL.md +33 -0
  188. package/.pi/skills/delivery/requirements-to-implementation/SKILL.md +34 -0
  189. package/.pi/skills/delivery/risk-based-verification/SKILL.md +43 -0
  190. package/.pi/skills/delivery/tradeoff-analysis/SKILL.md +34 -0
  191. package/.pi/skills/engineering/api-contract-design/SKILL.md +38 -0
  192. package/.pi/skills/engineering/cohesion-coupling/SKILL.md +43 -0
  193. package/.pi/skills/engineering/complexity-control/SKILL.md +31 -0
  194. package/.pi/skills/engineering/defensive-programming/SKILL.md +38 -0
  195. package/.pi/skills/engineering/dependency-management/SKILL.md +29 -0
  196. package/.pi/skills/engineering/domain-modeling/SKILL.md +32 -0
  197. package/.pi/skills/engineering/error-handling/SKILL.md +37 -0
  198. package/.pi/skills/engineering/legacy-code-seams/SKILL.md +35 -0
  199. package/.pi/skills/engineering/naming-and-intent/SKILL.md +29 -0
  200. package/.pi/skills/engineering/refactoring-safe-evolution/SKILL.md +35 -0
  201. package/.pi/skills/engineering/routine-function-design/SKILL.md +34 -0
  202. package/.pi/skills/engineering/small-change-discipline/SKILL.md +35 -0
  203. package/.pi/skills/lsp-navigation/SKILL.md +89 -0
  204. package/.pi/skills/quality/code-review-self-check/SKILL.md +35 -0
  205. package/.pi/skills/quality/privacy-data-handling/SKILL.md +26 -0
  206. package/.pi/skills/quality/security-review/SKILL.md +34 -0
  207. package/.pi/skills/quality/test-strategy/SKILL.md +33 -0
  208. package/.pi/skills/quality/testability-design/SKILL.md +33 -0
  209. package/.pi/skills/systems/concurrency-safety/SKILL.md +32 -0
  210. package/.pi/skills/systems/data-modeling-migrations/SKILL.md +31 -0
  211. package/.pi/skills/systems/observability-instrumentation/SKILL.md +32 -0
  212. package/.pi/skills/systems/performance-measurement/SKILL.md +35 -0
  213. package/.pi/skills/systems/reliability-design/SKILL.md +32 -0
  214. package/.sentrux/rules.toml +20 -4
  215. package/AGENTS.md +5 -0
  216. package/CHANGELOG.md +14 -0
  217. package/README.md +3 -12
  218. package/THIRD_PARTY_NOTICES.md +12 -21
  219. package/package.json +15 -7
  220. package/vendor/pi-subagents/src/agents.ts +45 -1
  221. package/vendor/pi-subagents/src/subagents.ts +866 -811
  222. package/vendor/pi-vcc/src/core/brief.ts +68 -99
  223. package/vendor/pi-vcc/src/core/settings.ts +2 -2
  224. package/.agents/skills/caveman/SKILL.md +0 -67
  225. package/.pi/agents/harness/meta-optimizer.md +0 -36
  226. package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
  227. package/.pi/extensions/lib/harness-subagent-auth.ts +0 -207
  228. package/.pi/extensions/lib/harness-subagent-policy.ts +0 -236
  229. package/.pi/extensions/pi-model-router-harness.ts +0 -42
  230. package/.pi/harness/evolution/meta-optimizer.mjs +0 -99
  231. package/.pi/harness/specs/router-tuning-proposal.schema.json +0 -114
  232. package/.pi/model-router.example.json +0 -36
  233. package/.pi/prompts/harness-critic.md +0 -10
  234. package/.pi/prompts/harness-eval.md +0 -10
  235. package/.pi/prompts/harness-router-tune.md +0 -52
  236. package/.pi/scripts/harness-generate-model-router.mjs +0 -327
  237. package/.pi/scripts/harness-model-router-routing.test.mjs +0 -97
  238. package/.pi/scripts/harness-sync-model-router.mjs +0 -97
  239. package/.pi/scripts/vendor-sync-pi-model-router.sh +0 -47
  240. package/vendor/pi-model-router/.prettierignore +0 -4
  241. package/vendor/pi-model-router/.prettierrc +0 -5
  242. package/vendor/pi-model-router/AGENTS.md +0 -39
  243. package/vendor/pi-model-router/LICENSE +0 -21
  244. package/vendor/pi-model-router/README.md +0 -99
  245. package/vendor/pi-model-router/UPSTREAM_PIN.md +0 -10
  246. package/vendor/pi-model-router/docs/ARCHITECTURE.md +0 -54
  247. package/vendor/pi-model-router/extensions/commands.ts +0 -720
  248. package/vendor/pi-model-router/extensions/config.ts +0 -348
  249. package/vendor/pi-model-router/extensions/constants.ts +0 -1
  250. package/vendor/pi-model-router/extensions/index.ts +0 -478
  251. package/vendor/pi-model-router/extensions/provider.ts +0 -580
  252. package/vendor/pi-model-router/extensions/routing.ts +0 -564
  253. package/vendor/pi-model-router/extensions/state.ts +0 -52
  254. package/vendor/pi-model-router/extensions/types.ts +0 -95
  255. package/vendor/pi-model-router/extensions/ui.ts +0 -144
  256. package/vendor/pi-model-router/model-router.example.json +0 -48
  257. package/vendor/pi-model-router/package.json +0 -48
  258. package/vendor/pi-model-router/tsconfig.json +0 -16
  259. /package/.pi/{prompts → harness/docs}/planning-rubrics.md +0 -0
  260. /package/.pi/{extensions/lib → lib}/ask-user/fallback.ts +0 -0
  261. /package/.pi/{extensions/lib → lib}/ask-user/render.ts +0 -0
  262. /package/.pi/{extensions/lib → lib}/ask-user/schema.ts +0 -0
  263. /package/.pi/{extensions/lib → lib}/ask-user/types.ts +0 -0
  264. /package/.pi/{extensions/lib → lib}/ask-user/validate-core.mjs +0 -0
  265. /package/.pi/{extensions/lib → lib}/ask-user/validate.ts +0 -0
  266. /package/.pi/{extensions/lib → lib}/harness-cocoindex-refresh.ts +0 -0
  267. /package/.pi/{extensions/lib → lib}/harness-paths.ts +0 -0
  268. /package/.pi/{extensions/lib → lib}/harness-spawn-budget.ts +0 -0
  269. /package/.pi/{extensions/lib → lib}/harness-vcc-settings.ts +0 -0
  270. /package/.pi/{extensions/lib → lib}/harness-web/run-cli.ts +0 -0
  271. /package/.pi/{extensions/lib → lib}/plan-approval/dialog.ts +0 -0
  272. /package/.pi/{extensions/lib → lib}/plan-approval/schema.ts +0 -0
  273. /package/.pi/{extensions/lib → lib}/plan-approval-readiness.ts +0 -0
  274. /package/.pi/{extensions/lib → lib}/plan-debate-eligibility.ts +0 -0
  275. /package/.pi/{extensions/lib → lib}/plan-debate-focus.ts +0 -0
  276. /package/.pi/{extensions/lib → lib}/plan-debate-id.ts +0 -0
  277. /package/.pi/{extensions/lib → lib}/plan-debate-lanes.ts +0 -0
  278. /package/.pi/{extensions/lib → lib}/plan-debate-round-status.ts +0 -0
  279. /package/.pi/{extensions/lib → lib}/plan-debate-write-guard.ts +0 -0
  280. /package/.pi/{extensions/lib → lib}/plan-review-gate.ts +0 -0
  281. /package/.pi/{extensions/lib → lib}/plan-review-integrator-rules.ts +0 -0
  282. /package/.pi/{extensions/lib → lib}/plan-scope-guard.ts +0 -0
  283. /package/.pi/{extensions/lib → lib}/posthog-client.ts +0 -0
  284. /package/.pi/{extensions/lib → lib}/posthog-node.d.ts +0 -0
@@ -24,6 +24,9 @@ export type HarnessPostHogEventName =
24
24
  | "harness_eval_verdict"
25
25
  | "harness_sentrux_signal"
26
26
  | "harness_observation"
27
+ | "harness_lens_analysis_complete"
28
+ | "harness_lens_findings"
29
+ | "harness_lens_turn_findings"
27
30
  | "harness_subagent_spawned"
28
31
  | "harness_subagent_completed"
29
32
  | "harness_subagent_result_wait"
@@ -0,0 +1,9 @@
1
+ export function blockRunContextMessage(content: string) {
2
+ return {
3
+ message: {
4
+ customType: "harness-run-context-block",
5
+ display: true,
6
+ content,
7
+ },
8
+ };
9
+ }
@@ -101,7 +101,6 @@ const HARNESS_COMMANDS = new Set([
101
101
  "harness-drift-proceed",
102
102
  "harness-policy-status",
103
103
  "harness-trace-last",
104
- "harness-router-tune",
105
104
  "harness-budget-status",
106
105
  ]);
107
106
 
@@ -213,7 +212,6 @@ export const HARNESS_COMMAND_PHASE: Record<string, HarnessPhase> = {
213
212
  "harness-run-status": "plan",
214
213
  "harness-use-run": "plan",
215
214
  "harness-policy-status": "merge",
216
- "harness-router-tune": "plan",
217
215
  "harness-budget-status": "plan",
218
216
  "harness-setup": "execute",
219
217
  };
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Subagent tool policy — block nested orchestration tools (defense in depth).
3
+ * Shared by AGT evaluation context and extensions (lives under .pi/lib, not extensions).
3
4
  */
4
5
 
5
6
  export const SUBAGENT_BLOCKED_TOOLS = new Set([
@@ -5,7 +5,7 @@
5
5
  import { constants } from "node:fs";
6
6
  import { access } from "node:fs/promises";
7
7
  import { join } from "node:path";
8
- import type { HarnessPhase } from "../../lib/harness-run-context.js";
8
+ import type { HarnessPhase } from "./harness-run-context.js";
9
9
 
10
10
  export interface SpawnTopologyResult {
11
11
  ok: boolean;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Resolve concrete LLM credentials for harness subagent subprocesses.
3
+ *
4
+ * Harness subprocesses run with `--no-extensions`, so auth forwarding only uses
5
+ * concrete provider/model references from the parent session or agent config.
6
+ */
7
+
8
+ import type { AgentConfig } from "../../vendor/pi-subagents/src/agents.js";
9
+
10
+ const SENTINEL_API_KEYS = new Set(["<authenticated>"]);
11
+
12
+ export function isUsableApiKey(key: string | undefined): key is string {
13
+ return Boolean(key && !SENTINEL_API_KEYS.has(key));
14
+ }
15
+
16
+ export function parseModelRef(
17
+ ref: string,
18
+ ): { provider: string; modelId: string } | null {
19
+ const slash = ref.indexOf("/");
20
+ if (slash <= 0) return null;
21
+ const provider = ref.slice(0, slash).trim();
22
+ const modelId = ref.slice(slash + 1).trim();
23
+ if (!provider || !modelId || provider === "router") return null;
24
+ return { provider, modelId };
25
+ }
26
+
27
+ export interface ConcreteSubagentModel {
28
+ modelRef: string;
29
+ provider: string;
30
+ modelId: string;
31
+ }
32
+
33
+ export function resolveConcreteSubagentModel(
34
+ _parentCwd: string,
35
+ parentModel: { provider: string; id: string } | undefined,
36
+ agent: AgentConfig,
37
+ _taskSnippet?: string,
38
+ ): ConcreteSubagentModel | undefined {
39
+ if (agent.model) {
40
+ const parsed = parseModelRef(agent.model);
41
+ if (parsed) {
42
+ return { modelRef: agent.model, ...parsed };
43
+ }
44
+ }
45
+
46
+ if (!parentModel || parentModel.provider === "router") return undefined;
47
+ const modelRef = `${parentModel.provider}/${parentModel.id}`;
48
+ const parsed = parseModelRef(modelRef);
49
+ if (!parsed) return undefined;
50
+ return { modelRef, ...parsed };
51
+ }
@@ -5,13 +5,11 @@
5
5
  import {
6
6
  type AgentConfig,
7
7
  agentAllowsMutatingTools,
8
- } from "../../../vendor/pi-subagents/src/agents.js";
9
- import {
10
- type HarnessPhase,
11
- inferHarnessPhase,
12
- } from "../../lib/harness-run-context.js";
8
+ } from "../../vendor/pi-subagents/src/agents.js";
9
+ import { getAgentKind } from "./agents-policy.mjs";
10
+ import { getHarnessPackageRoot } from "./harness-paths.js";
11
+ import { type HarnessPhase, inferHarnessPhase } from "./harness-run-context.js";
13
12
  import { validateHarnessSpawnTopology } from "./harness-spawn-topology.js";
14
- import { classifyHarnessAgent } from "./harness-subagent-policy.js";
15
13
 
16
14
  export interface SubagentTaskRef {
17
15
  agent: string;
@@ -105,9 +103,14 @@ export async function precheckHarnessSubagentSpawn(
105
103
  return topology;
106
104
  }
107
105
 
106
+ const packageRoot = getHarnessPackageRoot(
107
+ // @ts-expect-error pi extensions run as ESM
108
+ import.meta.url,
109
+ );
110
+ const projectRoot = opts?.projectRoot ?? process.cwd();
108
111
  for (const name of names) {
109
112
  if (!name.startsWith("harness/")) continue;
110
- classifyHarnessAgent(name);
113
+ getAgentKind(packageRoot, projectRoot, name);
111
114
  }
112
115
 
113
116
  return { ok: true };
@@ -4,13 +4,13 @@
4
4
 
5
5
  import { mkdir, readFile } from "node:fs/promises";
6
6
  import { dirname, join, resolve } from "node:path";
7
- import { validateAgainstHarnessSchema } from "../../lib/harness-schema-validate.js";
8
- import { resolveGuardedRunDir } from "../../lib/harness-subagent-submit-path.js";
9
- import { writeYamlFile } from "../../lib/harness-yaml.js";
7
+ import { validateAgainstHarnessSchema } from "./harness-schema-validate.js";
8
+ import { resolveGuardedRunDir } from "./harness-subagent-submit-path.js";
10
9
  import {
11
10
  resolveArtifactRelPath,
12
11
  type SubmitToolSpec,
13
12
  } from "./harness-subagent-submit-registry.js";
13
+ import { writeYamlFile } from "./harness-yaml.js";
14
14
  import {
15
15
  type ApplyDebateLaneResult,
16
16
  applyDebateLaneFromDoc,
@@ -0,0 +1,163 @@
1
+ import { join } from "node:path";
2
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ import { Type } from "@sinclair/typebox";
4
+ import { allowsAgentTool } from "./agents-policy.mjs";
5
+ import { resolveGuardedRunDir } from "./harness-subagent-submit-path.js";
6
+ import {
7
+ executeSubmitPipeline,
8
+ loadSubmitDocument,
9
+ } from "./harness-subagent-submit-pipeline.js";
10
+ import { SUBMIT_TOOL_SPECS } from "./harness-subagent-submit-registry.js";
11
+
12
+ const DocumentSchema = Type.Object(
13
+ {
14
+ document: Type.Optional(
15
+ Type.Record(Type.String(), Type.Unknown(), {
16
+ description:
17
+ "Artifact fields (deprecated when source_path is set; ADR 0043)",
18
+ }),
19
+ ),
20
+ source_path: Type.Optional(
21
+ Type.String({
22
+ description:
23
+ "Relative path under run dir, e.g. artifacts/.draft/decomposition.yaml",
24
+ }),
25
+ ),
26
+ },
27
+ { additionalProperties: false },
28
+ );
29
+
30
+ export function resolveHarnessSubmitRunContext(packageRoot: string): {
31
+ projectRoot: string;
32
+ specsDir: string;
33
+ runId: string;
34
+ runDirEnv?: string;
35
+ agentId: string;
36
+ } {
37
+ const projectRoot = process.env.HARNESS_PKG_ROOT?.trim() || packageRoot;
38
+ const specsDir = join(projectRoot, ".pi", "harness", "specs");
39
+ const runId = process.env.HARNESS_RUN_ID?.trim() ?? "";
40
+ const runDirEnv = process.env.HARNESS_RUN_DIR?.trim();
41
+ const agentId = process.env.HARNESS_AGENT_ID?.trim() ?? "";
42
+ return { projectRoot, specsDir, runId, runDirEnv, agentId };
43
+ }
44
+
45
+ export function isSubprocessHarnessSubmit(): boolean {
46
+ return (
47
+ process.env.PI_HARNESS_SUBPROCESS === "1" &&
48
+ Boolean(process.env.HARNESS_RUN_ID?.trim())
49
+ );
50
+ }
51
+
52
+ export function registerHarnessSubagentSubmitTools(
53
+ pi: ExtensionAPI,
54
+ packageRoot: string,
55
+ ): void {
56
+ for (const spec of SUBMIT_TOOL_SPECS) {
57
+ pi.registerTool({
58
+ name: spec.toolName,
59
+ label: spec.toolName.replace(/^submit_/, "Submit "),
60
+ description: `Terminal harness artifact submit (${spec.toolName}). Call once with the full schema document before ending the turn.`,
61
+ parameters: DocumentSchema,
62
+ async execute(_id, params, _signal, _onUpdate, _ctx) {
63
+ if (!isSubprocessHarnessSubmit()) {
64
+ return {
65
+ content: [
66
+ {
67
+ type: "text",
68
+ text: "submit tools require PI_HARNESS_SUBPROCESS and HARNESS_RUN_ID",
69
+ },
70
+ ],
71
+ details: {},
72
+ isError: true,
73
+ };
74
+ }
75
+ const { projectRoot, specsDir, runId, runDirEnv, agentId } =
76
+ resolveHarnessSubmitRunContext(packageRoot);
77
+ if (
78
+ !allowsAgentTool({
79
+ packageRoot,
80
+ projectRoot,
81
+ agentId,
82
+ toolName: spec.toolName,
83
+ toolInput: params as Record<string, unknown>,
84
+ isSubprocess: true,
85
+ })
86
+ ) {
87
+ return {
88
+ content: [
89
+ {
90
+ type: "text",
91
+ text: `${spec.toolName} is not allowed for agent ${agentId} (agents.policy.yaml)`,
92
+ },
93
+ ],
94
+ details: { agentId, tool: spec.toolName },
95
+ isError: true,
96
+ };
97
+ }
98
+ const runResolved = await resolveGuardedRunDir({
99
+ projectRoot,
100
+ runId,
101
+ runDirEnv,
102
+ });
103
+ if (!runResolved.ok) {
104
+ return {
105
+ content: [{ type: "text", text: runResolved.error }],
106
+ details: {},
107
+ isError: true,
108
+ };
109
+ }
110
+ const loaded = await loadSubmitDocument({
111
+ projectRoot,
112
+ runDir: runResolved.runDir,
113
+ document: (params as { document?: Record<string, unknown> }).document,
114
+ source_path: (params as { source_path?: string }).source_path,
115
+ });
116
+ if (!loaded.ok) {
117
+ return {
118
+ content: [
119
+ {
120
+ type: "text",
121
+ text: `Validation failed:\n${loaded.validation_errors.join("\n")}`,
122
+ },
123
+ ],
124
+ isError: true,
125
+ details: loaded,
126
+ };
127
+ }
128
+ const result = await executeSubmitPipeline({
129
+ projectRoot,
130
+ specsDir,
131
+ spec,
132
+ agentId,
133
+ document: loaded.document,
134
+ runId,
135
+ runDirEnv,
136
+ });
137
+ if (!result.ok) {
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: `Validation failed:\n${(result.validation_errors ?? []).join("\n")}`,
143
+ },
144
+ ],
145
+ isError: true,
146
+ details: result,
147
+ };
148
+ }
149
+ const lines = [`ok: wrote ${result.artifact_path}`];
150
+ if (result.lane_result?.messenger_posted) {
151
+ lines.push("messenger updated");
152
+ }
153
+ if (result.human_required) {
154
+ lines.push("human_required: parent must call ask_user");
155
+ }
156
+ return {
157
+ content: [{ type: "text", text: lines.join("\n") }],
158
+ details: result as unknown,
159
+ };
160
+ },
161
+ });
162
+ }
163
+ }
@@ -1,12 +1,11 @@
1
1
  /**
2
- * Registry: submit tool name → agent allowlist, schema, artifact path.
2
+ * Registry: submit tool name → schema, artifact path (allowlists live in agents.policy.yaml).
3
3
  */
4
4
 
5
5
  import type { DebateLaneKind } from "./plan-debate-lane.js";
6
6
 
7
7
  export interface SubmitToolSpec {
8
8
  toolName: string;
9
- agents: readonly string[];
10
9
  schemaFile: string;
11
10
  artifactPath: string | ((doc: Record<string, unknown>) => string);
12
11
  debateLane?: DebateLaneKind;
@@ -24,126 +23,91 @@ function roundPath(prefix: string, doc: Record<string, unknown>): string {
24
23
  export const SUBMIT_TOOL_SPECS: readonly SubmitToolSpec[] = [
25
24
  {
26
25
  toolName: "submit_planning_context",
27
- agents: ["harness/planning/planning-context"],
28
26
  schemaFile: "plan-planning-context.schema.json",
29
27
  artifactPath: "artifacts/planning-context.yaml",
30
28
  },
31
29
  {
32
30
  toolName: "submit_decomposition_brief",
33
- agents: ["harness/planning/decompose", "harness/planning/plan-synthesizer"],
34
31
  schemaFile: "plan-decomposition-brief.schema.json",
35
32
  artifactPath: "artifacts/decomposition.yaml",
36
33
  },
37
34
  {
38
35
  toolName: "submit_hypothesis_brief",
39
- agents: [
40
- "harness/planning/hypothesis",
41
- "harness/planning/plan-synthesizer",
42
- ],
43
36
  schemaFile: "plan-hypothesis-brief.schema.json",
44
37
  artifactPath: "artifacts/hypothesis.yaml",
45
38
  },
46
39
  {
47
40
  toolName: "submit_implementation_research",
48
- agents: ["harness/planning/implementation-researcher"],
49
41
  schemaFile: "plan-implementation-research-brief.schema.json",
50
42
  artifactPath: "artifacts/implementation-research.yaml",
51
43
  },
52
44
  {
53
45
  toolName: "submit_stack_brief",
54
- agents: ["harness/planning/stack-researcher"],
55
46
  schemaFile: "plan-stack-brief.schema.json",
56
47
  artifactPath: "artifacts/stack.yaml",
57
48
  },
58
49
  {
59
50
  toolName: "submit_execution_plan_brief",
60
- agents: [
61
- "harness/planning/execution-plan-author",
62
- "harness/planning/plan-synthesizer",
63
- ],
64
51
  schemaFile: "plan-execution-plan-brief.schema.json",
65
52
  artifactPath: "artifacts/execution-plan-draft.yaml",
66
53
  },
67
54
  {
68
55
  toolName: "submit_hypothesis_validation",
69
- agents: ["harness/planning/hypothesis-validator"],
70
56
  schemaFile: "plan-hypothesis-eval.schema.json",
71
57
  artifactPath: (doc) => roundPath("hypothesis-validation", doc),
72
58
  debateLane: "hypothesis-validation",
73
59
  },
74
60
  {
75
61
  toolName: "submit_validation_turn",
76
- agents: ["harness/planning/plan-evaluator"],
77
62
  schemaFile: "plan-validation-turn.schema.json",
78
63
  artifactPath: (doc) => roundPath("validation-turn", doc),
79
64
  debateLane: "validation-turn",
80
65
  },
81
66
  {
82
67
  toolName: "submit_adversary_brief",
83
- agents: ["harness/planning/plan-adversary"],
84
68
  schemaFile: "plan-adversary-brief.schema.json",
85
69
  artifactPath: (doc) => roundPath("adversary-brief", doc),
86
70
  debateLane: "adversary-brief",
87
71
  },
88
72
  {
89
73
  toolName: "submit_sprint_audit",
90
- agents: ["harness/planning/sprint-contract-auditor"],
91
74
  schemaFile: "plan-sprint-audit-turn.schema.json",
92
75
  artifactPath: (doc) => roundPath("sprint-audit", doc),
93
76
  debateLane: "sprint-audit",
94
77
  },
95
78
  {
96
79
  toolName: "submit_review_round_draft",
97
- agents: ["harness/planning/review-integrator"],
98
80
  schemaFile: "plan-review-round-draft.schema.json",
99
81
  artifactPath: (doc) => roundPath("review-round-draft", doc),
100
82
  },
101
83
  {
102
84
  toolName: "submit_executor_handoff",
103
- agents: ["harness/running/executor"],
104
85
  schemaFile: "harness-executor-handoff.schema.json",
105
86
  artifactPath: "handoff/executor-summary.yaml",
106
87
  },
107
88
  {
108
89
  toolName: "submit_eval_verdict",
109
- agents: ["harness/reviewing/evaluator"],
110
90
  schemaFile: "eval-verdict.schema.json",
111
91
  artifactPath: "artifacts/eval-verdict.yaml",
112
92
  },
113
93
  {
114
94
  toolName: "submit_adversary_report",
115
- agents: ["harness/reviewing/adversary"],
116
95
  schemaFile: "adversary-report.schema.json",
117
96
  artifactPath: "artifacts/adversary-report.yaml",
118
97
  },
119
98
  {
120
99
  toolName: "submit_human_required",
121
- agents: ["harness/planning/decompose", "harness/planning/hypothesis"],
122
100
  schemaFile: "harness-human-required.schema.json",
123
101
  artifactPath: "artifacts/human-required.yaml",
124
102
  humanRequired: true,
125
103
  },
126
104
  {
127
105
  toolName: "submit_sentrux_manifest_proposal",
128
- agents: ["harness/sentrux-steward"],
129
106
  schemaFile: "sentrux-manifest-proposal.schema.json",
130
107
  artifactPath: "artifacts/sentrux-manifest-proposal.yaml",
131
108
  },
132
109
  ] as const;
133
110
 
134
- export const SUBMIT_TOOLS_BY_AGENT: Readonly<
135
- Record<string, ReadonlySet<string>>
136
- > = (() => {
137
- const map = new Map<string, Set<string>>();
138
- for (const spec of SUBMIT_TOOL_SPECS) {
139
- for (const agent of spec.agents) {
140
- if (!map.has(agent)) map.set(agent, new Set());
141
- map.get(agent)?.add(spec.toolName);
142
- }
143
- }
144
- return Object.fromEntries(map.entries());
145
- })();
146
-
147
111
  export function specForSubmitTool(
148
112
  toolName: string,
149
113
  ): SubmitToolSpec | undefined {
@@ -7,21 +7,26 @@ import type {
7
7
  ExtensionAPI,
8
8
  ExtensionContext,
9
9
  } from "@earendil-works/pi-coding-agent";
10
- import type { AgentConfig } from "../../../vendor/pi-subagents/src/agents.js";
10
+ import type { AgentConfig } from "../../vendor/pi-subagents/src/agents.js";
11
11
  import {
12
12
  createSubagentsExtension,
13
13
  type HarnessSubagentsOptions,
14
14
  type SpawnAuthForward,
15
- } from "../../../vendor/pi-subagents/src/subagents.js";
15
+ } from "../../vendor/pi-subagents/src/subagents.js";
16
+ import { subagentGovernanceExtensionPath } from "../extensions/subagent-governance.js";
17
+ import { getAgentKind } from "./agents-policy.mjs";
18
+ import {
19
+ delegationEnvFromBundle,
20
+ mintSubagentDelegation,
21
+ } from "./agt/delegation.js";
22
+ import { spawnCircuitOpen } from "./agt/sre-hooks.js";
23
+ import { refreshHarnessCocoindexIndex } from "./harness-cocoindex-refresh.js";
24
+ import { captureHarnessEvent } from "./harness-posthog.js";
16
25
  import {
17
26
  getLatestRunContext,
18
27
  getRunIdFromSession,
19
28
  type HarnessPhase,
20
- } from "../../lib/harness-run-context.js";
21
- import { parseSpawnContextFromTask } from "../../lib/harness-spawn-parse.js";
22
- import { harnessSubagentSubmitExtensionPath } from "../harness-subagent-submit.js";
23
- import { refreshHarnessCocoindexIndex } from "./harness-cocoindex-refresh.js";
24
- import { captureHarnessEvent } from "./harness-posthog.js";
29
+ } from "./harness-run-context.js";
25
30
  import {
26
31
  checkHarnessSpawnBudget,
27
32
  countHarnessAgentsInRequest,
@@ -29,6 +34,7 @@ import {
29
34
  recordSpawnEnd,
30
35
  recordSpawnStart,
31
36
  } from "./harness-spawn-budget.js";
37
+ import { parseSpawnContextFromTask } from "./harness-spawn-parse.js";
32
38
  import {
33
39
  isUsableApiKey,
34
40
  resolveConcreteSubagentModel,
@@ -111,19 +117,52 @@ async function resolveHarnessSpawnAuth(
111
117
  export function createHarnessSubagentsExtension(
112
118
  packageRoot: string,
113
119
  ): (pi: ExtensionAPI) => void {
114
- const submitExtPath = harnessSubagentSubmitExtensionPath(packageRoot);
120
+ const governanceExtPath = subagentGovernanceExtensionPath(packageRoot);
115
121
  const options: HarnessSubagentsOptions = {
116
122
  packageRoot,
117
- harnessSubprocessExtensionPath: submitExtPath,
123
+ subprocessGovernanceExtensionPath: governanceExtPath,
124
+ harnessSubprocessExtensionPath: governanceExtPath,
118
125
  resolveSubprocessEnv: (task, agent) => {
119
- if (!agent.name.startsWith("harness/")) return undefined;
126
+ const projectRoot = process.cwd();
127
+ const base: Record<string, string> = {
128
+ PI_HARNESS_SUBPROCESS: "1",
129
+ HARNESS_AGENT_ID: agent.name,
130
+ HARNESS_PKG_ROOT: packageRoot,
131
+ HARNESS_PROJECT_ROOT: projectRoot,
132
+ };
120
133
  const ctx = parseSpawnContextFromTask(task);
121
- if (!ctx?.run_id) return undefined;
134
+ if (!ctx?.run_id) return base;
135
+ if (spawnCircuitOpen(ctx.run_id)) {
136
+ return undefined;
137
+ }
138
+ const runDir =
139
+ ctx.run_dir ?? join(packageRoot, ".pi", "harness", "runs", ctx.run_id);
140
+ const kind = getAgentKind(packageRoot, projectRoot, agent.name);
141
+ let delegationEnv: Record<string, string> = {};
142
+ try {
143
+ const bundle = mintSubagentDelegation({
144
+ runId: ctx.run_id,
145
+ runDir,
146
+ agentId: agent.name,
147
+ agentKind: kind,
148
+ });
149
+ delegationEnv = delegationEnvFromBundle(bundle);
150
+ } catch {
151
+ /* identity mint best-effort */
152
+ }
122
153
  return {
154
+ ...base,
123
155
  HARNESS_RUN_ID: ctx.run_id,
124
- HARNESS_RUN_DIR:
125
- ctx.run_dir ??
126
- join(packageRoot, ".pi", "harness", "runs", ctx.run_id),
156
+ HARNESS_RUN_DIR: runDir,
157
+ HARNESS_SUBAGENT_PHASE_HINT:
158
+ kind === "executor"
159
+ ? "execute"
160
+ : kind === "evaluator"
161
+ ? "evaluate"
162
+ : kind === "adversary"
163
+ ? "adversary"
164
+ : "plan",
165
+ ...delegationEnv,
127
166
  };
128
167
  },
129
168
  defaultAgentScope: "both",
@@ -13,7 +13,7 @@ import {
13
13
  loadRunContextForSubprocess,
14
14
  nowIso,
15
15
  policyBootstrapFromRunContext,
16
- } from "../../lib/harness-run-context.js";
16
+ } from "./harness-run-context.js";
17
17
 
18
18
  type PolicyState = {
19
19
  phase: "plan" | "execute" | "evaluate" | "adversary" | "merge";
@@ -8,8 +8,8 @@ import {
8
8
  saveProjectActiveRun,
9
9
  saveRunContextToDisk,
10
10
  validatePlanPacket,
11
- } from "../../../lib/harness-run-context.js";
12
- import { writeYamlFile } from "../../../lib/harness-yaml.js";
11
+ } from "../harness-run-context.js";
12
+ import { writeYamlFile } from "../harness-yaml.js";
13
13
  import { writePlanReviewMarkdown } from "./plan-review.js";
14
14
 
15
15
  export const CREATE_PLAN_SNIPPET = "create_plan()";
@@ -1,5 +1,5 @@
1
- import type { PlanPacketLike } from "../../../lib/harness-run-context.js";
2
- import { stringifyYaml } from "../../../lib/harness-yaml.js";
1
+ import type { PlanPacketLike } from "../harness-run-context.js";
2
+ import { stringifyYaml } from "../harness-yaml.js";
3
3
 
4
4
  /** Canonical YAML for plan_packet (same shape as plan-packet.yaml on disk). */
5
5
  export function formatPlanPacketYaml(packet: PlanPacketLike): string {