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
@@ -14,7 +14,6 @@ Bootstraps the complete ultimate-pi agentic harness: Graphify knowledge graph, C
14
14
  | Pitfall | Correct approach |
15
15
  |---------|------------------|
16
16
  | `UP_PKG="$(pwd)"` in an **external** repo | Wrong — scripts live in the npm package. Resolve via `harness-resolve-up-pkg.mjs` (see Step 0). |
17
- | Provider detection from `OPENAI_*` / `ANTHROPIC_*` env only | Wrong for pi users — keys live in `~/.pi/agent/auth.json`. Use `harness-generate-model-router.mjs` (Pi `ModelRegistry.getAvailable()`). |
18
17
  | Re-running 2.1–2.8 manually after CLI verify | Wasteful — trust `harness-cli-verify.sh` output; only fix reported ✗ lines. |
19
18
  | Overwriting `AGENTS.md` after graphify | Graphify appends a section — **merge**, do not replace (Step 4.3). |
20
19
  | `sentrux-rules-sync` without project manifest | Use **`harness-sentrux-bootstrap.mjs`** (Step 4.2) — seeds manifest + idempotent rules sync. |
@@ -141,6 +140,8 @@ python3 "$UP_PKG/.pi/scripts/harness-web.py" scrape "https://example.com" -o .we
141
140
 
142
141
  After pi loads extensions, agents should smoke **`web_search`** once (not `UP_PKG` / `import scrapling` preflight). Example intent: query `ultimate-pi harness`, `limit` 2.
143
142
 
143
+ **WRS subagent models (optional):** set env vars to any Pi `provider/model-id` — `HARNESS_WEB_FAST_MODEL`, `HARNESS_WEB_EXPANDER_MODEL`, `HARNESS_WEB_QUALITY_MODEL` (see **web-retrieval** skill). Add to `.env` via `harness-sync-env.mjs` or export in shell.
144
+
144
145
  - **`--skip-tools`:** skip Step 2 (includes Scrapling verify).
145
146
  - On Linux/WSL, if stealth scrape fails, install browser libs from `harness-cli-verify.sh` output or use `--fast` for static targets.
146
147
 
@@ -154,9 +155,9 @@ bash "$UP_PKG/.pi/scripts/harness-cli-verify.sh"
154
155
  # Reinstall everything: bash "$UP_PKG/.pi/scripts/harness-cli-verify.sh" --force
155
156
  ```
156
157
 
157
- **Required (script must exit 0):** scrapling + harness-web smoke, ctx7, biome, ast-grep (`sg`), sentrux (when harness manifest present).
158
+ **Required (script must exit 0):** scrapling + harness-web smoke, ctx7, ast-grep (`sg`), sentrux (when harness manifest present).
158
159
 
159
- **Warnings allowed:** gh (if not authenticated), agent-browser (if OS libs need manual `sudo apt-get install`), cocoindex-code (empty corpus on tiny repos; first `[full]` install downloads local embedding model).
160
+ **Warnings allowed:** biome (optional; skipped for non-JS/TS repos or if install fails), gh (if not authenticated), agent-browser (if OS libs need manual `sudo apt-get install`), cocoindex-code (empty corpus on tiny repos; first `[full]` install downloads local embedding model).
160
161
 
161
162
  If the script reports **agent-browser shared library errors** on Linux/WSL, run the fix it prints, then re-verify:
162
163
 
@@ -189,7 +190,7 @@ python3 "$UP_PKG/.pi/scripts/harness-web.py" search "query" -o .web/search.json
189
190
  python3 "$UP_PKG/.pi/scripts/harness-web.py" scrape "https://example.com" -o .web/page.md --fast
190
191
  ```
191
192
 
192
- See `.agents/skills/scrapling-web/SKILL.md`.
193
+ See `.agents/skills/web-retrieval/SKILL.md` (install + env).
193
194
 
194
195
  ### 2.2 — ctx7 (Context7 Library Docs + Skills Management)
195
196
 
@@ -251,21 +252,21 @@ ccc status
251
252
 
252
253
  Verify: `ccc doctor` and `ccc search --limit 3 "export function"` (no `--refresh`).
253
254
 
254
- ### 2.5 — biome (Lint + Format Gate)
255
+ ### 2.5 — biome (Optional, JS/TS-focused lint + format)
255
256
 
256
- ```bash
257
- if ! command -v biome &>/dev/null || [ "$FORCE" = "true" ]; then
258
- npm install -g @biomejs/biome
259
- fi
260
- ```
257
+ Biome is **not a hard requirement** for harness setup. Install/use it when the target project is JS/TS (for example, has `package.json` or already uses `biome.json`). For other stacks, skip and use the repo's native formatter/linter.
261
258
 
