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
@@ -1,260 +0,0 @@
1
- import type { ExtensionUIContext } from "@earendil-works/pi-coding-agent";
2
- import {
3
- Editor,
4
- type EditorTheme,
5
- Key,
6
- matchesKey,
7
- truncateToWidth,
8
- } from "@earendil-works/pi-tui";
9
- import type { AskResponse, DialogResult, ValidatedAskParams } from "./types.js";
10
-
11
- type DisplayOption = {
12
- title: string;
13
- description?: string;
14
- isFreeform?: boolean;
15
- };
16
-
17
- interface CustomAnswer {
18
- response: AskResponse;
19
- }
20
-
21
- function withTimeout<T>(
22
- promise: Promise<T | null>,
23
- ms: number | undefined,
24
- ): Promise<T | null> {
25
- if (!ms) return promise;
26
- return Promise.race([
27
- promise,
28
- new Promise<null>((resolve) => {
29
- setTimeout(() => resolve(null), ms);
30
- }),
31
- ]);
32
- }
33
-
34
- export async function runAskDialog(
35
- ui: ExtensionUIContext,
36
- validated: ValidatedAskParams,
37
- ): Promise<DialogResult> {
38
- const { question, context, options, allowMultiple, allowFreeform } =
39
- validated;
40
-
41
- const displayOptions: DisplayOption[] = [...options];
42
- if (allowFreeform) {
43
- displayOptions.push({
44
- title: "Type something…",
45
- isFreeform: true,
46
- });
47
- }
48
-
49
- // Freeform-only: no listed options
50
- if (displayOptions.length === 0) {
51
- const text = await ui.input(question, "");
52
- if (!text?.trim()) {
53
- return { response: null, cancelled: true };
54
- }
55
- return {
56
- response: { kind: "freeform", text: text.trim() },
57
- cancelled: false,
58
- };
59
- }
60
-
61
- const result = await withTimeout(
62
- ui.custom<CustomAnswer | null>((tui, theme, _kb, done) => {
63
- let optionIndex = 0;
64
- let editMode = false;
65
- const selected = new Set<number>();
66
- let cachedLines: string[] | undefined;
67
-
68
- const editorTheme: EditorTheme = {
69
- borderColor: (s) => theme.fg("accent", s),
70
- selectList: {
71
- selectedPrefix: (t) => theme.fg("accent", t),
72
- selectedText: (t) => theme.fg("accent", t),
73
- description: (t) => theme.fg("muted", t),
74
- scrollInfo: (t) => theme.fg("dim", t),
75
- noMatch: (t) => theme.fg("warning", t),
76
- },
77
- };
78
- const editor = new Editor(tui, editorTheme);
79
-
80
- editor.onSubmit = (value) => {
81
- const trimmed = value.trim();
82
- if (trimmed) {
83
- done({ response: { kind: "freeform", text: trimmed } });
84
- } else {
85
- editMode = false;
86
- editor.setText("");
87
- refresh();
88
- }
89
- };
90
-
91
- function refresh() {
92
- cachedLines = undefined;
93
- tui.requestRender();
94
- }
95
-
96
- function submitSelection() {
97
- if (allowMultiple) {
98
- const titles = [...selected]
99
- .sort((a, b) => a - b)
100
- .map((i) => displayOptions[i].title)
101
- .filter((t) => t !== "Type something…");
102
- if (titles.length === 0) return;
103
- done({ response: { kind: "selection", selections: titles } });
104
- return;
105
- }
106
- const opt = displayOptions[optionIndex];
107
- if (opt.isFreeform) {
108
- editMode = true;
109
- refresh();
110
- return;
111
- }
112
- done({
113
- response: { kind: "selection", selections: [opt.title] },
114
- });
115
- }
116
-
117
- function handleInput(data: string) {
118
- if (editMode) {
119
- if (matchesKey(data, Key.escape)) {
120
- editMode = false;
121
- editor.setText("");
122
- refresh();
123
- return;
124
- }
125
- editor.handleInput(data);
126
- refresh();
127
- return;
128
- }
129
-
130
- if (matchesKey(data, Key.up)) {
131
- optionIndex = Math.max(0, optionIndex - 1);
132
- refresh();
133
- return;
134
- }
135
- if (matchesKey(data, Key.down)) {
136
- optionIndex = Math.min(displayOptions.length - 1, optionIndex + 1);
137
- refresh();
138
- return;
139
- }
140
-
141
- if (allowMultiple && matchesKey(data, Key.space)) {
142
- const opt = displayOptions[optionIndex];
143
- if (!opt.isFreeform) {
144
- if (selected.has(optionIndex)) {
145
- selected.delete(optionIndex);
146
- } else {
147
- selected.add(optionIndex);
148
- }
149
- refresh();
150
- }
151
- return;
152
- }
153
-
154
- if (matchesKey(data, Key.enter)) {
155
- submitSelection();
156
- return;
157
- }
158
-
159
- if (matchesKey(data, Key.escape)) {
160
- done(null);
161
- }
162
- }
163
-
164
- function render(width: number): string[] {
165
- if (cachedLines) return cachedLines;
166
-
167
- const lines: string[] = [];
168
- const add = (s: string) => lines.push(truncateToWidth(s, width));
169
- const useOverlay = validated.displayMode !== "inline";
170
-
171
- if (useOverlay) {
172
- add(theme.fg("accent", "─".repeat(width)));
173
- }
174
-
175
- if (context) {
176
- for (const line of context.split("\n")) {
177
- add(theme.fg("muted", ` ${line}`));
178
- }
179
- lines.push("");
180
- }
181
-
182
- add(theme.fg("text", ` ${question}`));
183
- lines.push("");
184
-
185
- for (let i = 0; i < displayOptions.length; i++) {
186
- const opt = displayOptions[i];
187
- const isFreeform = opt.isFreeform === true;
188
- const focused = i === optionIndex;
189
- const checked = selected.has(i);
190
- let prefix = " ";
191
- if (allowMultiple && !isFreeform) {
192
- prefix = checked ? theme.fg("accent", "[x] ") : "[ ] ";
193
- } else if (focused) {
194
- prefix = theme.fg("accent", "> ");
195
- }
196
-
197
- const num = `${i + 1}. `;
198
- const label = opt.title;
199
- if (isFreeform && editMode && focused) {
200
- add(prefix + theme.fg("accent", `${num}${label} ✎`));
201
- } else if (focused && !allowMultiple) {
202
- add(prefix + theme.fg("accent", `${num}${label}`));
203
- } else {
204
- add(`${prefix}${theme.fg("text", `${num}${label}`)}`);
205
- }
206
-
207
- if (opt.description) {
208
- add(` ${theme.fg("muted", opt.description)}`);
209
- }
210
- }
211
-
212
- if (editMode) {
213
- lines.push("");
214
- add(theme.fg("muted", " Your answer:"));
215
- for (const line of editor.render(width - 2)) {
216
- add(` ${line}`);
217
- }
218
- }
219
-
220
- lines.push("");
221
- if (editMode) {
222
- add(theme.fg("dim", " Enter to submit • Esc to go back"));
223
- } else if (allowMultiple) {
224
- add(
225
- theme.fg(
226
- "dim",
227
- " ↑↓ navigate • Space toggle • Enter confirm • Esc cancel",
228
- ),
229
- );
230
- } else {
231
- add(
232
- theme.fg("dim", " ↑↓ navigate • Enter to select • Esc to cancel"),
233
- );
234
- }
235
-
236
- if (useOverlay) {
237
- add(theme.fg("accent", "─".repeat(width)));
238
- }
239
-
240
- cachedLines = lines;
241
- return lines;
242
- }
243
-
244
- return {
245
- render,
246
- invalidate: () => {
247
- cachedLines = undefined;
248
- },
249
- handleInput,
250
- };
251
- }),
252
- validated.timeout,
253
- );
254
-
255
- if (!result) {
256
- return { response: null, cancelled: true };
257
- }
258
-
259
- return { response: result.response, cancelled: false };
260
- }
@@ -1,209 +0,0 @@
1
- /**
2
- * Resolve concrete LLM credentials for harness subagent subprocesses.
3
- *
4
- * Parent sessions often use `router/<profile>` (pi-model-router). Subagents run with
5
- * `--no-extensions`, so they cannot use the logical router provider — they need
6
- * a real provider/model plus that provider's API key.
7
- *
8
- * Session-locked routing: subprocess model is chosen once from agent system prompt
9
- * complexity (same analysis as parent session lock), not from per-turn parent tier.
10
- */
11
-
12
- import { existsSync, readFileSync } from "node:fs";
13
- import { join } from "node:path";
14
- import { resolveTierFromPrompt } from "../../../vendor/pi-model-router/extensions/routing.js";
15
- import type {
16
- RouterProfile,
17
- RouterTier,
18
- RoutingRule,
19
- } from "../../../vendor/pi-model-router/extensions/types.js";
20
- import type { AgentConfig } from "../../../vendor/pi-subagents/src/agents.js";
21
-
22
- const ROUTER_SENTINEL_KEY = "pi-model-router";
23
- const SENTINEL_API_KEYS = new Set([ROUTER_SENTINEL_KEY, "<authenticated>"]);
24
-
25
- interface ModelRouterJson {
26
- defaultProfile?: string;
27
- phaseBias?: number;
28
- rules?: RoutingRule[];
29
- profiles?: Record<string, RouterProfile>;
30
- }
31
-
32
- export function isUsableApiKey(key: string | undefined): key is string {
33
- return Boolean(key && !SENTINEL_API_KEYS.has(key));
34
- }
35
-
36
- export function parseModelRef(
37
- ref: string,
38
- ): { provider: string; modelId: string } | null {
39
- const slash = ref.indexOf("/");
40
- if (slash <= 0) return null;
41
- const provider = ref.slice(0, slash).trim();
42
- const modelId = ref.slice(slash + 1).trim();
43
- if (!provider || !modelId) return null;
44
- return { provider, modelId };
45
- }
46
-
47
- /** Planning subagents that should prefer low/medium router tier for latency. */
48
- const ROUTINE_PLANNING_AGENT_PATHS = new Set([
49
- "harness/planning/plan-evaluator",
50
- "harness/planning/plan-adversary",
51
- "harness/planning/review-integrator",
52
- "harness/planning/hypothesis-validator",
53
- "harness/planning/sprint-contract-auditor",
54
- "harness/planning/planning-context",
55
- "harness/planning/scout-structure",
56
- "harness/planning/scout-semantic",
57
- "harness/planning/decompose",
58
- "harness/planning/hypothesis",
59
- "harness/planning/stack-research",
60
- "harness/planning/plan-validator",
61
- ]);
62
-
63
- export function isRoutinePlanningAgent(agentName: string): boolean {
64
- return ROUTINE_PLANNING_AGENT_PATHS.has(agentName);
65
- }
66
-
67
- export function thinkingToRouterTier(
68
- thinking?: string,
69
- agentName?: string,
70
- ): RouterTier {
71
- if (agentName && isRoutinePlanningAgent(agentName)) {
72
- if (thinking === "high" || thinking === "xhigh") return "medium";
73
- return "low";
74
- }
75
- if (thinking === "high" || thinking === "xhigh") return "high";
76
- if (thinking === "off" || thinking === "minimal" || thinking === "low") {
77
- return "low";
78
- }
79
- return "medium";
80
- }
81
-
82
- function loadModelRouterConfig(cwd: string): ModelRouterJson | undefined {
83
- const path = join(cwd, ".pi", "model-router.json");
84
- if (!existsSync(path)) return undefined;
85
- try {
86
- return JSON.parse(readFileSync(path, "utf8")) as ModelRouterJson;
87
- } catch {
88
- return undefined;
89
- }
90
- }
91
-
92
- function resolveRouterProfileEntry(
93
- config: ModelRouterJson,
94
- profileId: string,
95
- ): { profileId: string; profile: RouterProfile } | undefined {
96
- const profiles = config.profiles;
97
- if (!profiles) return undefined;
98
- const candidates = [
99
- profileId,
100
- config.defaultProfile ?? "auto",
101
- "auto",
102
- "opencode-go",
103
- ];
104
- const seen = new Set<string>();
105
- for (const id of candidates) {
106
- if (!id || seen.has(id)) continue;
107
- seen.add(id);
108
- const profile = profiles[id];
109
- if (profile?.high?.model && profile.medium?.model && profile.low?.model) {
110
- return { profileId: id, profile };
111
- }
112
- }
113
- return undefined;
114
- }
115
-
116
- /** Tier from agent system prompt (+ optional task line) for session model lock. */
117
- export function resolveSubagentRouterTier(
118
- cwd: string,
119
- profileId: string,
120
- agent: AgentConfig,
121
- taskSnippet?: string,
122
- ): RouterTier {
123
- const config = loadModelRouterConfig(cwd);
124
- if (config) {
125
- const entry = resolveRouterProfileEntry(config, profileId);
126
- if (entry) {
127
- return resolveTierFromPrompt(
128
- agent.systemPrompt ?? "",
129
- taskSnippet?.trim() ?? "",
130
- entry.profileId,
131
- entry.profile,
132
- config.rules,
133
- config.phaseBias ?? 0.5,
134
- );
135
- }
136
- }
137
- return thinkingToRouterTier(agent.thinking, agent.name);
138
- }
139
-
140
- /** Map router profile tier → concrete `provider/model` from `.pi/model-router.json`. */
141
- export function resolveRouterConcreteModelRef(
142
- cwd: string,
143
- profileId: string,
144
- tier: RouterTier,
145
- ): string | undefined {
146
- const path = join(cwd, ".pi", "model-router.json");
147
- if (!existsSync(path)) return undefined;
148
- const raw = loadModelRouterConfig(cwd);
149
- if (!raw) return undefined;
150
- const entry = resolveRouterProfileEntry(raw, profileId);
151
- const model = entry?.profile[tier]?.model;
152
- return typeof model === "string" && model.includes("/") ? model : undefined;
153
- }
154
-
155
- export interface ConcreteSubagentModel {
156
- modelRef: string;
157
- provider: string;
158
- modelId: string;
159
- routerProfile?: string;
160
- routerTier?: RouterTier;
161
- }
162
-
163
- /**
164
- * Pick the subprocess model ref before resolving API keys.
165
- * Never returns `router/*` — always a concrete provider.
166
- */
167
- export function resolveConcreteSubagentModel(
168
- cwd: string,
169
- parentModel: { provider: string; id: string } | undefined,
170
- agent: AgentConfig,
171
- taskSnippet?: string,
172
- ): ConcreteSubagentModel | undefined {
173
- if (agent.model && !agent.model.startsWith("router/")) {
174
- const parsed = parseModelRef(agent.model);
175
- if (parsed) {
176
- return { modelRef: agent.model, ...parsed };
177
- }
178
- }
179
-
180
- const parentIsRouter = parentModel?.provider === "router";
181
- const agentIsRouter = Boolean(agent.model?.startsWith("router/"));
182
-
183
- if (!parentIsRouter && !agentIsRouter) {
184
- if (parentModel && parentModel.provider !== "router") {
185
- return {
186
- modelRef: `${parentModel.provider}/${parentModel.id}`,
187
- provider: parentModel.provider,
188
- modelId: parentModel.id,
189
- };
190
- }
191
- return undefined;
192
- }
193
-
194
- const profileId =
195
- agentIsRouter && agent.model
196
- ? agent.model.slice("router/".length)
197
- : (parentModel?.id ?? "auto");
198
- const tier = resolveSubagentRouterTier(cwd, profileId, agent, taskSnippet);
199
- const concrete = resolveRouterConcreteModelRef(cwd, profileId, tier);
200
- if (!concrete) return undefined;
201
- const parsed = parseModelRef(concrete);
202
- if (!parsed || parsed.provider === "router") return undefined;
203
- return {
204
- modelRef: concrete,
205
- ...parsed,
206
- routerProfile: profileId,
207
- routerTier: tier,
208
- };
209
- }
@@ -1,236 +0,0 @@
1
- /**
2
- * Per-agent tool policy for harness/* subagents (defense in depth with frontmatter).
3
- */
4
-
5
- import {
6
- evaluateContextModeMutation,
7
- isMutatingBash,
8
- } from "../../lib/harness-context-mode-policy.js";
9
- import type { HarnessPhase } from "../../lib/harness-run-context.js";
10
- import {
11
- isSubmitToolName,
12
- SUBMIT_TOOLS_BY_AGENT,
13
- } from "./harness-subagent-submit-registry.js";
14
- import {
15
- evaluateSubagentToolCall,
16
- type ToolCallDecision,
17
- } from "./spawn-policy.js";
18
-
19
- export type HarnessAgentKind =
20
- | "planner"
21
- | "executor"
22
- | "evaluator"
23
- | "adversary"
24
- | "tie_breaker"
25
- | "meta"
26
- | "trace"
27
- | "incident"
28
- | "other";
29
-
30
- const MUTATING_TOOLS = new Set(["write", "edit"]);
31
-
32
- /** Planning agents must use submit_* → canonical artifacts/*.yaml, not JSON dumps. */
33
- const PLANNING_ARTIFACT_JSON_WRITE = /artifacts\/[^\s'"`;]+\.json\b/i;
34
-
35
- const PLANNING_BASH_DENY_PATTERNS = [
36
- /\bgraphify\s+update\b/i,
37
- /\bgraphify\s+extract\b/i,
38
- /\bgraphify\s+install\b/i,
39
- /\bccc\s+(index|init|reset|daemon)\b/i,
40
- /\bccc\s+search\b.*--refresh/i,
41
- /\bpip\s+install\b/i,
42
- /\buv\s+tool\s+install\b/i,
43
- /\bnpm\s+install\b/i,
44
- /\bnpm\s+install\b.*cocoindex/i,
45
- /\buv\s+tool\s+install\b.*cocoindex/i,
46
- ];
47
-
48
- const READ_ONLY_KINDS = new Set<HarnessAgentKind>([
49
- "planner",
50
- "evaluator",
51
- "adversary",
52
- "tie_breaker",
53
- "trace",
54
- "incident",
55
- "meta",
56
- ]);
57
-
58
- export function isHarnessPlanningAgent(agentType: string): boolean {
59
- const id = agentType.replace(/^harness\//, "");
60
- return id.startsWith("planning/");
61
- }
62
-
63
- export function classifyHarnessAgent(agentType: string): HarnessAgentKind {
64
- const id = agentType.replace(/^harness\//, "");
65
- if (id.startsWith("planning/")) {
66
- return "planner";
67
- }
68
- switch (id) {
69
- case "executor":
70
- return "executor";
71
- case "evaluator":
72
- return "evaluator";
73
- case "adversary":
74
- return "adversary";
75
- case "tie-breaker":
76
- return "tie_breaker";
77
- case "meta-optimizer":
78
- return "meta";
79
- case "trace-librarian":
80
- return "trace";
81
- case "incident-recorder":
82
- return "incident";
83
- default:
84
- return agentType.startsWith("harness/") ? "other" : "other";
85
- }
86
- }
87
-
88
- export function isHarnessPackageAgent(agentType: string): boolean {
89
- return agentType.startsWith("harness/");
90
- }
91
-
92
- export function evaluateHarnessSubagentToolCall(
93
- toolName: string,
94
- input: Record<string, unknown> | undefined,
95
- agentType: string,
96
- ): ToolCallDecision {
97
- const base = evaluateSubagentToolCall(toolName, agentType);
98
- if (base.action === "block") {
99
- return base;
100
- }
101
-
102
- if (!isHarnessPackageAgent(agentType)) {
103
- if (
104
- isSubmitToolName(toolName) &&
105
- process.env.PI_HARNESS_SUBPROCESS !== "1"
106
- ) {
107
- return {
108
- action: "block",
109
- reason:
110
- "harness-subagent-policy: submit_* tools are subprocess-only; parent orchestrator must use harness_artifact_ready and write_harness_yaml for merges.",
111
- };
112
- }
113
- return { action: "allow" };
114
- }
115
-
116
- if (isSubmitToolName(toolName)) {
117
- if (process.env.PI_HARNESS_SUBPROCESS !== "1") {
118
- return {
119
- action: "block",
120
- reason:
121
- "harness-subagent-policy: submit_* tools are not available in the parent harness session.",
122
- };
123
- }
124
- if (toolName === "submit_human_required") {
125
- const kind = classifyHarnessAgent(agentType);
126
- if (kind === "executor") {
127
- return {
128
- action: "block",
129
- reason:
130
- "submit_human_required is not available for harness/executor.",
131
- };
132
- }
133
- return { action: "allow" };
134
- }
135
- const allowed = SUBMIT_TOOLS_BY_AGENT[agentType];
136
- if (!allowed?.has(toolName)) {
137
- return {
138
- action: "block",
139
- reason: `harness-subagent-policy: ${toolName} is not allowed for ${agentType}.`,
140
- };
141
- }
142
- return { action: "allow" };
143
- }
144
-
145
- const kind = classifyHarnessAgent(agentType);
146
- if (!READ_ONLY_KINDS.has(kind)) {
147
- return { action: "allow" };
148
- }
149
-
150
- if (toolName === "create_plan" || toolName === "approve_plan") {
151
- return {
152
- action: "block",
153
- reason: `harness-subagent-policy: ${toolName} is parent-orchestrator only (not available in subagents).`,
154
- };
155
- }
156
-
157
- if (MUTATING_TOOLS.has(toolName)) {
158
- return {
159
- action: "block",
160
- reason: `harness-subagent-policy: ${toolName} blocked for harness/${kind} (read-only phase agent).`,
161
- };
162
- }
163
-
164
- if (toolName === "bash") {
165
- const command = String(input?.command ?? "");
166
- if (
167
- kind === "planner" &&
168
- command &&
169
- PLANNING_ARTIFACT_JSON_WRITE.test(command)
170
- ) {
171
- return {
172
- action: "block",
173
- reason:
174
- "harness-subagent-policy: artifacts must be YAML only — use submit_* (e.g. submit_hypothesis_brief → artifacts/hypothesis.yaml), not bash writes to .json.",
175
- };
176
- }
177
- if (command && isMutatingBash(command)) {
178
- return {
179
- action: "block",
180
- reason: `harness-subagent-policy: mutating bash blocked for harness/${kind}.`,
181
- };
182
- }
183
- if (
184
- command &&
185
- isHarnessPlanningAgent(agentType) &&
186
- PLANNING_BASH_DENY_PATTERNS.some((p) => p.test(command))
187
- ) {
188
- return {
189
- action: "block",
190
- reason:
191
- "harness-subagent-policy: planning scouts may use read-only graphify/sg/ccc commands only.",
192
- };
193
- }
194
- }
195
-
196
- const ctxPhase =
197
- (harnessSubagentPhaseHint(agentType) as HarnessPhase | null) ?? "plan";
198
- const ctxDecision = evaluateContextModeMutation(
199
- toolName,
200
- input ?? {},
201
- ctxPhase,
202
- { aborted: false, readOnlyAgent: true },
203
- );
204
- if (ctxDecision.blocked) {
205
- return {
206
- action: "block",
207
- reason: ctxDecision.reason.replace(
208
- /^policy-gate:/,
209
- "harness-subagent-policy:",
210
- ),
211
- };
212
- }
213
-
214
- return { action: "allow" };
215
- }
216
-
217
- export { isSubmitToolName } from "./harness-subagent-submit-registry.js";
218
-
219
- export function harnessSubagentPhaseHint(agentType: string): string | null {
220
- if (isHarnessPlanningAgent(agentType)) {
221
- return "plan";
222
- }
223
- const kind = classifyHarnessAgent(agentType);
224
- switch (kind) {
225
- case "planner":
226
- return "plan";
227
- case "executor":
228
- return "execute";
229
- case "evaluator":
230
- return "evaluate";
231
- case "adversary":
232
- return "adversary";
233
- default:
234
- return null;
235
- }
236
- }