ultimate-pi 0.18.0 → 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 (314) hide show
  1. package/.agents/skills/harness-debate-plan/SKILL.md +1 -1
  2. package/.agents/skills/harness-decisions/SKILL.md +2 -3
  3. package/.agents/skills/harness-governor/SKILL.md +6 -5
  4. package/.agents/skills/harness-orchestration/SKILL.md +4 -4
  5. package/.agents/skills/harness-review/SKILL.md +7 -7
  6. package/.agents/skills/harness-sentrux-setup/SKILL.md +4 -3
  7. package/.agents/skills/harness-steer/SKILL.md +1 -1
  8. package/.agents/skills/sentrux/SKILL.md +9 -9
  9. package/.pi/PACKAGING.md +4 -4
  10. package/.pi/SYSTEM.md +54 -120
  11. package/.pi/agents/harness/incident-recorder.md +0 -1
  12. package/.pi/agents/harness/planning/decompose.md +1 -3
  13. package/.pi/agents/harness/planning/execution-plan-author.md +0 -2
  14. package/.pi/agents/harness/planning/hypothesis-validator.md +0 -2
  15. package/.pi/agents/harness/planning/hypothesis.md +0 -2
  16. package/.pi/agents/harness/planning/implementation-researcher.md +0 -2
  17. package/.pi/agents/harness/planning/plan-adversary.md +0 -2
  18. package/.pi/agents/harness/planning/plan-evaluator.md +1 -3
  19. package/.pi/agents/harness/planning/planning-context.md +0 -2
  20. package/.pi/agents/harness/planning/review-integrator.md +0 -2
  21. package/.pi/agents/harness/planning/sprint-contract-auditor.md +0 -2
  22. package/.pi/agents/harness/planning/stack-researcher.md +0 -2
  23. package/.pi/agents/harness/{adversary.md → reviewing/adversary.md} +0 -2
  24. package/.pi/agents/harness/{evaluator.md → reviewing/evaluator.md} +0 -2
  25. package/.pi/agents/harness/{tie-breaker.md → reviewing/tie-breaker.md} +0 -2
  26. package/.pi/agents/harness/{executor.md → running/executor.md} +0 -2
  27. package/.pi/agents/harness/sentrux-bootstrap.md +0 -1
  28. package/.pi/agents/harness/sentrux-steward.md +0 -2
  29. package/.pi/agents/harness/trace-librarian.md +0 -1
  30. package/.pi/extensions/00-harness-project-control.ts +133 -0
  31. package/.pi/extensions/00-posthog-network-bootstrap.ts +1 -1
  32. package/.pi/extensions/agt-kill-switch.ts +57 -0
  33. package/.pi/extensions/agt-prompt-guard.ts +32 -0
  34. package/.pi/extensions/budget-guard.ts +2 -0
  35. package/.pi/extensions/custom-footer.ts +46 -145
  36. package/.pi/extensions/custom-header.ts +1 -1
  37. package/.pi/extensions/custom-system-prompt.ts +1 -1
  38. package/.pi/extensions/debate-orchestrator.ts +7 -5
  39. package/.pi/extensions/harness-ask-user.ts +8 -8
  40. package/.pi/extensions/harness-debate-tools.ts +27 -43
  41. package/.pi/extensions/harness-lens.ts +94 -0
  42. package/.pi/extensions/harness-live-widget.ts +33 -2
  43. package/.pi/extensions/harness-plan-approval.ts +12 -12
  44. package/.pi/extensions/harness-run-context.ts +1214 -852
  45. package/.pi/extensions/harness-subagent-governance.ts +8 -0
  46. package/.pi/extensions/harness-subagent-submit.ts +36 -164
  47. package/.pi/extensions/harness-subagents.ts +4 -4
  48. package/.pi/extensions/harness-telemetry.ts +3 -1
  49. package/.pi/extensions/harness-web-tools.ts +3 -3
  50. package/.pi/extensions/observation-bus.ts +2 -0
  51. package/.pi/extensions/policy-gate.ts +27 -5
  52. package/.pi/extensions/review-integrity.ts +91 -10
  53. package/.pi/extensions/sentrux-rules-sync.ts +3 -1
  54. package/.pi/extensions/subagent-governance.ts +92 -0
  55. package/.pi/extensions/test-diff-integrity.ts +1 -0
  56. package/.pi/extensions/trace-recorder.ts +3 -1
  57. package/.pi/extensions/{ultimate-pi-vcc.ts → vcc-compaction.ts} +1 -1
  58. package/.pi/harness/README.md +6 -2
  59. package/.pi/harness/agents.manifest.json +38 -49
  60. package/.pi/harness/agents.policy.yaml +275 -0
  61. package/.pi/harness/corpus/graphify-kb-updater.config.json +55 -0
  62. package/.pi/harness/docs/adrs/0006-sentrux-dual-layer.md +2 -1
  63. package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +1 -1
  64. package/.pi/harness/docs/adrs/0035-plan-phase-review-gate.md +1 -1
  65. package/.pi/harness/docs/adrs/0044-harness-steer-loop.md +3 -2
  66. package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
  67. package/.pi/harness/docs/adrs/0045-phase-scoped-agent-directories.md +33 -0
  68. package/.pi/harness/docs/adrs/0046-agt-policy-engine.md +51 -0
  69. package/.pi/harness/docs/adrs/0047-agt-layered-security.md +39 -0
  70. package/.pi/harness/docs/adrs/0048-tool-call-hook-order.md +25 -0
  71. package/.pi/harness/docs/adrs/0049-agents-policy-manifest.md +36 -0
  72. package/.pi/harness/docs/adrs/README.md +6 -0
  73. package/.pi/harness/docs/graphify-kb-updater-runbook.md +11 -5
  74. package/.pi/harness/docs/practice-map.md +2 -2
  75. package/.pi/harness/evolution/README.md +1 -2
  76. package/.pi/harness/examples/agents.policy.project.yaml +19 -0
  77. package/.pi/harness/examples/policies/custom-deny-bash.yaml +9 -0
  78. package/.pi/harness/policies/bash-denylists.yaml +5 -0
  79. package/.pi/harness/policies/defaults.yaml +51 -0
  80. package/.pi/harness/policies/orchestrator.yaml +18 -0
  81. package/.pi/harness/policies/phases.yaml +10 -0
  82. package/.pi/harness/policies/roles.yaml +5 -0
  83. package/.pi/harness/policies/web-guard.yaml +5 -0
  84. package/.pi/harness/policies/workflow-sequences.yaml +9 -0
  85. package/.pi/harness/sentrux/architecture.manifest.json +26 -4
  86. package/.pi/harness/specs/harness-spawn-context.schema.json +1 -1
  87. package/.pi/harness/specs/observation.schema.json +2 -1
  88. package/.pi/lib/agents-policy.d.mts +70 -0
  89. package/.pi/lib/agents-policy.mjs +325 -0
  90. package/.pi/lib/agents-policy.ts +19 -0
  91. package/.pi/lib/agt/audit-run-sink.ts +52 -0
  92. package/.pi/lib/agt/build-evaluation-context.ts +285 -0
  93. package/.pi/lib/agt/config.ts +28 -0
  94. package/.pi/lib/agt/delegation.ts +69 -0
  95. package/.pi/lib/agt/evaluate-policy.ts +56 -0
  96. package/.pi/lib/agt/identity-registry.ts +41 -0
  97. package/.pi/lib/agt/index.ts +55 -0
  98. package/.pi/lib/agt/kill-switch-state.ts +11 -0
  99. package/.pi/lib/agt/legacy-evaluate.ts +101 -0
  100. package/.pi/lib/agt/policy-engine.ts +154 -0
  101. package/.pi/lib/agt/rings.ts +21 -0
  102. package/.pi/lib/agt/sre-hooks.ts +45 -0
  103. package/.pi/lib/agt/trust-run-store.ts +26 -0
  104. package/.pi/lib/agt/workflow-history.ts +29 -0
  105. package/.pi/lib/agt-governance-active.ts +14 -0
  106. package/.pi/lib/agt-tool-guard.ts +78 -0
  107. package/.pi/lib/ask-user/dialog.ts +314 -0
  108. package/.pi/{extensions/lib → lib}/debate-bus-core.ts +10 -10
  109. package/.pi/{extensions/lib → lib}/debate-bus-state.ts +1 -1
  110. package/.pi/{extensions/lib → lib}/extension-load-guard.ts +21 -0
  111. package/.pi/lib/harness-agt-tool-guard.ts +5 -0
  112. package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +6 -16
  113. package/.pi/lib/harness-debate-core-deps.ts +14 -0
  114. package/.pi/lib/harness-debate-workflow-deps.ts +43 -0
  115. package/.pi/lib/harness-lens/.gitattributes +1 -0
  116. package/.pi/lib/harness-lens/clients/edit-autopatch.ts +88 -0
  117. package/.pi/lib/harness-lens/clients/file-kinds.ts +380 -0
  118. package/.pi/lib/harness-lens/clients/file-time.ts +215 -0
  119. package/.pi/lib/harness-lens/clients/file-utils.ts +484 -0
  120. package/.pi/lib/harness-lens/clients/format-service.ts +276 -0
  121. package/.pi/lib/harness-lens/clients/formatters.ts +1000 -0
  122. package/.pi/lib/harness-lens/clients/git-guard.ts +31 -0
  123. package/.pi/lib/harness-lens/clients/indent-retarget.ts +90 -0
  124. package/.pi/lib/harness-lens/clients/installer/index.ts +2368 -0
  125. package/.pi/lib/harness-lens/clients/latency-logger.ts +80 -0
  126. package/.pi/lib/harness-lens/clients/lens-config.ts +43 -0
  127. package/.pi/lib/harness-lens/clients/lens-events.ts +164 -0
  128. package/.pi/lib/harness-lens/clients/lsp/aggregation.ts +91 -0
  129. package/.pi/lib/harness-lens/clients/lsp/client.ts +1466 -0
  130. package/.pi/lib/harness-lens/clients/lsp/config.ts +216 -0
  131. package/.pi/lib/harness-lens/clients/lsp/edits.ts +297 -0
  132. package/.pi/lib/harness-lens/clients/lsp/index.ts +1355 -0
  133. package/.pi/lib/harness-lens/clients/lsp/interactive-install.ts +424 -0
  134. package/.pi/lib/harness-lens/clients/lsp/language.ts +223 -0
  135. package/.pi/lib/harness-lens/clients/lsp/launch.ts +939 -0
  136. package/.pi/lib/harness-lens/clients/lsp/lsp-index.ts +11 -0
  137. package/.pi/lib/harness-lens/clients/lsp/path-utils.ts +12 -0
  138. package/.pi/lib/harness-lens/clients/lsp/server-strategies.ts +81 -0
  139. package/.pi/lib/harness-lens/clients/lsp/server.ts +1971 -0
  140. package/.pi/lib/harness-lens/clients/path-utils.ts +182 -0
  141. package/.pi/lib/harness-lens/clients/pipeline.ts +360 -0
  142. package/.pi/lib/harness-lens/clients/project-profile.ts +117 -0
  143. package/.pi/lib/harness-lens/clients/runtime-agent-end.ts +112 -0
  144. package/.pi/lib/harness-lens/clients/runtime-config.ts +33 -0
  145. package/.pi/lib/harness-lens/clients/runtime-coordinator.ts +186 -0
  146. package/.pi/lib/harness-lens/clients/runtime-tool-result.ts +171 -0
  147. package/.pi/lib/harness-lens/clients/safe-spawn.ts +339 -0
  148. package/.pi/lib/harness-lens/clients/secrets-scanner.ts +214 -0
  149. package/.pi/lib/harness-lens/clients/tool-policy.ts +2072 -0
  150. package/.pi/lib/harness-lens/clients/types.ts +59 -0
  151. package/.pi/lib/harness-lens/clients/widget-state.ts +283 -0
  152. package/.pi/lib/harness-lens/index.ts +532 -0
  153. package/.pi/lib/harness-lens/tools/lsp-diagnostics.ts +706 -0
  154. package/.pi/lib/harness-lens/tools/lsp-navigation.ts +1246 -0
  155. package/.pi/{extensions/lib → lib}/harness-posthog.ts +3 -0
  156. package/.pi/lib/harness-project-config.ts +91 -0
  157. package/.pi/lib/harness-run-context-responses.ts +9 -0
  158. package/.pi/lib/harness-run-context.ts +1 -3
  159. package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +4 -3
  160. package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +5 -28
  161. package/.pi/lib/harness-subagent-auth.ts +51 -0
  162. package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +13 -10
  163. package/.pi/{extensions/lib → lib}/harness-subagent-submit-pipeline.ts +3 -3
  164. package/.pi/lib/harness-subagent-submit-register.ts +163 -0
  165. package/.pi/{extensions/lib → lib}/harness-subagent-submit-registry.ts +1 -55
  166. package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +53 -14
  167. package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
  168. package/.pi/lib/harness-ui-state.ts +27 -12
  169. package/.pi/{extensions/lib → lib}/plan-approval/create-plan.ts +2 -2
  170. package/.pi/{extensions/lib → lib}/plan-approval/format-plan.ts +2 -2
  171. package/.pi/{extensions/lib → lib}/plan-approval/plan-review.ts +162 -201
  172. package/.pi/{extensions/lib → lib}/plan-approval/render.ts +1 -1
  173. package/.pi/{extensions/lib → lib}/plan-approval/resolve-disk.ts +2 -2
  174. package/.pi/{extensions/lib → lib}/plan-approval/types.ts +1 -1
  175. package/.pi/{extensions/lib → lib}/plan-approval/validate.ts +3 -3
  176. package/.pi/{extensions/lib → lib}/plan-approval-readiness.ts +3 -52
  177. package/.pi/{extensions/lib → lib}/plan-debate-envelope.ts +1 -1
  178. package/.pi/{extensions/lib → lib}/plan-debate-gate.ts +1 -1
  179. package/.pi/{extensions/lib → lib}/plan-debate-lane.ts +1 -4
  180. package/.pi/{extensions/lib → lib}/plan-messenger.ts +1 -1
  181. package/.pi/prompts/harness-auto.md +2 -2
  182. package/.pi/prompts/harness-plan.md +4 -6
  183. package/.pi/prompts/harness-review.md +9 -9
  184. package/.pi/prompts/harness-run.md +7 -7
  185. package/.pi/prompts/harness-setup.md +42 -68
  186. package/.pi/prompts/harness-steer.md +2 -2
  187. package/.pi/scripts/README.md +3 -5
  188. package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
  189. package/.pi/scripts/graphify-kb-updater.mjs +48 -8
  190. package/.pi/scripts/harness-agents-manifest.mjs +61 -4
  191. package/.pi/scripts/harness-agt-doctor.ts +36 -0
  192. package/.pi/scripts/harness-cli-verify.sh +9 -2
  193. package/.pi/scripts/harness-project-toggle.mjs +129 -0
  194. package/.pi/scripts/harness-sentrux-cli.mjs +142 -0
  195. package/.pi/scripts/harness-verify.mjs +113 -39
  196. package/.pi/scripts/harness-web-policy-guard.mjs +2 -2
  197. package/.pi/scripts/validate-plan-dag.mjs +65 -74
  198. package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +2 -2
  199. package/.pi/scripts/vendor-sync-pi-vcc.sh +1 -1
  200. package/.pi/skills/architecture/broker-domain/SKILL.md +65 -0
  201. package/.pi/skills/architecture/cqrs/SKILL.md +63 -0
  202. package/.pi/skills/architecture/event-driven/SKILL.md +60 -0
  203. package/.pi/skills/architecture/hexagonal-ports-adapters/SKILL.md +66 -0
  204. package/.pi/skills/architecture/layered/SKILL.md +68 -0
  205. package/.pi/skills/architecture/microkernel/SKILL.md +62 -0
  206. package/.pi/skills/architecture/microservices/SKILL.md +64 -0
  207. package/.pi/skills/architecture/modular-monolith/SKILL.md +65 -0
  208. package/.pi/skills/architecture/orchestration-driven-soa/SKILL.md +61 -0
  209. package/.pi/skills/architecture/pipeline/SKILL.md +63 -0
  210. package/.pi/skills/architecture/service-based/SKILL.md +64 -0
  211. package/.pi/skills/architecture/service-mesh/SKILL.md +60 -0
  212. package/.pi/skills/architecture/space-based/SKILL.md +60 -0
  213. package/.pi/skills/ast-grep/SKILL.md +40 -321
  214. package/.pi/skills/delivery/debugging-discipline/SKILL.md +36 -0
  215. package/.pi/skills/delivery/documentation-update/SKILL.md +33 -0
  216. package/.pi/skills/delivery/requirements-to-implementation/SKILL.md +34 -0
  217. package/.pi/skills/delivery/risk-based-verification/SKILL.md +43 -0
  218. package/.pi/skills/delivery/tradeoff-analysis/SKILL.md +34 -0
  219. package/.pi/skills/engineering/api-contract-design/SKILL.md +38 -0
  220. package/.pi/skills/engineering/cohesion-coupling/SKILL.md +43 -0
  221. package/.pi/skills/engineering/complexity-control/SKILL.md +31 -0
  222. package/.pi/skills/engineering/defensive-programming/SKILL.md +38 -0
  223. package/.pi/skills/engineering/dependency-management/SKILL.md +29 -0
  224. package/.pi/skills/engineering/domain-modeling/SKILL.md +32 -0
  225. package/.pi/skills/engineering/error-handling/SKILL.md +37 -0
  226. package/.pi/skills/engineering/legacy-code-seams/SKILL.md +35 -0
  227. package/.pi/skills/engineering/naming-and-intent/SKILL.md +29 -0
  228. package/.pi/skills/engineering/refactoring-safe-evolution/SKILL.md +35 -0
  229. package/.pi/skills/engineering/routine-function-design/SKILL.md +34 -0
  230. package/.pi/skills/engineering/small-change-discipline/SKILL.md +35 -0
  231. package/.pi/skills/lsp-navigation/SKILL.md +89 -0
  232. package/.pi/skills/quality/code-review-self-check/SKILL.md +35 -0
  233. package/.pi/skills/quality/privacy-data-handling/SKILL.md +26 -0
  234. package/.pi/skills/quality/security-review/SKILL.md +34 -0
  235. package/.pi/skills/quality/test-strategy/SKILL.md +33 -0
  236. package/.pi/skills/quality/testability-design/SKILL.md +33 -0
  237. package/.pi/skills/systems/concurrency-safety/SKILL.md +32 -0
  238. package/.pi/skills/systems/data-modeling-migrations/SKILL.md +31 -0
  239. package/.pi/skills/systems/observability-instrumentation/SKILL.md +32 -0
  240. package/.pi/skills/systems/performance-measurement/SKILL.md +35 -0
  241. package/.pi/skills/systems/reliability-design/SKILL.md +32 -0
  242. package/.sentrux/rules.toml +20 -4
  243. package/AGENTS.md +5 -0
  244. package/CHANGELOG.md +26 -0
  245. package/README.md +85 -58
  246. package/THIRD_PARTY_NOTICES.md +12 -21
  247. package/package.json +15 -7
  248. package/vendor/pi-subagents/src/agents.ts +45 -1
  249. package/vendor/pi-subagents/src/subagents.ts +866 -811
  250. package/vendor/pi-vcc/src/core/brief.ts +68 -99
  251. package/vendor/pi-vcc/src/core/settings.ts +2 -2
  252. package/.agents/skills/caveman/SKILL.md +0 -67
  253. package/.pi/agents/harness/meta-optimizer.md +0 -36
  254. package/.pi/agents/harness/planning/scout-graphify.md +0 -39
  255. package/.pi/agents/harness/planning/scout-semantic.md +0 -41
  256. package/.pi/agents/harness/planning/scout-structure.md +0 -37
  257. package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
  258. package/.pi/extensions/lib/harness-subagent-auth.ts +0 -209
  259. package/.pi/extensions/lib/harness-subagent-policy.ts +0 -236
  260. package/.pi/extensions/pi-model-router-harness.ts +0 -42
  261. package/.pi/harness/evolution/meta-optimizer.mjs +0 -99
  262. package/.pi/harness/specs/router-tuning-proposal.schema.json +0 -114
  263. package/.pi/model-router.example.json +0 -36
  264. package/.pi/prompts/harness-critic.md +0 -10
  265. package/.pi/prompts/harness-eval.md +0 -10
  266. package/.pi/prompts/harness-router-tune.md +0 -52
  267. package/.pi/scripts/harness-generate-model-router.mjs +0 -327
  268. package/.pi/scripts/harness-model-router-routing.test.mjs +0 -97
  269. package/.pi/scripts/harness-sync-model-router.mjs +0 -97
  270. package/.pi/scripts/vendor-sync-pi-model-router.sh +0 -47
  271. package/vendor/pi-model-router/.prettierignore +0 -4
  272. package/vendor/pi-model-router/.prettierrc +0 -5
  273. package/vendor/pi-model-router/AGENTS.md +0 -39
  274. package/vendor/pi-model-router/LICENSE +0 -21
  275. package/vendor/pi-model-router/README.md +0 -99
  276. package/vendor/pi-model-router/UPSTREAM_PIN.md +0 -10
  277. package/vendor/pi-model-router/docs/ARCHITECTURE.md +0 -54
  278. package/vendor/pi-model-router/extensions/commands.ts +0 -720
  279. package/vendor/pi-model-router/extensions/config.ts +0 -348
  280. package/vendor/pi-model-router/extensions/constants.ts +0 -1
  281. package/vendor/pi-model-router/extensions/index.ts +0 -478
  282. package/vendor/pi-model-router/extensions/provider.ts +0 -580
  283. package/vendor/pi-model-router/extensions/routing.ts +0 -564
  284. package/vendor/pi-model-router/extensions/state.ts +0 -52
  285. package/vendor/pi-model-router/extensions/types.ts +0 -95
  286. package/vendor/pi-model-router/extensions/ui.ts +0 -144
  287. package/vendor/pi-model-router/model-router.example.json +0 -48
  288. package/vendor/pi-model-router/package.json +0 -48
  289. package/vendor/pi-model-router/tsconfig.json +0 -16
  290. /package/.pi/{prompts → harness/docs}/planning-rubrics.md +0 -0
  291. /package/.pi/{extensions/lib → lib}/ask-user/fallback.ts +0 -0
  292. /package/.pi/{extensions/lib → lib}/ask-user/render.ts +0 -0
  293. /package/.pi/{extensions/lib → lib}/ask-user/schema.ts +0 -0
  294. /package/.pi/{extensions/lib → lib}/ask-user/types.ts +0 -0
  295. /package/.pi/{extensions/lib → lib}/ask-user/validate-core.mjs +0 -0
  296. /package/.pi/{extensions/lib → lib}/ask-user/validate.ts +0 -0
  297. /package/.pi/{extensions/lib → lib}/harness-cocoindex-refresh.ts +0 -0
  298. /package/.pi/{extensions/lib → lib}/harness-paths.ts +0 -0
  299. /package/.pi/{extensions/lib → lib}/harness-spawn-budget.ts +0 -0
  300. /package/.pi/{extensions/lib → lib}/harness-vcc-settings.ts +0 -0
  301. /package/.pi/{extensions/lib → lib}/harness-web/run-cli.ts +0 -0
  302. /package/.pi/{extensions/lib → lib}/plan-approval/dialog.ts +0 -0
  303. /package/.pi/{extensions/lib → lib}/plan-approval/schema.ts +0 -0
  304. /package/.pi/{extensions/lib → lib}/plan-debate-eligibility.ts +0 -0
  305. /package/.pi/{extensions/lib → lib}/plan-debate-focus.ts +0 -0
  306. /package/.pi/{extensions/lib → lib}/plan-debate-id.ts +0 -0
  307. /package/.pi/{extensions/lib → lib}/plan-debate-lanes.ts +0 -0
  308. /package/.pi/{extensions/lib → lib}/plan-debate-round-status.ts +0 -0
  309. /package/.pi/{extensions/lib → lib}/plan-debate-write-guard.ts +0 -0
  310. /package/.pi/{extensions/lib → lib}/plan-review-gate.ts +0 -0
  311. /package/.pi/{extensions/lib → lib}/plan-review-integrator-rules.ts +0 -0
  312. /package/.pi/{extensions/lib → lib}/plan-scope-guard.ts +0 -0
  313. /package/.pi/{extensions/lib → lib}/posthog-client.ts +0 -0
  314. /package/.pi/{extensions/lib → lib}/posthog-node.d.ts +0 -0