262
- Check if project already has biome config:
263
259
  ```bash
264
- ls biome.json 2>/dev/null && echo "biome.json found — using project config" || echo "No biome.json using defaults"
260
+ if [ -f package.json ] || [ -f biome.json ]; then
261
+ if ! command -v biome &>/dev/null || [ "$FORCE" = "true" ]; then
262
+ npm install -g @biomejs/biome
263
+ fi
264
+ biome --version
265
+ else
266
+ echo "Skipping biome (non-JS/TS repo; optional tool)"
267
+ fi
265
268
  ```
266
269
 
267
- Verify: `biome --version`
268
-
269
270
  ### 2.6 — ast-grep (AST-Aware Structural Code Search)
270
271
 
271
272
  ```bash
@@ -327,7 +328,14 @@ sentrux plugin add-standard 2>/dev/null || echo "Plugins already installed or fa
327
328
 
328
329
  ## Step 3 — Pi Extension Packages
329
330
 
330
- Bundled extensions load from the installed `ultimate-pi` package. **Session-locked model routing** comes from a **vendored** fork of [`yeliu84/pi-model-router`](https://github.com/yeliu84/pi-model-router) in `vendor/pi-model-router/`, wired through [`.pi/extensions/pi-model-router-harness.ts`](.pi/extensions/pi-model-router-harness.ts). The router picks **one concrete model** when the session starts (from the first user prompt + system prompt complexity), then changes **thinking level only** each turn. The harness **gates** activation on `.pi/model-router.json` (Step **3.5** below) so `router/auto` cannot load prematurely. Attribution: see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) and `vendor/pi-model-router/UPSTREAM_PIN.md`. Maintainer refresh: `npm run vendor:sync-router`.
331
+ Bundled extensions load from the installed `ultimate-pi` package. The harness lens wrapper at `.pi/extensions/harness-lens.ts` loads `.pi/extensions/lib/harness-lens/` for edit autopatch, secrets blocking, deferred format, and LSP tools. Structural search uses shell `sg` (installed globally by setup); architecture gates use Sentrux. See [ADR 0045](.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md).
332
+
333
+ Harness lens findings are **complementary** to Sentrux:
334
+
335
+ - **Harness lens:** fast edit-time and turn-time code feedback; standalone lens widgets/health telemetry are disabled, and findings flow through the harness PostHog telemetry layer.
336
+ - **Sentrux:** architecture-quality signal and gate (`.sentrux/rules.toml`, `sentrux-signal.yaml`, harness review/evaluate inputs).
337
+
338
+ Do not treat harness lens as a replacement for Sentrux. If a future lens change adds architecture-boundary gating that duplicates Sentrux, keep Sentrux authoritative and disable/remove the overlapping lens path.
331
339
 
332
340
  Optionally install the companion lockfile used in development:
333
341
 
@@ -341,51 +349,19 @@ else
341
349
  fi
342
350
  ```
343
351
 
344
- Merge extension entries from `$UP_PKG/.pi/settings.example.json` into this project's `.pi/settings.json` `packages` array (add any missing `npm:…` entries; keep existing user packages). **Do not add** `npm:@yeliu84/pi-model-router` (superseded by the vendored router).
352
+ Merge extension entries from `$UP_PKG/.pi/settings.example.json` into this project's `.pi/settings.json` `packages` array (add any missing `npm:…` entries; keep existing user packages).
345
353
 
346
354
  Verify each package:
347
355
 
348
356
  | Package | Purpose | Phase |
349
357
  |---------|---------|-------|
350
358
  | `@posthog/pi` | Analytics event capture | F0 |
351
- | `pi-lean-ctx` | Context runtime (read/bash/find/grep/MCP bridge) | F0 |
359
+ | `context-mode` | Context runtime and MCP context-saving tools | F0 |
352
360
  | `harness-subagents` (bundled extension) | L4 `subagent` tool, subprocess spawns, package agents | P16 |
353
361
  | Vendored `pi-vcc` (`vendor/pi-vcc`, `.pi/extensions/ultimate-pi-vcc.ts`) | VCC compaction / `vcc_recall` — env-only: `HARNESS_VCC_COMPACTION` (default on), `HARNESS_VCC_DEBUG` | Shipped |
