ultimate-pi 0.18.1 → 0.19.1

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 (325) 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/.agents/skills/web-retrieval/SKILL.md +163 -0
  5. package/.agents/skills/wiki-autoresearch/SKILL.md +6 -6
  6. package/.pi/PACKAGING.md +4 -4
  7. package/.pi/SYSTEM.md +75 -123
  8. package/.pi/agents/harness/incident-recorder.md +0 -1
  9. package/.pi/agents/harness/planning/decompose.md +0 -2
  10. package/.pi/agents/harness/planning/execution-plan-author.md +0 -2
  11. package/.pi/agents/harness/planning/hypothesis-validator.md +0 -2
  12. package/.pi/agents/harness/planning/hypothesis.md +0 -2
  13. package/.pi/agents/harness/planning/implementation-researcher.md +1 -3
  14. package/.pi/agents/harness/planning/plan-adversary.md +0 -2
  15. package/.pi/agents/harness/planning/plan-evaluator.md +1 -3
  16. package/.pi/agents/harness/planning/planning-context.md +0 -2
  17. package/.pi/agents/harness/planning/review-integrator.md +0 -2
  18. package/.pi/agents/harness/planning/sprint-contract-auditor.md +0 -2
  19. package/.pi/agents/harness/planning/stack-researcher.md +5 -3
  20. package/.pi/agents/harness/reviewing/adversary.md +0 -2
  21. package/.pi/agents/harness/reviewing/evaluator.md +0 -2
  22. package/.pi/agents/harness/reviewing/tie-breaker.md +0 -2
  23. package/.pi/agents/harness/running/executor.md +0 -2
  24. package/.pi/agents/harness/sentrux-bootstrap.md +0 -1
  25. package/.pi/agents/harness/sentrux-steward.md +0 -2
  26. package/.pi/agents/harness/trace-librarian.md +0 -1
  27. package/.pi/agents/harness/web-retrieval/web-answerer.md +35 -0
  28. package/.pi/agents/harness/web-retrieval/web-criteria-verifier.md +28 -0
  29. package/.pi/agents/harness/web-retrieval/web-gap-analyzer.md +31 -0
  30. package/.pi/agents/harness/web-retrieval/web-query-expander-fast.md +34 -0
  31. package/.pi/agents/harness/web-retrieval/web-query-expander.md +60 -0
  32. package/.pi/agents/harness/web-retrieval/web-summarizer.md +18 -0
  33. package/.pi/extensions/agt-kill-switch.ts +57 -0
  34. package/.pi/extensions/agt-prompt-guard.ts +32 -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 +6 -6
  39. package/.pi/extensions/harness-ask-user.ts +7 -7
  40. package/.pi/extensions/harness-debate-tools.ts +26 -42
  41. package/.pi/extensions/harness-lens.ts +94 -0
  42. package/.pi/extensions/harness-plan-approval.ts +11 -11
  43. package/.pi/extensions/harness-run-context.ts +1070 -876
  44. package/.pi/extensions/harness-subagent-governance.ts +8 -0
  45. package/.pi/extensions/harness-subagent-submit.ts +34 -163
  46. package/.pi/extensions/harness-subagents.ts +3 -3
  47. package/.pi/extensions/harness-telemetry.ts +2 -2
  48. package/.pi/extensions/harness-web-guard.ts +2 -1
  49. package/.pi/extensions/harness-web-tools.ts +691 -53
  50. package/.pi/extensions/policy-gate.ts +25 -5
  51. package/.pi/extensions/sentrux-rules-sync.ts +1 -1
  52. package/.pi/extensions/subagent-governance.ts +92 -0
  53. package/.pi/extensions/trace-recorder.ts +1 -1
  54. package/.pi/extensions/{ultimate-pi-vcc.ts → vcc-compaction.ts} +1 -1
  55. package/.pi/harness/README.md +6 -2
  56. package/.pi/harness/agents.manifest.json +46 -25
  57. package/.pi/harness/agents.policy.yaml +309 -0
  58. package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +1 -1
  59. package/.pi/harness/docs/adrs/0035-plan-phase-review-gate.md +1 -1
  60. package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
  61. package/.pi/harness/docs/adrs/0046-agt-policy-engine.md +51 -0
  62. package/.pi/harness/docs/adrs/0047-agt-layered-security.md +39 -0
  63. package/.pi/harness/docs/adrs/0048-tool-call-hook-order.md +25 -0
  64. package/.pi/harness/docs/adrs/0049-agents-policy-manifest.md +36 -0
  65. package/.pi/harness/docs/adrs/0050-agentic-web-retrieval-stack.md +46 -0
  66. package/.pi/harness/docs/adrs/README.md +5 -0
  67. package/.pi/harness/docs/harness-web-search.md +97 -0
  68. package/.pi/harness/env.harness.template +9 -1
  69. package/.pi/harness/evolution/README.md +1 -2
  70. package/.pi/harness/examples/agents.policy.project.yaml +19 -0
  71. package/.pi/harness/examples/policies/custom-deny-bash.yaml +9 -0
  72. package/.pi/harness/examples/web-heuristic-angles.project.yaml +22 -0
  73. package/.pi/harness/policies/bash-denylists.yaml +5 -0
  74. package/.pi/harness/policies/defaults.yaml +51 -0
  75. package/.pi/harness/policies/orchestrator.yaml +18 -0
  76. package/.pi/harness/policies/phases.yaml +10 -0
  77. package/.pi/harness/policies/roles.yaml +5 -0
  78. package/.pi/harness/policies/web-guard.yaml +5 -0
  79. package/.pi/harness/policies/workflow-sequences.yaml +9 -0
  80. package/.pi/harness/sentrux/architecture.manifest.json +26 -4
  81. package/.pi/harness/specs/observation.schema.json +2 -1
  82. package/.pi/harness/web-heuristic-angles.json +278 -0
  83. package/.pi/harness/web-heuristic-angles.yaml +182 -0
  84. package/.pi/lib/agents-policy.d.mts +70 -0
  85. package/.pi/lib/agents-policy.mjs +331 -0
  86. package/.pi/lib/agents-policy.ts +19 -0
  87. package/.pi/lib/agt/audit-run-sink.ts +52 -0
  88. package/.pi/lib/agt/build-evaluation-context.ts +285 -0
  89. package/.pi/lib/agt/config.ts +28 -0
  90. package/.pi/lib/agt/delegation.ts +69 -0
  91. package/.pi/lib/agt/evaluate-policy.ts +56 -0
  92. package/.pi/lib/agt/identity-registry.ts +41 -0
  93. package/.pi/lib/agt/index.ts +55 -0
  94. package/.pi/lib/agt/kill-switch-state.ts +11 -0
  95. package/.pi/lib/agt/legacy-evaluate.ts +101 -0
  96. package/.pi/lib/agt/policy-engine.ts +154 -0
  97. package/.pi/lib/agt/rings.ts +21 -0
  98. package/.pi/lib/agt/sre-hooks.ts +45 -0
  99. package/.pi/lib/agt/trust-run-store.ts +26 -0
  100. package/.pi/lib/agt/workflow-history.ts +29 -0
  101. package/.pi/lib/agt-governance-active.ts +14 -0
  102. package/.pi/lib/agt-tool-guard.ts +78 -0
  103. package/.pi/lib/ask-user/dialog.ts +314 -0
  104. package/.pi/{extensions/lib → lib}/debate-bus-core.ts +10 -10
  105. package/.pi/{extensions/lib → lib}/debate-bus-state.ts +1 -1
  106. package/.pi/{extensions/lib → lib}/extension-load-guard.ts +13 -2
  107. package/.pi/lib/harness-agt-tool-guard.ts +5 -0
  108. package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +1 -1
  109. package/.pi/lib/harness-debate-core-deps.ts +14 -0
  110. package/.pi/lib/harness-debate-workflow-deps.ts +43 -0
  111. package/.pi/lib/harness-lens/.gitattributes +1 -0
  112. package/.pi/lib/harness-lens/clients/edit-autopatch.ts +88 -0
  113. package/.pi/lib/harness-lens/clients/file-kinds.ts +380 -0
  114. package/.pi/lib/harness-lens/clients/file-time.ts +215 -0
  115. package/.pi/lib/harness-lens/clients/file-utils.ts +484 -0
  116. package/.pi/lib/harness-lens/clients/format-service.ts +276 -0
  117. package/.pi/lib/harness-lens/clients/formatters.ts +1000 -0
  118. package/.pi/lib/harness-lens/clients/git-guard.ts +31 -0
  119. package/.pi/lib/harness-lens/clients/indent-retarget.ts +90 -0
  120. package/.pi/lib/harness-lens/clients/installer/index.ts +2368 -0
  121. package/.pi/lib/harness-lens/clients/latency-logger.ts +80 -0
  122. package/.pi/lib/harness-lens/clients/lens-config.ts +43 -0
  123. package/.pi/lib/harness-lens/clients/lens-events.ts +164 -0
  124. package/.pi/lib/harness-lens/clients/lsp/aggregation.ts +91 -0
  125. package/.pi/lib/harness-lens/clients/lsp/client.ts +1466 -0
  126. package/.pi/lib/harness-lens/clients/lsp/config.ts +216 -0
  127. package/.pi/lib/harness-lens/clients/lsp/edits.ts +297 -0
  128. package/.pi/lib/harness-lens/clients/lsp/index.ts +1355 -0
  129. package/.pi/lib/harness-lens/clients/lsp/interactive-install.ts +424 -0
  130. package/.pi/lib/harness-lens/clients/lsp/language.ts +223 -0
  131. package/.pi/lib/harness-lens/clients/lsp/launch.ts +939 -0
  132. package/.pi/lib/harness-lens/clients/lsp/lsp-index.ts +11 -0
  133. package/.pi/lib/harness-lens/clients/lsp/path-utils.ts +12 -0
  134. package/.pi/lib/harness-lens/clients/lsp/server-strategies.ts +81 -0
  135. package/.pi/lib/harness-lens/clients/lsp/server.ts +1971 -0
  136. package/.pi/lib/harness-lens/clients/path-utils.ts +182 -0
  137. package/.pi/lib/harness-lens/clients/pipeline.ts +360 -0
  138. package/.pi/lib/harness-lens/clients/project-profile.ts +117 -0
  139. package/.pi/lib/harness-lens/clients/runtime-agent-end.ts +112 -0
  140. package/.pi/lib/harness-lens/clients/runtime-config.ts +33 -0
  141. package/.pi/lib/harness-lens/clients/runtime-coordinator.ts +186 -0
  142. package/.pi/lib/harness-lens/clients/runtime-tool-result.ts +171 -0
  143. package/.pi/lib/harness-lens/clients/safe-spawn.ts +339 -0
  144. package/.pi/lib/harness-lens/clients/secrets-scanner.ts +214 -0
  145. package/.pi/lib/harness-lens/clients/tool-policy.ts +2072 -0
  146. package/.pi/lib/harness-lens/clients/types.ts +59 -0
  147. package/.pi/lib/harness-lens/clients/widget-state.ts +283 -0
  148. package/.pi/lib/harness-lens/index.ts +532 -0
  149. package/.pi/lib/harness-lens/tools/lsp-diagnostics.ts +706 -0
  150. package/.pi/lib/harness-lens/tools/lsp-navigation.ts +1246 -0
  151. package/.pi/{extensions/lib → lib}/harness-posthog.ts +3 -0
  152. package/.pi/lib/harness-run-context-responses.ts +9 -0
  153. package/.pi/lib/harness-run-context.ts +0 -2
  154. package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +1 -0
  155. package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +1 -1
  156. package/.pi/lib/harness-subagent-auth.ts +81 -0
  157. package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +10 -7
  158. package/.pi/{extensions/lib → lib}/harness-subagent-submit-pipeline.ts +3 -3
  159. package/.pi/lib/harness-subagent-submit-register.ts +163 -0
  160. package/.pi/{extensions/lib → lib}/harness-subagent-submit-registry.ts +1 -37
  161. package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +74 -14
  162. package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
  163. package/.pi/lib/harness-web/artifacts.ts +200 -0
  164. package/.pi/lib/harness-web/cache.ts +369 -0
  165. package/.pi/{extensions/lib → lib}/harness-web/run-cli.ts +42 -2
  166. package/.pi/{extensions/lib → lib}/plan-approval/create-plan.ts +2 -2
  167. package/.pi/{extensions/lib → lib}/plan-approval/format-plan.ts +2 -2
  168. package/.pi/{extensions/lib → lib}/plan-approval/plan-review.ts +162 -201
  169. package/.pi/{extensions/lib → lib}/plan-approval/render.ts +1 -1
  170. package/.pi/{extensions/lib → lib}/plan-approval/resolve-disk.ts +2 -2
  171. package/.pi/{extensions/lib → lib}/plan-approval/types.ts +1 -1
  172. package/.pi/{extensions/lib → lib}/plan-approval/validate.ts +3 -3
  173. package/.pi/{extensions/lib → lib}/plan-debate-envelope.ts +1 -1
  174. package/.pi/{extensions/lib → lib}/plan-debate-gate.ts +1 -1
  175. package/.pi/{extensions/lib → lib}/plan-debate-lane.ts +1 -4
  176. package/.pi/{extensions/lib → lib}/plan-messenger.ts +1 -1
  177. package/.pi/prompts/harness-plan.md +2 -1
  178. package/.pi/prompts/harness-setup.md +40 -65
  179. package/.pi/scripts/README.md +2 -5
  180. package/.pi/scripts/gen-web-heuristic-angles-json.mjs +24 -0
  181. package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
  182. package/.pi/scripts/harness-agents-manifest.mjs +60 -3
  183. package/.pi/scripts/harness-agt-doctor.ts +36 -0
  184. package/.pi/scripts/harness-cli-verify.sh +14 -2
  185. package/.pi/scripts/harness-verify.mjs +191 -39
  186. package/.pi/scripts/harness-web-policy-guard.mjs +3 -3
  187. package/.pi/scripts/harness-web.py +218 -15
  188. package/.pi/scripts/harness_web/deep_search.py +55 -0
  189. package/.pi/scripts/harness_web/evidence_bundle.py +47 -0
  190. package/.pi/scripts/harness_web/find_similar.py +88 -0
  191. package/.pi/scripts/harness_web/heuristic_angles_shipped.py +85 -0
  192. package/.pi/scripts/harness_web/heuristic_config.py +251 -0
  193. package/.pi/scripts/harness_web/highlights.py +47 -0
  194. package/.pi/scripts/harness_web/multi_search.py +59 -0
  195. package/.pi/scripts/harness_web/output.py +24 -0
  196. package/.pi/scripts/harness_web/query_angles.py +116 -0
  197. package/.pi/scripts/harness_web/rank.py +163 -0
  198. package/.pi/scripts/harness_web/scrape.py +30 -0
  199. package/.pi/scripts/tests/test_harness_web_heuristic_config.py +132 -0
  200. package/.pi/scripts/tests/test_harness_web_query_angles.py +45 -0
  201. package/.pi/scripts/tests/test_harness_web_rank.py +56 -0
  202. package/.pi/scripts/validate-plan-dag.mjs +65 -74
  203. package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +2 -2
  204. package/.pi/scripts/vendor-sync-pi-vcc.sh +1 -1
  205. package/.pi/skills/architecture/broker-domain/SKILL.md +65 -0
  206. package/.pi/skills/architecture/cqrs/SKILL.md +63 -0
  207. package/.pi/skills/architecture/event-driven/SKILL.md +60 -0
  208. package/.pi/skills/architecture/hexagonal-ports-adapters/SKILL.md +66 -0
  209. package/.pi/skills/architecture/layered/SKILL.md +68 -0
  210. package/.pi/skills/architecture/microkernel/SKILL.md +62 -0
  211. package/.pi/skills/architecture/microservices/SKILL.md +64 -0
  212. package/.pi/skills/architecture/modular-monolith/SKILL.md +65 -0
  213. package/.pi/skills/architecture/orchestration-driven-soa/SKILL.md +61 -0
  214. package/.pi/skills/architecture/pipeline/SKILL.md +63 -0
  215. package/.pi/skills/architecture/service-based/SKILL.md +64 -0
  216. package/.pi/skills/architecture/service-mesh/SKILL.md +60 -0
  217. package/.pi/skills/architecture/space-based/SKILL.md +60 -0
  218. package/.pi/skills/ast-grep/SKILL.md +40 -321
  219. package/.pi/skills/delivery/debugging-discipline/SKILL.md +36 -0
  220. package/.pi/skills/delivery/documentation-update/SKILL.md +33 -0
  221. package/.pi/skills/delivery/requirements-to-implementation/SKILL.md +34 -0
  222. package/.pi/skills/delivery/risk-based-verification/SKILL.md +43 -0
  223. package/.pi/skills/delivery/tradeoff-analysis/SKILL.md +34 -0
  224. package/.pi/skills/engineering/api-contract-design/SKILL.md +38 -0
  225. package/.pi/skills/engineering/cohesion-coupling/SKILL.md +43 -0
  226. package/.pi/skills/engineering/complexity-control/SKILL.md +31 -0
  227. package/.pi/skills/engineering/defensive-programming/SKILL.md +38 -0
  228. package/.pi/skills/engineering/dependency-management/SKILL.md +29 -0
  229. package/.pi/skills/engineering/domain-modeling/SKILL.md +32 -0
  230. package/.pi/skills/engineering/error-handling/SKILL.md +37 -0
  231. package/.pi/skills/engineering/legacy-code-seams/SKILL.md +35 -0
  232. package/.pi/skills/engineering/naming-and-intent/SKILL.md +29 -0
  233. package/.pi/skills/engineering/refactoring-safe-evolution/SKILL.md +35 -0
  234. package/.pi/skills/engineering/routine-function-design/SKILL.md +34 -0
  235. package/.pi/skills/engineering/small-change-discipline/SKILL.md +35 -0
  236. package/.pi/skills/lsp-navigation/SKILL.md +89 -0
  237. package/.pi/skills/quality/code-review-self-check/SKILL.md +35 -0
  238. package/.pi/skills/quality/privacy-data-handling/SKILL.md +26 -0
  239. package/.pi/skills/quality/security-review/SKILL.md +34 -0
  240. package/.pi/skills/quality/test-strategy/SKILL.md +33 -0
  241. package/.pi/skills/quality/testability-design/SKILL.md +33 -0
  242. package/.pi/skills/systems/concurrency-safety/SKILL.md +32 -0
  243. package/.pi/skills/systems/data-modeling-migrations/SKILL.md +31 -0
  244. package/.pi/skills/systems/observability-instrumentation/SKILL.md +32 -0
  245. package/.pi/skills/systems/performance-measurement/SKILL.md +35 -0
  246. package/.pi/skills/systems/reliability-design/SKILL.md +32 -0
  247. package/.sentrux/rules.toml +20 -4
  248. package/AGENTS.md +7 -2
  249. package/CHANGELOG.md +20 -0
  250. package/README.md +3 -12
  251. package/THIRD_PARTY_NOTICES.md +12 -21
  252. package/package.json +17 -7
  253. package/vendor/pi-subagents/src/agents.ts +45 -1
  254. package/vendor/pi-subagents/src/subagents.ts +866 -811
  255. package/vendor/pi-vcc/src/core/brief.ts +68 -99
  256. package/vendor/pi-vcc/src/core/settings.ts +2 -2
  257. package/.agents/skills/caveman/SKILL.md +0 -67
  258. package/.agents/skills/scrapling-web/SKILL.md +0 -98
  259. package/.pi/agents/harness/meta-optimizer.md +0 -36
  260. package/.pi/extensions/00-posthog-network-bootstrap.ts +0 -11
  261. package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
  262. package/.pi/extensions/lib/harness-subagent-auth.ts +0 -207
  263. package/.pi/extensions/lib/harness-subagent-policy.ts +0 -236
  264. package/.pi/extensions/pi-model-router-harness.ts +0 -42
  265. package/.pi/harness/evolution/meta-optimizer.mjs +0 -99
  266. package/.pi/harness/specs/router-tuning-proposal.schema.json +0 -114
  267. package/.pi/model-router.example.json +0 -36
  268. package/.pi/prompts/harness-critic.md +0 -10
  269. package/.pi/prompts/harness-eval.md +0 -10
  270. package/.pi/prompts/harness-router-tune.md +0 -52
  271. package/.pi/scripts/harness-generate-model-router.mjs +0 -327
  272. package/.pi/scripts/harness-model-router-routing.test.mjs +0 -97
  273. package/.pi/scripts/harness-sync-model-router.mjs +0 -97
  274. package/.pi/scripts/harness_web/__pycache__/__init__.cpython-314.pyc +0 -0
  275. package/.pi/scripts/harness_web/__pycache__/config.cpython-314.pyc +0 -0
  276. package/.pi/scripts/harness_web/__pycache__/output.cpython-314.pyc +0 -0
  277. package/.pi/scripts/harness_web/__pycache__/scrape.cpython-314.pyc +0 -0
  278. package/.pi/scripts/harness_web/__pycache__/search.cpython-314.pyc +0 -0
  279. package/.pi/scripts/harness_web/__pycache__/search_ddg.cpython-314.pyc +0 -0
  280. package/.pi/scripts/harness_web/__pycache__/search_searxng.cpython-314.pyc +0 -0
  281. package/.pi/scripts/vendor-sync-pi-model-router.sh +0 -47
  282. package/vendor/pi-model-router/.prettierignore +0 -4
  283. package/vendor/pi-model-router/.prettierrc +0 -5
  284. package/vendor/pi-model-router/AGENTS.md +0 -39
  285. package/vendor/pi-model-router/LICENSE +0 -21
  286. package/vendor/pi-model-router/README.md +0 -99
  287. package/vendor/pi-model-router/UPSTREAM_PIN.md +0 -10
  288. package/vendor/pi-model-router/docs/ARCHITECTURE.md +0 -54
  289. package/vendor/pi-model-router/extensions/commands.ts +0 -720
  290. package/vendor/pi-model-router/extensions/config.ts +0 -348
  291. package/vendor/pi-model-router/extensions/constants.ts +0 -1
  292. package/vendor/pi-model-router/extensions/index.ts +0 -478
  293. package/vendor/pi-model-router/extensions/provider.ts +0 -580
  294. package/vendor/pi-model-router/extensions/routing.ts +0 -564
  295. package/vendor/pi-model-router/extensions/state.ts +0 -52
  296. package/vendor/pi-model-router/extensions/types.ts +0 -95
  297. package/vendor/pi-model-router/extensions/ui.ts +0 -144
  298. package/vendor/pi-model-router/model-router.example.json +0 -48
  299. package/vendor/pi-model-router/package.json +0 -48
  300. package/vendor/pi-model-router/tsconfig.json +0 -16
  301. /package/.pi/{prompts → harness/docs}/planning-rubrics.md +0 -0
  302. /package/.pi/{extensions/lib → lib}/ask-user/fallback.ts +0 -0
  303. /package/.pi/{extensions/lib → lib}/ask-user/render.ts +0 -0
  304. /package/.pi/{extensions/lib → lib}/ask-user/schema.ts +0 -0
  305. /package/.pi/{extensions/lib → lib}/ask-user/types.ts +0 -0
  306. /package/.pi/{extensions/lib → lib}/ask-user/validate-core.mjs +0 -0
  307. /package/.pi/{extensions/lib → lib}/ask-user/validate.ts +0 -0
  308. /package/.pi/{extensions/lib → lib}/harness-cocoindex-refresh.ts +0 -0
  309. /package/.pi/{extensions/lib → lib}/harness-paths.ts +0 -0
  310. /package/.pi/{extensions/lib → lib}/harness-spawn-budget.ts +0 -0
  311. /package/.pi/{extensions/lib → lib}/harness-vcc-settings.ts +0 -0
  312. /package/.pi/{extensions/lib → lib}/plan-approval/dialog.ts +0 -0
  313. /package/.pi/{extensions/lib → lib}/plan-approval/schema.ts +0 -0
  314. /package/.pi/{extensions/lib → lib}/plan-approval-readiness.ts +0 -0
  315. /package/.pi/{extensions/lib → lib}/plan-debate-eligibility.ts +0 -0
  316. /package/.pi/{extensions/lib → lib}/plan-debate-focus.ts +0 -0
  317. /package/.pi/{extensions/lib → lib}/plan-debate-id.ts +0 -0
  318. /package/.pi/{extensions/lib → lib}/plan-debate-lanes.ts +0 -0
  319. /package/.pi/{extensions/lib → lib}/plan-debate-round-status.ts +0 -0
  320. /package/.pi/{extensions/lib → lib}/plan-debate-write-guard.ts +0 -0
  321. /package/.pi/{extensions/lib → lib}/plan-review-gate.ts +0 -0
  322. /package/.pi/{extensions/lib → lib}/plan-review-integrator-rules.ts +0 -0
  323. /package/.pi/{extensions/lib → lib}/plan-scope-guard.ts +0 -0
  324. /package/.pi/{extensions/lib → lib}/posthog-client.ts +0 -0
  325. /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,207 +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/decompose",
