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
@@ -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
+ }
@@ -0,0 +1,69 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getOrCreateParentIdentity } from "./identity-registry.js";
4
+
5
+ const ROLE_CAPABILITIES: Record<string, string[]> = {
6
+ planner: ["harness.read", "harness.submit.plan"],
7
+ executor: ["harness.read", "harness.write", "harness.submit.run"],
8
+ evaluator: ["harness.read", "harness.submit.review"],
9
+ adversary: ["harness.read", "harness.submit.review"],
10
+ tie_breaker: ["harness.read", "harness.submit.review"],
11
+ meta: ["harness.read"],
12
+ trace: ["harness.read"],
13
+ incident: ["harness.read"],
14
+ other: ["harness.read"],
15
+ };
16
+
17
+ export function capabilitiesForHarnessAgent(
18
+ agentId: string,
19
+ kind: string,
20
+ ): string[] {
21
+ if (agentId.startsWith("harness/planning/")) {
22
+ return ROLE_CAPABILITIES.planner ?? ["harness.read"];
23
+ }
24
+ return ROLE_CAPABILITIES[kind] ?? ROLE_CAPABILITIES.other;
25
+ }
26
+
27
+ export interface DelegationBundle {
28
+ agentDid: string;
29
+ delegationCeiling: number;
30
+ identityPath: string;
31
+ }
32
+
33
+ export function mintSubagentDelegation(input: {
34
+ runId: string;
35
+ runDir: string;
36
+ agentId: string;
37
+ agentKind: string;
38
+ trustCeiling?: number;
39
+ }): DelegationBundle {
40
+ const parent = getOrCreateParentIdentity(input.runId, input.runDir);
41
+ const caps = capabilitiesForHarnessAgent(input.agentId, input.agentKind);
42
+ const safeId = input.agentId.replace(/\//g, "_");
43
+ const agentDir = join(input.runDir, "agents", safeId);
44
+ mkdirSync(agentDir, { recursive: true });
45
+
46
+ const child = parent.delegate(`harness-${safeId}`, caps, {
47
+ description: `Harness subagent ${input.agentId}`,
48
+ });
49
+ writeFileSync(
50
+ join(agentDir, "identity.json"),
51
+ JSON.stringify(child.toJSON(), null, 2),
52
+ );
53
+
54
+ const ceiling = input.trustCeiling ?? 1;
55
+ return {
56
+ agentDid: child.did,
57
+ delegationCeiling: ceiling,
58
+ identityPath: join(agentDir, "identity.json"),
59
+ };
60
+ }
61
+
62
+ export function delegationEnvFromBundle(
63
+ bundle: DelegationBundle,
64
+ ): Record<string, string> {
65
+ return {
66
+ HARNESS_AGENT_DID: bundle.agentDid,
67
+ HARNESS_DELEGATION_CEILING: String(bundle.delegationCeiling),
68
+ };
69
+ }
@@ -0,0 +1,56 @@
1
+ import type { PolicyDecisionResult } from "@microsoft/agent-governance-sdk";
2
+ import type { BuildEvaluationContextInput } from "./build-evaluation-context.js";
3
+ import { buildHarnessAgtEvaluationContext } from "./build-evaluation-context.js";
4
+ import { isHarnessAgtPolicyEnabled } from "./config.js";
5
+ import { evaluateLegacyHarnessToolPolicy } from "./legacy-evaluate.js";
6
+ import { getAgtPolicyEngine } from "./policy-engine.js";
7
+
8
+ export interface HarnessPolicyEvaluation {
9
+ allowed: boolean;
10
+ reason: string;
11
+ source: "agt" | "legacy";
12
+ agt?: PolicyDecisionResult;
13
+ }
14
+
15
+ export async function evaluateHarnessToolPolicy(
16
+ packageRoot: string,
17
+ input: BuildEvaluationContextInput,
18
+ ): Promise<HarnessPolicyEvaluation> {
19
+ if (!isHarnessAgtPolicyEnabled()) {
20
+ const legacy = await evaluateLegacyHarnessToolPolicy(input);
21
+ return {
22
+ allowed: legacy.allowed,
23
+ reason: legacy.reason,
24
+ source: "legacy",
25
+ };
26
+ }
27
+
28
+ try {
29
+ const context = await buildHarnessAgtEvaluationContext(input);
30
+ const engine = getAgtPolicyEngine(packageRoot, input.projectRoot);
31
+ const agentDid = String(context.agent_did ?? context.harness_agent_id);
32
+ const result = engine.evaluatePolicy(agentDid, context);
33
+ if (!result.allowed) {
34
+ return {
35
+ allowed: false,
36
+ reason:
37
+ result.reason ??
38
+ `agt-policy: denied by ${result.policyName ?? "policy"}/${result.matchedRule ?? "rule"}`,
39
+ source: "agt",
40
+ agt: result,
41
+ };
42
+ }
43
+ return {
44
+ allowed: true,
45
+ reason: result.reason ?? "allow",
46
+ source: "agt",
47
+ agt: result,
48
+ };
49
+ } catch (err) {
50
+ return {
51
+ allowed: false,
52
+ reason: `agt-policy: evaluation failed (fail-closed): ${String(err)}`,
53
+ source: "agt",
54
+ };
55
+ }
56
+ }
@@ -0,0 +1,41 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { AgentIdentity } from "@microsoft/agent-governance-sdk";
4
+
5
+ const runRoots = new Map<string, AgentIdentity>();
6
+
7
+ export function getOrCreateParentIdentity(
8
+ runId: string,
9
+ runDir: string,
10
+ ): AgentIdentity {
11
+ const cached = runRoots.get(runId);
12
+ if (cached) return cached;
13
+
14
+ const agentsDir = join(runDir, "agents", "_parent");
15
+ const identityPath = join(agentsDir, "identity.json");
16
+ mkdirSync(agentsDir, { recursive: true });
17
+
18
+ if (existsSync(identityPath)) {
19
+ const json = JSON.parse(readFileSync(identityPath, "utf-8"));
20
+ const restored = AgentIdentity.fromJSON(json);
21
+ runRoots.set(runId, restored);
22
+ return restored;
23
+ }
24
+
25
+ const identity = AgentIdentity.generate(`harness-parent-${runId}`, [
26
+ "harness.orchestrate",
27
+ "harness.delegate",
28
+ "harness.plan",
29
+ "harness.execute",
30
+ ]);
31
+ writeFileSync(identityPath, JSON.stringify(identity.toJSON(), null, 2));
32
+ runRoots.set(runId, identity);
33
+ return identity;
34
+ }
35
+
36
+ export function loadChildIdentity(agentDir: string): AgentIdentity | null {
37
+ const identityPath = join(agentDir, "identity.json");
38
+ if (!existsSync(identityPath)) return null;
39
+ const json = JSON.parse(readFileSync(identityPath, "utf-8"));
40
+ return AgentIdentity.fromJSON(json);
41
+ }
@@ -0,0 +1,55 @@
1
+ export {
2
+ appendPolicyAuditEvent,
3
+ verifyRunAuditChain,
4
+ } from "./audit-run-sink.js";
5
+ export type {
6
+ BuildEvaluationContextInput,
7
+ HarnessAgtContext,
8
+ } from "./build-evaluation-context.js";
9
+ export {
10
+ buildHarnessAgtEvaluationContext,
11
+ buildHarnessAgtEvaluationContextFromRun,
12
+ } from "./build-evaluation-context.js";
13
+ export {
14
+ isHarnessAgtPolicyEnabled,
15
+ resolveHarnessPackageRootFromEnv,
16
+ resolveHarnessPoliciesDir,
17
+ } from "./config.js";
18
+ export {
19
+ capabilitiesForHarnessAgent,
20
+ delegationEnvFromBundle,
21
+ mintSubagentDelegation,
22
+ } from "./delegation.js";
23
+ export type { HarnessPolicyEvaluation } from "./evaluate-policy.js";
24
+ export { evaluateHarnessToolPolicy } from "./evaluate-policy.js";
25
+ export {
26
+ getOrCreateParentIdentity,
27
+ loadChildIdentity,
28
+ } from "./identity-registry.js";
29
+ export { evaluateLegacyHarnessToolPolicy } from "./legacy-evaluate.js";
30
+ export {
31
+ createAgtPolicyEngine,
32
+ createHarnessPolicyEngine,
33
+ doctorHarnessPolicies,
34
+ getAgtPolicyEngine,
35
+ getHarnessPolicyEngine,
36
+ HarnessPolicyLoadError,
37
+ resetHarnessPolicyEngineCache,
38
+ } from "./policy-engine.js";
39
+ export { createRingEnforcer, ringForHarnessAgentKind } from "./rings.js";
40
+ export {
41
+ getHarnessGovernanceMetrics,
42
+ isSreEnforceEnabled,
43
+ recordSpawnAttempt,
44
+ spawnCircuitOpen,
45
+ } from "./sre-hooks.js";
46
+ export {
47
+ getTrustManagerForRun,
48
+ recordPolicyAllow,
49
+ recordPolicyDeny,
50
+ trustScoreForAgent,
51
+ } from "./trust-run-store.js";
52
+ export {
53
+ workflowBlocked,
54
+ workflowFlagsFromEntries,
55
+ } from "./workflow-history.js";
@@ -0,0 +1,11 @@
1
+ const denyCounts = new Map<string, number>();
2
+
3
+ export function recordHarnessPolicyDeny(sessionId: string): number {
4
+ const n = (denyCounts.get(sessionId) ?? 0) + 1;
5
+ denyCounts.set(sessionId, n);
6
+ return n;
7
+ }
8
+
9
+ export function resetHarnessPolicyDenyCount(sessionId: string): void {
10
+ denyCounts.delete(sessionId);
11
+ }
@@ -0,0 +1,101 @@
1
+ import { allowsAgentTool } from "../agents-policy.mjs";
2
+ import { evaluateContextModeMutation } from "../harness-context-mode-policy.js";
3
+ import {
4
+ extractWritePathFromToolInput,
5
+ getLatestRunContext,
6
+ isPlanPhaseAllowedMutation,
7
+ } from "../harness-run-context.js";
8
+ import { evaluateSubagentToolCall } from "../harness-spawn-policy.js";
9
+ import type { BuildEvaluationContextInput } from "./build-evaluation-context.js";
10
+ import {
11
+ buildHarnessAgtEvaluationContext,
12
+ type HarnessAgtContext,
13
+ harnessSessionToolDenyReason,
14
+ } from "./build-evaluation-context.js";
15
+
16
+ /** Combined legacy path for HARNESS_AGT_POLICY=0 parity tests. */
17
+ export async function evaluateLegacyHarnessToolPolicy(
18
+ input: BuildEvaluationContextInput,
19
+ ): Promise<{ allowed: boolean; reason: string; context?: HarnessAgtContext }> {
20
+ const { toolName, toolInput, policyState, entries, projectRoot, sessionId } =
21
+ input;
22
+ const agentId =
23
+ process.env.PI_HARNESS_SUBPROCESS === "1"
24
+ ? (process.env.HARNESS_AGENT_ID?.trim() ?? "harness/unknown")
25
+ : "parent-orchestrator";
26
+ const isSubprocess = process.env.PI_HARNESS_SUBPROCESS === "1";
27
+ const isParent = agentId === "parent-orchestrator";
28
+
29
+ const spawn = evaluateSubagentToolCall(toolName, agentId);
30
+ if (spawn.action === "block") {
31
+ return { allowed: false, reason: spawn.reason ?? "spawn policy" };
32
+ }
33
+
34
+ if (
35
+ !allowsAgentTool({
36
+ packageRoot: input.packageRoot,
37
+ projectRoot,
38
+ agentId,
39
+ toolName,
40
+ toolInput,
41
+ isSubprocess,
42
+ isParentOrchestrator: isParent,
43
+ })
44
+ ) {
45
+ return {
46
+ allowed: false,
47
+ reason: `agents-policy: ${toolName} not allowed for ${agentId}`,
48
+ };
49
+ }
50
+
51
+ const runCtx = getLatestRunContext(entries);
52
+ const phase = policyState.phase;
53
+ const bashCommand =
54
+ toolName === "bash" ? String(toolInput.command ?? "") : "";
55
+
56
+ if (toolName === "write" || toolName === "edit") {
57
+ const planMutation = await isPlanPhaseAllowedMutation(
58
+ toolName,
59
+ toolInput,
60
+ phase,
61
+ runCtx,
62
+ projectRoot,
63
+ {
64
+ aborted: policyState.aborted,
65
+ entries,
66
+ ownerSessionId: runCtx?.owner_pi_session_id,
67
+ currentSessionId: sessionId,
68
+ },
69
+ );
70
+ if (!planMutation.allowed) {
71
+ return {
72
+ allowed: false,
73
+ reason: planMutation.reason ?? "plan phase mutation blocked",
74
+ };
75
+ }
76
+ }
77
+
78
+ const ctxMode = evaluateContextModeMutation(toolName, toolInput, phase, {
79
+ aborted: policyState.aborted,
80
+ budgetBypass: policyState.budgetBypass,
81
+ readOnlyAgent: false,
82
+ });
83
+ if (ctxMode.blocked) {
84
+ return { allowed: false, reason: ctxMode.reason };
85
+ }
86
+
87
+ const sessionDeny = harnessSessionToolDenyReason({
88
+ toolName,
89
+ toolInput,
90
+ phase,
91
+ agentId,
92
+ entries,
93
+ aborted: policyState.aborted,
94
+ });
95
+ if (sessionDeny) {
96
+ return { allowed: false, reason: sessionDeny };
97
+ }
98
+
99
+ const context = await buildHarnessAgtEvaluationContext(input);
100
+ return { allowed: true, reason: "legacy allow", context };
101
+ }