354
- | `pi-model-router` | Vendored (`vendor/`); activates after `.pi/model-router.json` exists | F0 |
355
-
356
- ## Step 3.5 — Model Router Configuration (Dynamic)
357
-
358
- `.pi/model-router.json` is **user-specific** (gitignored). Generate from **Pi authenticated providers** (`~/.pi/agent/auth.json`, OAuth, env) — **not** env-var guessing alone.
359
-
360
- Pi API (see `packages/coding-agent` docs / SDK example `02-custom-model.ts`):
361
-
362
- - `AuthStorage.create()` → credentials store
363
- - `ModelRegistry.create(authStorage)` → registry
364
- - `await modelRegistry.getAvailable()` → models with working auth (same as interactive pi)
365
-
366
- ```bash
367
- # Verify vendored extension source ships with ultimate-pi
368
- ls "$UP_PKG/vendor/pi-model-router/extensions/index.ts" 2>/dev/null \
369
- && echo "✓ vendored pi-model-router" \
370
- || echo "✗ missing vendor/pi-model-router"
371
-
372
- # Generate from Pi registry (skips if .pi/model-router.json exists; --force to regenerate)
373
- node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs"
374
- # Preview only: node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs" --dry-run
375
-
376
- # Merge router defaults after config exists (never adds npm packages — router is vendored)
377
- node "$UP_PKG/.pi/scripts/harness-sync-model-router.mjs"
378
- ```
379
-
380
- If generation prints "No authenticated Pi providers": warn in report — user should run **`/login`** in pi (or `pi login`) then re-run Step 3.5. Do **not** infer providers from `OPENAI_API_KEY` alone; pi sessions often use `opencode-go` via auth.json without those env vars.
381
-
382
- Do NOT block setup. If no config is written, `harness-sync-model-router.mjs` clears a premature `defaultProvider: "router"` in `.pi/settings.json`.
383
-
384
- **Router onboarding** — The vendored extension starts only after `.pi/model-router.json` appears. Running the script above prepares that file plus optional Pi defaults (**`router` / `auto`**, or whatever `defaultProfile` is) via `harness-sync-model-router.mjs` when `defaultProvider` was unset—then **`/reload`**. Generated profiles use **one model SKU per profile**; high/medium/low tiers differ in **thinking** only. Subagents resolve their subprocess model from the **agent system prompt** complexity (same lock rules).
385
-
386
- Manual override: **`/router profile auto`** or **`/router profile opencode-go`** anytime after reload if they changed defaults.
362
+ | Harness lens (`.pi/extensions/harness-lens.ts` → `.pi/extensions/lib/harness-lens/index.ts`) | Edit autopatch, secrets block, deferred format, LSP tools; PostHog lens telemetry; Sentrux remains architecture gate; `sg` is shell-only | F0 |
387
363
 
388
- ## Step 3.6 — Harness agents (package-resolved)
364
+ ## Step 3.5 — Harness agents (package-resolved)
389
365
 
390
366
  `harness-subagents` loads agents from the installed **`ultimate-pi`** package (`$UP_PKG/.pi/agents/**`) with namespaced ids (`harness/running/executor`, `harness/reviewing/evaluator`, `pi-pi/agent-expert`). **Do not copy** agents into the project unless you want a deliberate override.
391
367
 