@@ -0,0 +1,325 @@
1
+ /**
2
+ * agents.policy.yaml loader — package + project merge (SSOT for agent tools).
3
+ */
4
+
5
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
6
+ import { join, dirname } from "node:path";
7
+ import { parse as parseYaml } from "yaml";
8
+
9
+ const BUILTIN_DENY_TOOLS = new Set([
10
+ "subagent",
11
+ "Agent",
12
+ "get_subagent_result",
13
+ "steer_subagent",
14
+ "blackboard",
15
+ ]);
16
+
17
+ const PLANNING_BASH_DENY_PATTERNS = [
18
+ /\bgraphify\s+update\b/i,
19
+ /\bgraphify\s+extract\b/i,
20
+ /\bgraphify\s+install\b/i,
21
+ /\bccc\s+(index|init|reset|daemon)\b/i,
22
+ /\bccc\s+search\b.*--refresh/i,
23
+ /\bpip\s+install\b/i,
24
+ /\buv\s+tool\s+install\b/i,
25
+ /\bnpm\s+install\b/i,
26
+ ];
27
+
28
+ const PLANNING_ARTIFACT_JSON_WRITE = /artifacts\/[^\s'"`;]+\.json\b/i;
29
+
30
+ const MUTATING_TOOLS = new Set(["write", "edit"]);
31
+
32
+ const cache = new Map();
33
+
34
+ export function packageAgentsPolicyPath(packageRoot) {
35
+ return join(packageRoot, ".pi", "harness", "agents.policy.yaml");
36
+ }
37
+
38
+ export function projectAgentsPolicyPath(projectRoot) {
39
+ return join(projectRoot, ".pi", "agents.policy.yaml");
40
+ }
41
+
42
+ export function projectPoliciesDir(projectRoot) {
43
+ return join(projectRoot, ".pi", "policies");
44
+ }
45
+
46
+ function readYamlFile(path) {
47
+ if (!existsSync(path)) return null;
48
+ try {
49
+ return parseYaml(readFileSync(path, "utf8"));
50
+ } catch {
51
+ return null;
52
+ }
53
+ }
54
+
55
+ function normalizeKindEntry(raw) {
56
+ if (!raw || typeof raw !== "object") return null;
57
+ const tools = Array.isArray(raw.tools) ? raw.tools.map(String) : [];
58
+ return {
59
+ tools,
60
+ extensions: raw.extensions === false ? false : Boolean(raw.extensions),
61
+ readOnly: raw.read_only === true,
62
+ maxTurns:
63
+ typeof raw.max_turns === "number" && raw.max_turns > 0
64
+ ? raw.max_turns
65
+ : undefined,
66
+ thinking:
67
+ typeof raw.thinking === "string" && raw.thinking.trim()
68
+ ? raw.thinking.trim()
69
+ : undefined,
70
+ };
71
+ }
72
+
73
+ function normalizeAgentEntry(raw) {
74
+ if (!raw || typeof raw !== "object") return {};
75
+ const toolsAdd = Array.isArray(raw.tools_add)
76
+ ? raw.tools_add.map(String)
77
+ : Array.isArray(raw.tools)
78
+ ? raw.tools.map(String)
79
+ : [];
80
+ return {
81
+ kind: typeof raw.kind === "string" ? raw.kind.trim() : undefined,
82
+ toolsAdd,
83
+ toolsDeny: Array.isArray(raw.tools_deny)
84
+ ? raw.tools_deny.map(String)
85
+ : [],
86
+ submitTool:
87
+ typeof raw.submit_tool === "string" ? raw.submit_tool.trim() : undefined,
88
+ extensions:
89
+ raw.extensions === false
90
+ ? false
91
+ : raw.extensions === true
92
+ ? true
93
+ : undefined,
94
+ maxTurns:
95
+ typeof raw.max_turns === "number" && raw.max_turns > 0
96
+ ? raw.max_turns
97
+ : undefined,
98
+ thinking:
99
+ typeof raw.thinking === "string" && raw.thinking.trim()
100
+ ? raw.thinking.trim()
101
+ : undefined,
102
+ };
103
+ }
104
+
105
+ export function loadAgentsPolicyMerged(packageRoot, projectRoot) {
106
+ const key = `${packageRoot}\0${projectRoot}`;
107
+ if (cache.has(key)) return cache.get(key);
108
+
109
+ const pkgDoc = readYamlFile(packageAgentsPolicyPath(packageRoot)) ?? {};
110
+ const projDoc = readYamlFile(projectAgentsPolicyPath(projectRoot)) ?? {};
111
+
112
+ const kinds = new Map();
113
+ for (const [name, raw] of Object.entries(pkgDoc.kinds ?? {})) {
114
+ const k = normalizeKindEntry(raw);
115
+ if (k) kinds.set(name, k);
116
+ }
117
+ for (const [name, raw] of Object.entries(projDoc.kinds ?? {})) {
118
+ const k = normalizeKindEntry(raw);
119
+ if (k) kinds.set(name, k);
120
+ }
121
+
122
+ const agents = new Map();
123
+ for (const [id, raw] of Object.entries(pkgDoc.agents ?? {})) {
124
+ agents.set(id, normalizeAgentEntry(raw));
125
+ }
126
+ for (const [id, raw] of Object.entries(projDoc.agents ?? {})) {
127
+ const prev = agents.get(id) ?? {};
128
+ const next = normalizeAgentEntry(raw);
129
+ agents.set(id, {
130
+ ...prev,
131
+ ...next,
132
+ toolsAdd: [...new Set([...(prev.toolsAdd ?? []), ...(next.toolsAdd ?? [])])],
133
+ toolsDeny: [...new Set([...(prev.toolsDeny ?? []), ...(next.toolsDeny ?? [])])],
134
+ });
135
+ }
136
+
137
+ const merged = {
138
+ schemaVersion: String(pkgDoc.apiVersion ?? projDoc.apiVersion ?? "harness.toolkit/v1"),
139
+ kinds,
140
+ agents,
141
+ defaults: normalizeAgentEntry(projDoc.defaults ?? pkgDoc.defaults ?? {}),
142
+ };
143
+ cache.set(key, merged);
144
+ return merged;
145
+ }
146
+
147
+ export function resolveEffectiveTools(agentId, merged) {
148
+ const entry = merged.agents.get(agentId) ?? merged.defaults;
149
+ const kindName = entry.kind ?? "other";
150
+ const kind = merged.kinds.get(kindName) ?? merged.kinds.get("other") ?? {
151
+ tools: ["read", "grep", "find", "ls"],
152
+ extensions: false,
153
+ readOnly: true,
154
+ };
155
+
156
+ const base = new Set(kind.tools);
157
+ for (const t of entry.toolsAdd ?? []) base.add(t);
158
+ for (const t of entry.toolsDeny ?? []) base.delete(t);
159
+ for (const t of BUILTIN_DENY_TOOLS) base.delete(t);
160
+
161
+ return {
162
+ kind: kindName,
163
+ effectiveTools: [...base],
164
+ extensionsOff: entry.extensions === true ? false : entry.extensions === false ? true : !kind.extensions,
165
+ readOnly: kind.readOnly,
166
+ maxTurns: entry.maxTurns ?? kind.maxTurns,
167
+ thinking: entry.thinking ?? kind.thinking,
168
+ submitTool: entry.submitTool,
169
+ };
170
+ }
171
+
172
+ export function getAgentPolicySpec(packageRoot, projectRoot, agentId) {
173
+ const merged = loadAgentsPolicyMerged(packageRoot, projectRoot);
174
+ if (!merged.agents.has(agentId) && !merged.defaults?.kind) {
175
+ return null;
176
+ }
177
+ return resolveEffectiveTools(agentId, merged);
178
+ }
179
+
180
+ export function getAgentKind(packageRoot, projectRoot, agentId) {
181
+ const spec = getAgentPolicySpec(packageRoot, projectRoot, agentId);
182
+ if (spec) return spec.kind;
183
+ if (agentId.startsWith("harness/planning/")) return "planner";
184
+ if (agentId === "harness/running/executor") return "executor";
185
+ if (agentId === "harness/reviewing/evaluator") return "evaluator";
186
+ if (agentId === "harness/reviewing/adversary") return "adversary";
187
+ if (agentId === "harness/reviewing/tie-breaker") return "tie_breaker";
188
+ if (agentId === "harness/meta-optimizer") return "meta";
189
+ if (agentId === "harness/trace-librarian") return "trace";
190
+ if (agentId === "harness/incident-recorder") return "incident";
191
+ return "other";
192
+ }
193
+
194
+ export function isHarnessPlanningAgent(agentId) {
195
+ return agentId.startsWith("harness/planning/");
196
+ }
197
+
198
+ export function harnessSubagentPhaseHint(packageRoot, projectRoot, agentId) {
199
+ if (isHarnessPlanningAgent(agentId)) return "plan";
200
+ const kind = getAgentKind(packageRoot, projectRoot, agentId);
201
+ switch (kind) {
202
+ case "planner":
203
+ return "plan";
204
+ case "executor":
205
+ return "execute";
206
+ case "evaluator":
207
+ return "evaluate";
208
+ case "adversary":
209
+ return "adversary";
210
+ default:
211
+ return null;
212
+ }
213
+ }
214
+
215
+ function isMutatingBash(command) {
216
+ if (!command) return false;
217
+ return /\b(rm\s+-rf|git\s+(push|commit|reset|checkout|merge|rebase)|npm\s+run|make\b|docker\s+)/i.test(
218
+ command,
219
+ );
220
+ }
221
+
222
+ /**
223
+ * Manifest allowlist + subprocess constraints (replaces harness-subagent-policy.ts).
224
+ */
225
+ export function allowsAgentTool(input) {
226
+ const {
227
+ packageRoot,
228
+ projectRoot,
229
+ agentId,
230
+ toolName,
231
+ toolInput = {},
232
+ isSubprocess = false,
233
+ isParentOrchestrator = false,
234
+ } = input;
235
+
236
+ if (isParentOrchestrator) {
237
+ if (toolName.startsWith("submit_")) return false;
238
+ return true;
239
+ }
240
+
241
+ const spec = getAgentPolicySpec(packageRoot, projectRoot, agentId);
242
+ if (!spec) return false;
243
+
244
+ if (!spec.effectiveTools.includes(toolName)) return false;
245
+
246
+ if (toolName.startsWith("submit_")) {
247
+ if (!isSubprocess) return false;
248
+ if (toolName === "submit_human_required" && agentId === "harness/running/executor") {
249
+ return false;
250
+ }
251
+ }
252
+
253
+ if (MUTATING_TOOLS.has(toolName) && spec.readOnly) return false;
254
+
255
+ if (toolName === "ctx_batch_execute" && spec.readOnly) {
256
+ const commands = toolInput.commands;
257
+ if (Array.isArray(commands)) {
258
+ for (const c of commands) {
259
+ const cmd =
260
+ typeof c === "string"
261
+ ? c
262
+ : String(c?.command ?? c?.code ?? "");
263
+ if (cmd && isMutatingBash(cmd)) return false;
264
+ }
265
+ }
266
+ }
267
+
268
+ if (toolName === "ctx_execute" && spec.readOnly) {
269
+ const code = String(toolInput.code ?? toolInput.command ?? "");
270
+ if (code && isMutatingBash(code)) return false;
271
+ }
272
+
273
+ if (toolName === "bash" && spec.readOnly) {
274
+ const command = String(toolInput.command ?? "");
275
+ if (command && isMutatingBash(command)) return false;
276
+ if (
277
+ isHarnessPlanningAgent(agentId) &&
278
+ command &&
279
+ PLANNING_ARTIFACT_JSON_WRITE.test(command)
280
+ ) {
281
+ return false;
282
+ }
283
+ if (
284
+ isHarnessPlanningAgent(agentId) &&
285
+ command &&
286
+ PLANNING_BASH_DENY_PATTERNS.some((p) => p.test(command))
287
+ ) {
288
+ return false;
289
+ }
290
+ }
291
+
292
+ return true;
293
+ }
294
+
295
+ export function applyAgentPolicyToConfig(agent, packageRoot, projectRoot) {
296
+ const spec = getAgentPolicySpec(packageRoot, projectRoot, agent.name);
297
+ if (!spec) return agent;
298
+ return {
299
+ ...agent,
300
+ tools: spec.effectiveTools.length > 0 ? spec.effectiveTools : undefined,
301
+ extensionsOff: spec.extensionsOff,
302
+ maxTurns: spec.maxTurns ?? agent.maxTurns,
303
+ thinking: spec.thinking ?? agent.thinking,
304
+ };
305
+ }
306
+
307
+ export function findProjectRootFromAgentsDir(projectAgentsDir) {
308
+ if (!projectAgentsDir) return process.cwd();
309
+ const piDir = dirname(projectAgentsDir);
310
+ if (piDir.endsWith("/.pi") || piDir.endsWith("\\.pi")) {
311
+ return dirname(piDir);
312
+ }
313
+ return process.cwd();
314
+ }
315
+
316
+ export function isAgtGovernanceActive(projectRoot) {
317
+ if (existsSync(projectAgentsPolicyPath(projectRoot))) return true;
318
+ const polDir = projectPoliciesDir(projectRoot);
319
+ if (!existsSync(polDir)) return false;
320
+ try {
321
+ return readdirSync(polDir).some((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
322
+ } catch {
323
+ return false;
324
+ }
325
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * agents.policy.yaml — TypeScript surface (implementation in agents-policy.mjs).
3
+ */
4
+
5
+ export {
6
+ allowsAgentTool,
7
+ applyAgentPolicyToConfig,
8
+ findProjectRootFromAgentsDir,
9
+ getAgentKind,
10
+ getAgentPolicySpec,
11
+ harnessSubagentPhaseHint,
12
+ isAgtGovernanceActive,
13
+ isHarnessPlanningAgent,
14
+ loadAgentsPolicyMerged,
15
+ packageAgentsPolicyPath,
16
+ projectAgentsPolicyPath,
17
+ projectPoliciesDir,
18
+ resolveEffectiveTools,
19
+ } from "./agents-policy.mjs";
@@ -0,0 +1,52 @@
1
+ import { appendFileSync, mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { AuditLogger } from "@microsoft/agent-governance-sdk";
4
+
5
+ const loggers = new Map<string, AuditLogger>();
6
+
7
+ export function getAuditLoggerForRun(runDir: string): AuditLogger {
8
+ const key = runDir;
9
+ let logger = loggers.get(key);
10
+ if (!logger) {
11
+ logger = new AuditLogger();
12
+ loggers.set(key, logger);
13
+ }
14
+ return logger;
15
+ }
16
+
17
+ export function appendPolicyAuditEvent(input: {
18
+ runDir: string;
19
+ runId: string;
20
+ toolName: string;
21
+ allowed: boolean;
22
+ reason: string;
23
+ agentDid: string;
24
+ phase: string;
25
+ }): void {
26
+ const logger = getAuditLoggerForRun(input.runDir);
27
+ logger.log({
28
+ action: `tool.${input.toolName}:${input.phase}:${input.reason}`,
29
+ agentId: input.agentDid,
30
+ decision: input.allowed ? "allow" : "deny",
31
+ });
32
+ const auditPath = join(input.runDir, "agt-audit.jsonl");
33
+ mkdirSync(input.runDir, { recursive: true });
34
+ appendFileSync(
35
+ auditPath,
36
+ `${JSON.stringify({
37
+ ts: new Date().toISOString(),
38
+ run_id: input.runId,
39
+ tool: input.toolName,
40
+ allowed: input.allowed,
41
+ reason: input.reason,
42
+ agent_did: input.agentDid,
43
+ phase: input.phase,
44
+ })}\n`,
45
+ );
46
+ }
47
+
48
+ export function verifyRunAuditChain(runDir: string): boolean {
49
+ const logger = loggers.get(runDir);
50
+ if (!logger) return true;
51
+ return logger.verify();
52
+ }
@@ -0,0 +1,285 @@
1
+ import {
2
+ allowsAgentTool,
3
+ getAgentKind,
4
+ isHarnessPlanningAgent,
5
+ } from "../agents-policy.mjs";
6
+ import {
7
+ evaluateContextModeMutation,
8
+ isMutatingBash,
9
+ } from "../harness-context-mode-policy.js";
10
+ import {
11
+ extractWritePathFromToolInput,
12
+ getLatestRunContext,
13
+ type HarnessPhase,
14
+ type HarnessRunContext,
15
+ isHarnessAutoSession,
16
+ isPlanPhaseAllowedMutation,
17
+ } from "../harness-run-context.js";
18
+ import { evaluateSubagentToolCall } from "../harness-spawn-policy.js";
19
+
20
+ export interface BuildEvaluationContextInput {
21
+ toolName: string;
22
+ toolInput: Record<string, unknown>;
23
+ packageRoot: string;
24
+ projectRoot: string;
25
+ sessionId: string;
26
+ entries: unknown[];
27
+ policyState: {
28
+ phase: HarnessPhase;
29
+ approvedPlan: boolean;
30
+ planId: string | null;
31
+ aborted: boolean;
32
+ budgetBypass: boolean;
33
+ };
34
+ agentDid?: string;
35
+ }
36
+
37
+ export type HarnessAgtContext = Record<string, unknown>;
38
+
39
+ const PLANNING_BASH_DENY_PATTERNS = [
40
+ /\bgraphify\s+update\b/i,
41
+ /\bgraphify\s+extract\b/i,
42
+ /\bgraphify\s+install\b/i,
43
+ /\bccc\s+(index|init|reset|daemon)\b/i,
44
+ /\bccc\s+search\b.*--refresh/i,
45
+ /\bpip\s+install\b/i,
46
+ /\buv\s+tool\s+install\b/i,
47
+ /\bnpm\s+install\b/i,
48
+ /\bnpm\s+install\b.*cocoindex/i,
49
+ /\buv\s+tool\s+install\b.*cocoindex/i,
50
+ ];
51
+
52
+ const PLANNING_ARTIFACT_JSON_WRITE = /artifacts\/[^\s'"`;]+\.json\b/i;
53
+
54
+ const WEB_BLOCK_PATTERNS: Array<{ re: RegExp }> = [
55
+ { re: /\bfirecrawl\b/i },
56
+ { re: /\b(?:curl|wget)\b[^\n|;&]*\s+https?:\/\//i },
57
+ { re: /\bscrapling\s+(?:fetch|extract)\b/i },
58
+ ];
59
+
60
+ const WEB_ALLOW_PATTERNS = [
61
+ /harness-web\.py\b/i,
62
+ /harness-cli-verify\.sh\b/i,
63
+ /\bgraphify\b/i,
64
+ /\bctx7\b/i,
65
+ /\bcontext7\b/i,
66
+ /\bgit\b/i,
67
+ /harness-searxng-bootstrap/i,
68
+ ];
69
+
70
+ function resolveAgentId(): string {
71
+ if (process.env.PI_HARNESS_SUBPROCESS === "1") {
72
+ return process.env.HARNESS_AGENT_ID?.trim() || "harness/unknown";
73
+ }
74
+ return "parent-orchestrator";
75
+ }
76
+
77
+ export function bashWebBlocked(command: string): boolean {
78
+ if (!command) return false;
79
+ if (WEB_ALLOW_PATTERNS.some((re) => re.test(command))) return false;
80
+ return WEB_BLOCK_PATTERNS.some(({ re }) => re.test(command));
81
+ }
82
+
83
+ /** Shared session-scoped deny reasons for legacy parity and AGT context flags. */
84
+ export function harnessSessionToolDenyReason(input: {
85
+ toolName: string;
86
+ toolInput: Record<string, unknown>;
87
+ phase: HarnessPhase;
88
+ agentId: string;
89
+ entries: unknown[];
90
+ aborted: boolean;
91
+ }): string | null {
92
+ if (!isHarnessAutoSession(input.entries)) return null;
93
+ const bashCommand =
94
+ input.toolName === "bash" ? String(input.toolInput.command ?? "") : "";
95
+ if (
96
+ input.aborted &&
97
+ ((bashCommand && isMutatingBash(bashCommand)) ||
98
+ input.toolName === "write" ||
99
+ input.toolName === "edit")
100
+ ) {
101
+ return "harness-abort lock";
102
+ }
103
+ if (
104
+ bashCommand &&
105
+ isMutatingBash(bashCommand) &&
106
+ !input.aborted &&
107
+ input.phase !== "execute" &&
108
+ input.phase !== "merge"
109
+ ) {
110
+ return "mutating bash blocked outside execute/merge";
111
+ }
112
+ if (bashCommand && bashWebBlocked(bashCommand)) {
113
+ return "web/bash curl blocked (use harness web_search / web_fetch)";
114
+ }
115
+ return null;
116
+ }
117
+
118
+ function bashPlanningDenied(command: string, agentType: string): boolean {
119
+ if (!command || !isHarnessPlanningAgent(agentType)) return false;
120
+ return PLANNING_BASH_DENY_PATTERNS.some((p) => p.test(command));
121
+ }
122
+
123
+ function bashPlanningJsonDenied(command: string, agentType: string): boolean {
124
+ if (!command || !isHarnessPlanningAgent(agentType)) return false;
125
+ return PLANNING_ARTIFACT_JSON_WRITE.test(command);
126
+ }
127
+
128
+ function harnessSessionActive(entries: unknown[]): boolean {
129
+ return isHarnessAutoSession(entries);
130
+ }
131
+
132
+ export async function buildHarnessAgtEvaluationContext(
133
+ input: BuildEvaluationContextInput,
134
+ ): Promise<HarnessAgtContext> {
135
+ const agentId = resolveAgentId();
136
+ const isSubprocess = process.env.PI_HARNESS_SUBPROCESS === "1";
137
+ const isParentOrchestrator = agentId === "parent-orchestrator";
138
+ const agentKind = getAgentKind(input.packageRoot, input.projectRoot, agentId);
139
+ const runCtx = getLatestRunContext(input.entries);
140
+ const phase = input.policyState.phase;
141
+ const bashCommand =
142
+ input.toolName === "bash" ? String(input.toolInput.command ?? "") : "";
143
+ const sessionActive = harnessSessionActive(input.entries);
144
+
145
+ const MUTATING_FILE_TOOLS = new Set(["write", "edit"]);
146
+ const planMutation =
147
+ sessionActive && MUTATING_FILE_TOOLS.has(input.toolName)
148
+ ? await isPlanPhaseAllowedMutation(
149
+ input.toolName,
150
+ input.toolInput,
151
+ phase,
152
+ runCtx,
153
+ input.projectRoot,
154
+ {
155
+ aborted: input.policyState.aborted,
156
+ entries: input.entries,
157
+ ownerSessionId: runCtx?.owner_pi_session_id,
158
+ currentSessionId: input.sessionId,
159
+ },
160
+ )
161
+ : { allowed: true };
162
+
163
+ const ctxMode = sessionActive
164
+ ? evaluateContextModeMutation(input.toolName, input.toolInput, phase, {
165
+ aborted: input.policyState.aborted,
166
+ budgetBypass: input.policyState.budgetBypass,
167
+ readOnlyAgent:
168
+ agentKind === "planner" ||
169
+ agentKind === "evaluator" ||
170
+ agentKind === "adversary" ||
171
+ agentKind === "tie_breaker",
172
+ })
173
+ : { blocked: false, reason: "" };
174
+
175
+ const spawnDecision = evaluateSubagentToolCall(input.toolName, agentId);
176
+
177
+ const toolAllowed = allowsAgentTool({
178
+ packageRoot: input.packageRoot,
179
+ projectRoot: input.projectRoot,
180
+ agentId,
181
+ toolName: input.toolName,
182
+ toolInput: input.toolInput,
183
+ isSubprocess,
184
+ isParentOrchestrator,
185
+ });
186
+
187
+ let evalPlanPacketBlock = false;
188
+ if (
189
+ sessionActive &&
190
+ runCtx?.plan_packet_path &&
191
+ (phase === "evaluate" || phase === "adversary") &&
192
+ (input.toolName === "write" || input.toolName === "edit")
193
+ ) {
194
+ const target = String(
195
+ input.toolInput.path ?? input.toolInput.filePath ?? "",
196
+ );
197
+ if (target.includes("plan-packet.yaml")) {
198
+ evalPlanPacketBlock = true;
199
+ }
200
+ }
201
+
202
+ const writePath =
203
+ input.toolName === "write" || input.toolName === "edit"
204
+ ? extractWritePathFromToolInput(input.toolInput)
205
+ : null;
206
+
207
+ const mutatingBashPhaseBlock =
208
+ sessionActive &&
209
+ Boolean(bashCommand && isMutatingBash(bashCommand)) &&
210
+ !input.policyState.aborted &&
211
+ phase !== "execute" &&
212
+ phase !== "merge";
213
+
214
+ const abortMutatingBlock =
215
+ sessionActive &&
216
+ input.policyState.aborted &&
217
+ ((bashCommand && isMutatingBash(bashCommand)) ||
218
+ input.toolName === "write" ||
219
+ input.toolName === "edit");
220
+
221
+ return {
222
+ tool_name: input.toolName,
223
+ harness_phase: phase,
224
+ harness_agent_id: agentId,
225
+ harness_agent_kind: agentKind,
226
+ is_subprocess: isSubprocess,
227
+ is_parent_orchestrator: isParentOrchestrator,
228
+ harness_session_active: sessionActive,
229
+ is_harness_agent: agentId.startsWith("harness/"),
230
+ approved_plan: input.policyState.approvedPlan,
231
+ plan_ready: Boolean(runCtx?.plan_ready),
232
+ aborted: input.policyState.aborted,
233
+ budget_bypass: input.policyState.budgetBypass,
234
+ run_id: runCtx?.run_id ?? process.env.HARNESS_RUN_ID ?? "",
235
+ plan_id: input.policyState.planId ?? runCtx?.plan_id ?? "",
236
+ plan_mutation_allowed: planMutation.allowed,
237
+ plan_mutation_block: sessionActive && !planMutation.allowed,
238
+ context_mode_block: ctxMode.blocked,
239
+ tool_allowed: toolAllowed,
240
+ spawn_policy_block: spawnDecision.action === "block",
241
+ is_mutating_bash: bashCommand ? isMutatingBash(bashCommand) : false,
242
+ is_mutating_write_tool:
243
+ input.toolName === "write" || input.toolName === "edit",
244
+ bash_web_block: sessionActive && bashWebBlocked(bashCommand),
245
+ bash_planning_deny:
246
+ sessionActive && bashPlanningDenied(bashCommand, agentId),
247
+ bash_planning_json_block:
248
+ sessionActive && bashPlanningJsonDenied(bashCommand, agentId),
249
+ eval_plan_packet_write_block: evalPlanPacketBlock,
250
+ is_submit_tool: input.toolName.startsWith("submit_"),
251
+ is_planning_agent: isHarnessPlanningAgent(agentId),
252
+ is_read_only_kind:
253
+ agentKind === "planner" ||
254
+ agentKind === "evaluator" ||
255
+ agentKind === "adversary" ||
256
+ agentKind === "tie_breaker" ||
257
+ agentKind === "trace" ||
258
+ agentKind === "incident" ||
259
+ agentKind === "meta",
260
+ is_executor_kind: agentKind === "executor",
261
+ trust_score: Number(process.env.HARNESS_TRUST_SCORE ?? "1"),
262
+ delegation_ceiling: Number(process.env.HARNESS_DELEGATION_CEILING ?? "1"),
263
+ agent_did: input.agentDid ?? process.env.HARNESS_AGENT_DID ?? agentId,
264
+ write_path: writePath ?? "",
265
+ mutating_bash_phase_block: mutatingBashPhaseBlock,
266
+ abort_mutating_block: abortMutatingBlock,
267
+ };
268
+ }
269
+
270
+ export async function buildHarnessAgtEvaluationContextFromRun(
271
+ input: Omit<BuildEvaluationContextInput, "policyState"> & {
272
+ policyState?: BuildEvaluationContextInput["policyState"];
273
+ },
274
+ ): Promise<HarnessAgtContext> {
275
+ const policyState = input.policyState ?? {
276
+ phase: (process.env.HARNESS_SUBAGENT_PHASE_HINT as HarnessPhase) ?? "plan",
277
+ approvedPlan: true,
278
+ planId: null,
279
+ aborted: false,
280
+ budgetBypass: false,
281
+ };
282
+ return buildHarnessAgtEvaluationContext({ ...input, policyState });
283
+ }
284
+
285
+ export type { HarnessRunContext };
@@ -0,0 +1,28 @@
1
+ /** AGT feature flags and package-root resolution for harness policies. */
2
+
3
+ import { existsSync } from "node:fs";
4
+ import { join } from "node:path";
5
+
6
+ export function isHarnessAgtPolicyEnabled(): boolean {
7
+ const raw = process.env.HARNESS_AGT_POLICY?.trim().toLowerCase();
8
+ if (raw === "0" || raw === "false" || raw === "off") return false;
9
+ return true;
10
+ }
11
+
12
+ export function resolveHarnessPoliciesDir(packageRoot: string): string {
13
+ const fromEnv = process.env.HARNESS_AGT_POLICIES_DIR?.trim();
14
+ if (fromEnv && existsSync(fromEnv)) return fromEnv;
15
+ return join(packageRoot, ".pi", "harness", "policies");
16
+ }
17
+
18
+ export function resolveProjectPoliciesDir(projectRoot: string): string {
19
+ return join(projectRoot, ".pi", "policies");
20
+ }
21
+
22
+ export function resolveHarnessPackageRootFromEnv(): string {
23
+ return (
24
+ process.env.HARNESS_PKG_ROOT?.trim() ||
25
+ process.env.UP_PKG?.trim() ||
26
+ process.cwd()
27
+ );
28
+ }