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
@@ -16,9 +16,15 @@
16
16
  },
17
17
  {
18
18
  "name": "contracts",
19
- "paths": [".pi/harness/specs/*", ".pi/harness/docs/*"],
19
+ "paths": [
20
+ ".pi/harness/specs/*",
21
+ ".pi/harness/docs/*",
22
+ ".pi/harness/policies/*",
23
+ ".pi/harness/agents.policy.yaml",
24
+ ".pi/harness/examples/*"
25
+ ],
20
26
  "order": 1,
21
- "description": "Harness schemas, ADRs, and governance docs"
27
+ "description": "Harness schemas, ADRs, AGT policies, and agents.policy SSOT"
22
28
  },
23
29
  {
24
30
  "name": "runtime",
@@ -39,9 +45,15 @@
39
45
  },
40
46
  {
41
47
  "name": "tooling",
42
- "paths": [".pi/scripts/*", "test/*"],
48
+ "paths": [".pi/scripts/*"],
43
49
  "order": 4,
44
- "description": "Harness CLI scripts and tests"
50
+ "description": "Harness CLI scripts"
51
+ },
52
+ {
53
+ "name": "foundation",
54
+ "paths": [".pi/lib/*"],
55
+ "order": 5,
56
+ "description": "Shared harness/AGT libraries (imported by extensions and scripts)"
45
57
  }
46
58
  ],
47
59
  "boundaries": [
@@ -65,6 +77,16 @@
65
77
  "to": ".pi/extensions/*",
66
78
  "reason": "Contracts are data-only JSON schemas; extensions implement behavior"
67
79
  },
80
+ {
81
+ "from": ".pi/lib/*",
82
+ "to": ".pi/extensions/*",
83
+ "reason": "Foundation lib must not import extension modules"
84
+ },
85
+ {
86
+ "from": ".pi/harness/policies/*",
87
+ "to": ".pi/extensions/*",
88
+ "reason": "Declarative AGT YAML must not depend on extension implementation"
89
+ },
68
90
  {
69
91
  "from": ".pi/scripts/*",
70
92
  "to": ".agents/skills/*",
@@ -37,7 +37,8 @@
37
37
  "drift-monitor",
38
38
  "sentrux",
39
39
  "evaluator",
40
- "harness-telemetry"
40
+ "harness-telemetry",
41
+ "agt-policy"
41
42
  ]
42
43
  },
43
44
  "kind": {
@@ -0,0 +1,70 @@
1
+ export function packageAgentsPolicyPath(packageRoot: string): string;
2
+ export function projectAgentsPolicyPath(projectRoot: string): string;
3
+ export function projectPoliciesDir(projectRoot: string): string;
4
+
5
+ export interface AgentPolicySpec {
6
+ kind: string;
7
+ effectiveTools: string[];
8
+ extensionsOff: boolean;
9
+ readOnly: boolean;
10
+ maxTurns?: number;
11
+ thinking?: string;
12
+ submitTool?: string;
13
+ }
14
+
15
+ export interface AllowsAgentToolInput {
16
+ packageRoot: string;
17
+ projectRoot: string;
18
+ agentId: string;
19
+ toolName: string;
20
+ toolInput?: Record<string, unknown>;
21
+ isSubprocess?: boolean;
22
+ isParentOrchestrator?: boolean;
23
+ }
24
+
25
+ export function loadAgentsPolicyMerged(
26
+ packageRoot: string,
27
+ projectRoot: string,
28
+ ): {
29
+ schemaVersion: string;
30
+ kinds: Map<string, unknown>;
31
+ agents: Map<string, unknown>;
32
+ defaults: unknown;
33
+ };
34
+
35
+ export function resolveEffectiveTools(
36
+ agentId: string,
37
+ merged: ReturnType<typeof loadAgentsPolicyMerged>,
38
+ ): AgentPolicySpec;
39
+
40
+ export function getAgentPolicySpec(
41
+ packageRoot: string,
42
+ projectRoot: string,
43
+ agentId: string,
44
+ ): AgentPolicySpec | null;
45
+
46
+ export function getAgentKind(
47
+ packageRoot: string,
48
+ projectRoot: string,
49
+ agentId: string,
50
+ ): string;
51
+
52
+ export function isHarnessPlanningAgent(agentId: string): boolean;
53
+
54
+ export function harnessSubagentPhaseHint(
55
+ packageRoot: string,
56
+ projectRoot: string,
57
+ agentId: string,
58
+ ): string | null;
59
+
60
+ export function allowsAgentTool(input: AllowsAgentToolInput): boolean;
61
+
62
+ export function applyAgentPolicyToConfig<T extends { name: string }>(
63
+ agent: T,
64
+ packageRoot: string,
65
+ projectRoot: string,
66
+ ): T;
67
+
68
+ export function findProjectRootFromAgentsDir(projectAgentsDir: string): string;
69
+
70
+ export function isAgtGovernanceActive(projectRoot: string): boolean;
@@ -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
+ }