@@ -500,10 +476,9 @@ Ensure `.gitignore` contains harness runtime entries (see repo root `.gitignore`
500
476
  !.pi/harness/incidents/README.md
501
477
  .pi/harness/debates/*
502
478
  !.pi/harness/debates/README.md
503
- .pi/harness/router/proposals/*
504
479
 
505
- # Model router config (user-specific generated from env)
506
- .pi/model-router.json
480
+ # Harness lens runtime config/cache and local diagnostics state
481
+ .pi/harness/.lens/
507
482
 
508
483
  # sentrux baselines and local meta (rules.toml is committed)
509
484
  .sentrux/*
@@ -564,7 +539,7 @@ Created: $(date +%Y-%m-%d)
564
539
  - .pi/harness/specs/ → Harness contracts and schema docs
565
540
  - .pi/harness/incidents/ → Incident and override records
566
541
  - `.agents/skills/` (npm package) → Harness skills (no copy into `.pi/skills/` needed)
567
- - `.pi/agents/` → Optional per-repo agent overrides (package agents load automatically — see Step 3.6)
542
+ - `.pi/agents/` → Optional per-repo agent overrides (package agents load automatically — see Step 3.5)
568
543
 
569
544
  ## Graphify-First Workflow
570
545
 
@@ -580,7 +555,7 @@ Created: $(date +%Y-%m-%d)
580
555
  - Decisions and incidents in `.pi/harness/` with structured artifacts
581
556
  - `GRAPHIFY_VIZ_NODE_LIMIT=200000 graphify update .` after significant code changes
582
557
  - ast-grep (`sg`) is the default code search tool — use `sg -p 'pattern'` for structural search, never grep for code
583
- - Create `.sg/rules/` for project-wide code quality rules
558
+ - Use shell `sg` for structural search; project-specific ast-grep rule dirs are optional in the **target repo**, not a harness template default
584
559
  ```
585
560
 
586
561
  ## Step 5 — Verification
@@ -627,10 +602,11 @@ print(f'✓ knowledge graph built ({n} nodes)' if n else '✗ graph.json has 0 n
627
602
  " 2>/dev/null || echo "✗ no graph built yet"
628
603
  graphify hook status 2>/dev/null && echo "✓ graphify git hooks installed" || echo "✗ graphify git hooks not installed"
629
604
 
630
- # vendored model router
631
- ls "$UP_PKG/vendor/pi-model-router/extensions/index.ts" 2>/dev/null \
632
- && echo "✓ vendored pi-model-router" || echo "✗ vendor/pi-model-router missing"
633
- ls .pi/model-router.json 2>/dev/null && echo "✓ model-router config" || echo "✗ model-router config"
605
+ # harness lens extension
606
+ ls "$UP_PKG/.pi/extensions/harness-lens.ts" 2>/dev/null \
607
+ && echo "✓ harness lens wrapper" || echo "✗ harness lens wrapper missing"
608
+ ls "$UP_PKG/.pi/extensions/lib/harness-lens/index.ts" 2>/dev/null \
609
+ && echo "✓ harness lens upstream pin" || echo "✗ harness lens upstream pin missing"
634
610
 
635
611
  # raw folder for graphify sources
636
612
  ls -d ./raw 2>/dev/null && echo "✓ ./raw directory exists" || echo "! ./raw directory missing"
@@ -672,13 +648,13 @@ Output summary table:
672
648
  | ctx7 | ✓/✗ | Login: yes/no |
673
649
  | agent-browser | ✓/✗ | Config: .pi/harness/browser.json |
674
650
  | cocoindex-code | ✓/✗ | `ccc status`; index auto-refreshed before harness scouts |
675
- | biome | ✓/✗ | Project config: found/default |
651
+ | biome | ✓/✗/skip | Optional; JS/TS-focused (skip on non-JS/TS stacks) |
676
652
  | ast-grep | ✓/✗ | AST-aware code search (`sg`)
677
653
  | gh CLI | ✓/✗ | Auth: yes/no |
678
654
  | sentrux | ✓/✗ | CLI + plugins; rules via Step 4.2 bootstrap |
679
655
  | Sentrux rules.toml | ✓/✗ | `.sentrux/rules.toml` synced from manifest |
680
- | pi extensions | ✓/✗ | 4 packages |
681
- | model router | ✓/✗ | Package + config verified, activation via `/router profile auto` (or `opencode-go`) |
656
+ | pi extensions | ✓/✗ | bundled extensions + harness lens wrapper |
657
+ | harness lens | ✓/✗ | `.pi/extensions/harness-lens.ts`; PostHog owns lens telemetry; complements Sentrux architecture signal |
682
658
  | `.env` | ✓/✗/ask | Created / keys appended / user declined |
683
659
 
684
660
  | .gitignore | ✓/✗ | entries added (incl. `.env`) |
@@ -728,11 +704,10 @@ Next steps:
728
704
  | gh not installed | Show GitHub CLI install link. Skip label creation. |
729
705
  | pi packages install fail | Show error output. Check npm permissions. |
730
706
  | graph already exists | Report node count. Refresh with `graphify update .` unless user passed `--force`. |
731
- | biome.json missing | Create minimal config. |
707
+ | biome.json missing | No action required. Biome is optional; use project-native tooling. |
732
708
  | settings.json not writable | Warn. Settings won't persist across sessions. |
733
709
  | No internet | Block for tool installs. Continue for graphify-only steps if `--skip-tools`. |
734
710
  | sentrux install fails | Show install script output. Fallback: download from https://github.com/sentrux/sentrux/releases/latest |
735
- | No model-router.json / "No authenticated Pi providers" | Run `/login` in pi, then `node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs" --force` |
736
711
  | UP_PKG not found | `pi install npm:ultimate-pi` or `npm i -g ultimate-pi`; verify with `node "$UP_PKG/.pi/scripts/harness-resolve-up-pkg.mjs"` |
737
712
  | No `.env` at project root | `ask_user` create vs skip; on create: `harness-sync-env.mjs --create-missing` |
738
713
 
@@ -14,7 +14,7 @@ UP_PKG="$(node -p "require('path').dirname(require.resolve('ultimate-pi/package.
14
14
 
15
15
  **Developing this repo** (clone of `ultimate-pi`): from the repo root, `UP_PKG="$(pwd)"` (or the same `require.resolve` after `npm install`).
16
16
 
17
- From **Typescript extensions**, use `resolveHarnessScript()` / `getHarnessPackageRoot()` in `.pi/extensions/lib/harness-paths.ts`.
17
+ From **Typescript extensions**, use `resolveHarnessScript()` / `getHarnessPackageRoot()` in `.pi/lib/harness-paths.ts`.
18
18
 
19
19
  ## Invocations (from the consuming project root)
20
20
 
@@ -29,11 +29,8 @@ From **Typescript extensions**, use `resolveHarnessScript()` / `getHarnessPackag
29
29
  | Sentrux rules drift check (CI) | `node "$UP_PKG/.pi/scripts/sentrux-rules-sync.mjs" --check` |
30
30
  | Sentrux run/review check or gate (root-resolving) | `node "$UP_PKG/.pi/scripts/harness-sentrux-cli.mjs" check` / `gate [--save]` |
31
31
  | Resolve package root (`UP_PKG`) | `node "$UP_PKG/.pi/scripts/harness-resolve-up-pkg.mjs"` |
32
- | Model-router config (Pi auth) | `node "$UP_PKG/.pi/scripts/harness-generate-model-router.mjs"` |
33
32
  | Project `.env` (append-only) | `node "$UP_PKG/.pi/scripts/harness-sync-env.mjs"` (`--create-missing` after user confirms) |
34
- | Model-router / Pi defaults | `harness-sync-model-router.mjs` (Step 3.5 of `/harness-setup`) |
35
- | Vendor router sync (this repo only) | `bash .pi/scripts/vendor-sync-pi-model-router.sh` or `npm run vendor:sync-router` |
36
- | Meta-optimizer (JSONL proposals) | `node "$UP_PKG/.pi/harness/evolution/meta-optimizer.mjs"` |
33
+ | Harness lens extension | `.pi/extensions/harness-lens.ts` → `.pi/lib/harness-lens/index.ts` (loaded by `.pi/extensions`; PostHog owns lens telemetry) |
37
34
 
38
35
  Pass `--force` to shell scripts that support it (e.g. `harness-graphify-bootstrap.sh --force`, `harness-cli-verify.sh --force`).
39
36
 
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ /** Regenerate .pi/harness/web-heuristic-angles.json from shipped Python defaults. */
3
+ import { execFileSync } from "node:child_process";
4
+ import { writeFileSync } from "node:fs";
5
+ import { dirname, join } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const root = join(dirname(fileURLToPath(import.meta.url)), "..", "harness");
9
+ const out = join(root, "web-heuristic-angles.json");
10
+ const py = join(dirname(fileURLToPath(import.meta.url)), "harness_web", "heuristic_angles_shipped.py");
11
+ const json = execFileSync(
12
+ "python3",
13
+ [
14
+ "-c",
15
+ `import json, importlib.util
16
+ spec = importlib.util.spec_from_file_location("shipped", ${JSON.stringify(py)})
17
+ mod = importlib.util.module_from_spec(spec)
18
+ spec.loader.exec_module(mod)
19
+ print(json.dumps(mod.SHIPPED_HEURISTIC_ANGLES, indent=2))`,
20
+ ],
21
+ { encoding: "utf-8" },
22
+ );
23
+ writeFileSync(out, `${json}\n`, "utf-8");
24
+ console.log(`wrote ${out}`);
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generate .pi/harness/agents.policy.yaml from harness agent .md frontmatter + submit registry.
4
+ */
5
+
6
+ import { readFile, writeFile } from "node:fs/promises";
7
+ import { join, dirname } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { parse as parseYaml } from "yaml";
10
+ import { walkAgentsDir } from "../lib/harness-agent-discovery.mjs";
11
+
12
+ const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
13
+ const AGENTS_DIR = join(ROOT, ".pi", "agents");
14
+ const OUT = join(ROOT, ".pi", "harness", "agents.policy.yaml");
15
+
16
+ const SUBMIT_BY_AGENT = {
17
+ "harness/planning/planning-context": ["submit_planning_context"],
18
+ "harness/planning/decompose": ["submit_decomposition_brief", "submit_human_required"],
19
+ "harness/planning/hypothesis": ["submit_hypothesis_brief"],
20
+ "harness/planning/hypothesis-validator": ["submit_hypothesis_validation"],
21
+ "harness/planning/plan-evaluator": ["submit_validation_turn"],
22
+ "harness/planning/plan-adversary": ["submit_adversary_brief"],
23
+ "harness/planning/sprint-contract-auditor": ["submit_sprint_audit"],
24
+ "harness/planning/review-integrator": ["submit_review_round_draft"],
25
+ "harness/planning/implementation-researcher": ["submit_implementation_research"],
26
+ "harness/planning/stack-researcher": ["submit_stack_brief"],
27
+ "harness/planning/execution-plan-author": ["submit_execution_plan_brief"],
28
+ "harness/running/executor": ["submit_executor_handoff"],
29
+ "harness/reviewing/evaluator": ["submit_eval_verdict"],
30
+ "harness/reviewing/adversary": ["submit_adversary_report"],
31
+ "harness/reviewing/tie-breaker": ["submit_human_required"],
32
+ "harness/trace-librarian": ["submit_human_required"],
33
+ "harness/incident-recorder": ["submit_human_required"],
34
+ "harness/sentrux-steward": ["submit_sentrux_manifest_proposal"],
35
+ };
36
+
37
+ function parseFrontmatter(content) {
38
+ const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
39
+ if (!m) return {};
40
+ return parseYaml(m[1]) ?? {};
41
+ }
42
+
43
+ function kindFor(id) {
44
+ if (id.startsWith("harness/planning/")) return "planner";
45
+ if (id === "harness/running/executor") return "executor";
46
+ if (id === "harness/reviewing/evaluator") return "evaluator";
47
+ if (id === "harness/reviewing/adversary") return "adversary";
48
+ if (id === "harness/reviewing/tie-breaker") return "tie_breaker";
49
+ if (id === "harness/trace-librarian") return "trace";
50
+ if (id === "harness/incident-recorder") return "incident";
51
+ if (id === "harness/sentrux-steward" || id === "harness/sentrux-bootstrap")
52
+ return "planner";
53
+ return "other";
54
+ }
55
+
56
+ const KIND_BASE = {
57
+ planner: ["read", "grep", "find", "ls"],
58
+ executor: ["read", "write", "edit", "bash", "grep", "find", "ls"],
59
+ evaluator: ["read", "grep", "find", "ls"],
60
+ adversary: ["read", "grep", "find", "ls"],
61
+ tie_breaker: ["read", "grep", "find", "ls"],
62
+ trace: ["read", "grep", "find", "ls"],
63
+ incident: ["read", "grep", "find", "ls"],
64
+ other: ["read", "grep", "find", "ls"],
65
+ };
66
+
67
+ function csvTools(fm) {
68
+ const raw = fm.tools;
69
+ if (!raw) return [];
70
+ return String(raw)
71
+ .split(",")
72
+ .map((t) => t.trim())
73
+ .filter(Boolean);
74
+ }
75
+
76
+ async function main() {
77
+ const files = new Map();
78
+ walkAgentsDir(AGENTS_DIR, "package", files);
79
+
80
+ const kinds = {
81
+ planner: { tools: KIND_BASE.planner, extensions: false, read_only: true },
82
+ executor: { tools: KIND_BASE.executor, extensions: true, read_only: false },
83
+ evaluator: { tools: KIND_BASE.evaluator, extensions: false, read_only: true },
84
+ adversary: { tools: KIND_BASE.adversary, extensions: false, read_only: true },
85
+ tie_breaker: {
86
+ tools: KIND_BASE.tie_breaker,
87
+ extensions: false,
88
+ read_only: true,
89
+ },
90
+ trace: { tools: KIND_BASE.trace, extensions: false, read_only: true },
91
+ incident: { tools: KIND_BASE.incident, extensions: false, read_only: true },
92
+ other: { tools: KIND_BASE.other, extensions: false, read_only: true },
93
+ };
94
+
95
+ const agents = {};
96
+
97
+ for (const [id, file] of files) {
98
+ if (!id.startsWith("harness/")) continue;
99
+ const fm = parseFrontmatter(file.content);
100
+ const kind = kindFor(id);
101
+ const base = new Set(KIND_BASE[kind] ?? KIND_BASE.other);
102
+ const fromFm = csvTools(fm);
103
+ const submit = SUBMIT_BY_AGENT[id] ?? [];
104
+ const toolsAdd = [...new Set([...fromFm, ...submit])].filter(
105
+ (t) => !base.has(t),
106
+ );
107
+ const entry = { kind };
108
+ if (toolsAdd.length > 0) entry.tools_add = toolsAdd;
109
+ if (fm.extensions === false) entry.extensions = false;
110
+ if (fm.extensions === true) entry.extensions = true;
111
+ if (typeof fm.max_turns === "number") entry.max_turns = fm.max_turns;
112
+ if (typeof fm.thinking === "string") entry.thinking = fm.thinking;
113
+ if (submit.length === 1) entry.submit_tool = submit[0];
114
+ agents[id] = entry;
115
+ }
116
+
117
+ // plan-synthesizer: parent-only, minimal policy for spawn if ever used
118
+ agents["harness/planning/plan-synthesizer"] = {
119
+ kind: "planner",
120
+ tools_add: [
121
+ "submit_decomposition_brief",
122
+ "submit_hypothesis_brief",
123
+ "submit_execution_plan_brief",
124
+ ],
125
+ extensions: false,
126
+ };
127
+
128
+ const doc = {
129
+ apiVersion: "harness.toolkit/v1",
130
+ kinds,
131
+ agents,
132
+ };
133
+
134
+ const yaml = [
135
+ "# Generated/maintained SSOT for harness agent tools (see ADR 0049).",
136
+ "# Regenerate hints: node .pi/scripts/generate-agents-policy-yaml.mjs",
137
+ "",
138
+ ];
139
+ const { stringify } = await import("yaml");
140
+ yaml.push(stringify(doc));
141
+ await writeFile(OUT, yaml.join("\n"), "utf8");
142
+ console.log(`Wrote ${OUT} (${Object.keys(agents).length} harness agents)`);
143
+ }
144
+
145
+ main().catch((err) => {
146
+ console.error(err);
147
+ process.exit(1);
148
+ });
@@ -7,6 +7,7 @@
7
7
  * node .pi/scripts/harness-agents-manifest.mjs --check
8
8
  */
9
9
 
10
+ import { existsSync } from "node:fs";
10
11
  import { readFile, writeFile } from "node:fs/promises";
11
12
  import { join, dirname } from "node:path";
12
13
  import { fileURLToPath } from "node:url";
@@ -15,6 +16,10 @@ import {
15
16
  sha256Content,
16
17
  walkAgentsDir,
17
18
  } from "../lib/harness-agent-discovery.mjs";
19
+ import {
20
+ loadAgentsPolicyMerged,
21
+ packageAgentsPolicyPath,
22
+ } from "../lib/agents-policy.mjs";
18
23
 
19
24
  const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
20
25
  const MANIFEST_PATH = join(ROOT, ".pi", "harness", "agents.manifest.json");
@@ -27,7 +32,7 @@ async function readPackageMeta() {
27
32
  return { name: pkg.name ?? "ultimate-pi", version: pkg.version ?? "0.0.0" };
28
33
  }
29
34
 
30
- function buildManifest(packageFiles, packageName, packageVersion) {
35
+ async function buildManifest(packageFiles, packageName, packageVersion) {
31
36
  const agents = {};
32
37
  for (const f of packageFiles.values()) {
33
38
  agents[f.id] = {
@@ -35,11 +40,17 @@ function buildManifest(packageFiles, packageName, packageVersion) {
35
40
  sha256: sha256Content(f.content),
36
41
  };
37
42
  }
43
+ const policyPath = packageAgentsPolicyPath(ROOT);
44
+ let policy_sha256;
45
+ if (existsSync(policyPath)) {
46
+ policy_sha256 = sha256Content(await readFile(policyPath, "utf-8"));
47
+ }
38
48
  return {
39
49
  schema_version: "1.0.0",
40
50
  package: packageName,
41
51
  package_version: packageVersion,
42
52
  generated_at: new Date().toISOString(),
53
+ ...(policy_sha256 ? { policy_sha256 } : {}),
43
54
  agents,
44
55
  };
45
56
  }
@@ -68,6 +79,37 @@ function getDriftReport(manifest, packageFiles) {
68
79
  return { ok: items.length === 0, items };
69
80
  }
70
81
 
82
+ function frontmatterHasToolLists(content) {
83
+ const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
84
+ if (!m) return false;
85
+ return /^tools:/m.test(m[1]) || /^disallowed_tools:/m.test(m[1]);
86
+ }
87
+
88
+ function verifyAgentsPolicy(packageFiles) {
89
+ const items = [];
90
+ const policyPath = packageAgentsPolicyPath(ROOT);
91
+ if (!existsSync(policyPath)) {
92
+ return { ok: false, items: [{ id: "*", kind: "missing_agents_policy_yaml" }] };
93
+ }
94
+ const merged = loadAgentsPolicyMerged(ROOT, ROOT);
95
+ for (const [id, file] of packageFiles) {
96
+ if (!id.startsWith("harness/")) continue;
97
+ if (frontmatterHasToolLists(file.content)) {
98
+ items.push({ id, kind: "frontmatter_tools" });
99
+ }
100
+ if (!merged.agents.has(id)) {
101
+ items.push({ id, kind: "missing_policy_entry" });
102
+ }
103
+ }
104
+ for (const id of merged.agents.keys()) {
105
+ if (!id.startsWith("harness/")) continue;
106
+ if (!packageFiles.has(id)) {
107
+ items.push({ id, kind: "orphan_policy_entry" });
108
+ }
109
+ }
110
+ return { ok: items.length === 0, items };
111
+ }
112
+
71
113
  async function loadPackageFiles() {
72
114
  const files = new Map();
73
115
  walkAgentsDir(PACKAGE_AGENTS, "package", files);
@@ -81,7 +123,7 @@ async function main() {
81
123
  const mode = process.argv.includes("--check") ? "check" : "write";
82
124
  const { name, version } = await readPackageMeta();
83
125
  const packageFiles = await loadPackageFiles();
84
- const built = buildManifest(packageFiles, name, version);
126
+ const built = await buildManifest(packageFiles, name, version);
85
127
 
86
128
  if (mode === "write") {
87
129
  await writeFile(MANIFEST_PATH, `${JSON.stringify(built, null, "\t")}\n`, "utf-8");
@@ -107,6 +149,19 @@ async function main() {
107
149
  process.exit(1);
108
150
  }
109
151
 
152
+ const policyCheck = verifyAgentsPolicy(packageFiles);
153
+ if (!policyCheck.ok) {
154
+ for (const item of policyCheck.items) {
155
+ console.error(`policy: ${item.id} (${item.kind})`);
156
+ }
157
+ process.exit(1);
158
+ }
159
+
160
+ if (built.policy_sha256 && onDisk.policy_sha256 !== built.policy_sha256) {
161
+ console.error("policy_sha256 mismatch — regenerate manifest with --write");
162
+ process.exit(1);
163
+ }
164
+
110
165
  if (onDisk.package_version !== version) {
111
166
  console.error(
112
167
  `package_version mismatch: manifest=${onDisk.package_version} package=${version}`,
@@ -114,7 +169,9 @@ async function main() {
114
169
  process.exit(1);
115
170
  }
116
171
 
117
- console.log(`agents.manifest.json OK (${Object.keys(built.agents).length} agents)`);
172
+ console.log(
173
+ `agents.manifest.json OK (${Object.keys(built.agents).length} agents, policy aligned)`,
174
+ );
118
175
  }
119
176
 
120
177
  main().catch((err) => {
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env npx tsx
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { doctorHarnessPolicies } from "../lib/agt/policy-engine.js";
6
+
7
+ const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
8
+ const doc = doctorHarnessPolicies(ROOT);
9
+ if (!doc.ok) {
10
+ console.error("AGT policy doctor failed:");
11
+ for (const e of doc.errors) console.error(` - ${e}`);
12
+ process.exit(1);
13
+ }
14
+ const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf-8")) as {
15
+ files?: string[];
16
+ };
17
+ const files = pkg.files ?? [];
18
+ if (
19
+ !files.some(
20
+ (f: string) =>
21
+ f === ".pi/harness/policies" || f.startsWith(".pi/harness/policies/"),
22
+ )
23
+ ) {
24
+ console.error("package.json files[] missing .pi/harness/policies");
25
+ process.exit(1);
26
+ }
27
+ if (
28
+ !files.includes(".pi/lib") &&
29
+ !files.some((f) => f.startsWith(".pi/lib/"))
30
+ ) {
31
+ console.error("package.json files[] missing .pi/lib (ships .pi/lib/agt)");
32
+ process.exit(1);
33
+ }
34
+ console.log(
35
+ `AGT doctor OK (${doc.loaded.length} policies at ${doc.policyDir})`,
36
+ );
@@ -214,6 +214,11 @@ verify_scrapling() {
214
214
  else
215
215
  fail "harness-web search smoke failed (ddg_html)"
216
216
  fi
217
+ if python3 "$_hw" search-deep "ultimate-pi harness" --expand-heuristic -o .web/verify-search-deep.json --limit 3 2>/dev/null | grep -q wrote; then
218
+ pass "harness-web search-deep smoke (heuristic angles)"
219
+ else
220
+ fail "harness-web search-deep smoke failed"
221
+ fi
217
222
  if python3 "$_hw" scrape "https://example.com" -o .web/verify-page.md --fast 2>/dev/null | grep -q wrote; then
218
223
  pass "harness-web scrape --fast smoke"
219
224
  else
@@ -262,11 +267,18 @@ verify_cocoindex() {
262
267
 
263
268
  verify_biome() {
264
269
  log "[biome]"
265
- npm_global_install "@biomejs/biome" "biome" || { fail "biome npm install"; return; }
270
+ if [ ! -f "${ROOT}/package.json" ] && [ ! -f "${ROOT}/biome.json" ]; then
271
+ warn "biome skipped (non-JS/TS repo detected; optional tool)"
272
+ return
273
+ fi
274
+ npm_global_install "@biomejs/biome" "biome" || {
275
+ warn "biome npm install failed (optional — use your stack's formatter/linter)"
276
+ return
277
+ }
266
278
  if biome --version &>/dev/null; then
267
279
  pass "biome $(biome --version 2>/dev/null | head -1)"
268
280
  else
269
- fail "biome --version failed"
281
+ warn "biome --version failed (optional — use your stack's formatter/linter)"
270
282
  fi
271
283
  }
272
284