56
- "harness/planning/hypothesis",
57
- "harness/planning/stack-research",
58
- "harness/planning/plan-validator",
59
- ]);
60
-
61
- export function isRoutinePlanningAgent(agentName: string): boolean {
62
- return ROUTINE_PLANNING_AGENT_PATHS.has(agentName);
63
- }
64
-
65
- export function thinkingToRouterTier(
66
- thinking?: string,
67
- agentName?: string,
68
- ): RouterTier {
69
- if (agentName && isRoutinePlanningAgent(agentName)) {
70
- if (thinking === "high" || thinking === "xhigh") return "medium";
71
- return "low";
72
- }
73
- if (thinking === "high" || thinking === "xhigh") return "high";
74
- if (thinking === "off" || thinking === "minimal" || thinking === "low") {
75
- return "low";
76
- }
77
- return "medium";
78
- }
79
-
80
- function loadModelRouterConfig(cwd: string): ModelRouterJson | undefined {
81
- const path = join(cwd, ".pi", "model-router.json");
82
- if (!existsSync(path)) return undefined;
83
- try {
84
- return JSON.parse(readFileSync(path, "utf8")) as ModelRouterJson;
85
- } catch {
86
- return undefined;
87
- }
88
- }
89
-
90
- function resolveRouterProfileEntry(
91
- config: ModelRouterJson,
92
- profileId: string,
93
- ): { profileId: string; profile: RouterProfile } | undefined {
94
- const profiles = config.profiles;
95
- if (!profiles) return undefined;
96
- const candidates = [
97
- profileId,
98
- config.defaultProfile ?? "auto",
99
- "auto",
100
- "opencode-go",
101
- ];
102
- const seen = new Set<string>();
103
- for (const id of candidates) {
104
- if (!id || seen.has(id)) continue;
105
- seen.add(id);
106
- const profile = profiles[id];
107
- if (profile?.high?.model && profile.medium?.model && profile.low?.model) {
108
- return { profileId: id, profile };
109
- }
110
- }
111
- return undefined;
112
- }
113
-
114
- /** Tier from agent system prompt (+ optional task line) for session model lock. */
115
- export function resolveSubagentRouterTier(
116
- cwd: string,
117
- profileId: string,
118
- agent: AgentConfig,
119
- taskSnippet?: string,
120
- ): RouterTier {
121
- const config = loadModelRouterConfig(cwd);
122
- if (config) {
123
- const entry = resolveRouterProfileEntry(config, profileId);
124
- if (entry) {
125
- return resolveTierFromPrompt(
126
- agent.systemPrompt ?? "",
127
- taskSnippet?.trim() ?? "",
128
- entry.profileId,
129
- entry.profile,
130
- config.rules,
131
- config.phaseBias ?? 0.5,
132
- );
133
- }
134
- }
135
- return thinkingToRouterTier(agent.thinking, agent.name);
136
- }
137
-
138
- /** Map router profile tier → concrete `provider/model` from `.pi/model-router.json`. */
139
- export function resolveRouterConcreteModelRef(
140
- cwd: string,
141
- profileId: string,
142
- tier: RouterTier,
143
- ): string | undefined {
144
- const path = join(cwd, ".pi", "model-router.json");
145
- if (!existsSync(path)) return undefined;
146
- const raw = loadModelRouterConfig(cwd);
147
- if (!raw) return undefined;
148
- const entry = resolveRouterProfileEntry(raw, profileId);
149
- const model = entry?.profile[tier]?.model;
150
- return typeof model === "string" && model.includes("/") ? model : undefined;
151
- }
152
-
153
- export interface ConcreteSubagentModel {
154
- modelRef: string;
155
- provider: string;
156
- modelId: string;
157
- routerProfile?: string;
158
- routerTier?: RouterTier;
159
- }
160
-
161
- /**
162
- * Pick the subprocess model ref before resolving API keys.
163
- * Never returns `router/*` — always a concrete provider.
164
- */
165
- export function resolveConcreteSubagentModel(
166
- cwd: string,
167
- parentModel: { provider: string; id: string } | undefined,
168
- agent: AgentConfig,
169
- taskSnippet?: string,
170
- ): ConcreteSubagentModel | undefined {
171
- if (agent.model && !agent.model.startsWith("router/")) {
172
- const parsed = parseModelRef(agent.model);
173
- if (parsed) {
174
- return { modelRef: agent.model, ...parsed };
175
- }
176
- }
177
-
178
- const parentIsRouter = parentModel?.provider === "router";
179
- const agentIsRouter = Boolean(agent.model?.startsWith("router/"));
180
-
181
- if (!parentIsRouter && !agentIsRouter) {
182
- if (parentModel && parentModel.provider !== "router") {
183
- return {
184
- modelRef: `${parentModel.provider}/${parentModel.id}`,
185
- provider: parentModel.provider,
186
- modelId: parentModel.id,
187
- };
188
- }
189
- return undefined;
190
- }
191
-
192
- const profileId =
193
- agentIsRouter && agent.model
194
- ? agent.model.slice("router/".length)
195
- : (parentModel?.id ?? "auto");
196
- const tier = resolveSubagentRouterTier(cwd, profileId, agent, taskSnippet);
197
- const concrete = resolveRouterConcreteModelRef(cwd, profileId, tier);
198
- if (!concrete) return undefined;
199
- const parsed = parseModelRef(concrete);
200
- if (!parsed || parsed.provider === "router") return undefined;
201
- return {
202
- modelRef: concrete,
203
- ...parsed,
204
- routerProfile: profileId,
205
- routerTier: tier,
206
- };
207
- }
@@ -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 "running/executor":
70
- return "executor";
71
- case "reviewing/evaluator":
72
- return "evaluator";
73
- case "reviewing/adversary":
74
- return "adversary";
75
- case "reviewing/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/running/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
- }