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
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Safe cross-platform spawn utilities
3
+ *
4
+ * Provides both sync (deprecated) and async versions for gradual migration.
5
+ *
6
+ * Async version features:
7
+ * - Non-blocking execution
8
+ * - Proper process cleanup on timeout (no zombies)
9
+ * - Batch execution with concurrency limits
10
+ * - AbortSignal support for cancellation
11
+ *
12
+ * Migration guide:
13
+ * - Change: safeSpawn(cmd, args, opts)
14
+ * - To: await safeSpawnAsync(cmd, args, opts)
15
+ */
16
+
17
+ import { type SpawnOptions, spawn, spawnSync } from "node:child_process";
18
+
19
+ export interface SpawnResult {
20
+ stdout: string;
21
+ stderr: string;
22
+ status: number | null;
23
+ error?: Error;
24
+ }
25
+
26
+ export interface SafeSpawnOptions {
27
+ timeout?: number;
28
+ cwd?: string;
29
+ env?: NodeJS.ProcessEnv;
30
+ signal?: AbortSignal;
31
+ }
32
+
33
+ // ============================================================================
34
+ // INTERNAL HELPERS
35
+ // ============================================================================
36
+
37
+ /**
38
+ * Escape a single argument for cmd.exe when shell:true is required.
39
+ * Only used on Windows to avoid DEP0190 (args+shell concatenation warning).
40
+ */
41
+ function cmdEscapeArg(arg: string): string {
42
+ if (!/[\s"&|<>^()]/.test(arg)) return arg;
43
+ return `"${arg.replace(/"/g, '""')}"`;
44
+ }
45
+
46
+ // ============================================================================
47
+ // ASYNC VERSION (Recommended - Non-blocking)
48
+ // ============================================================================
49
+
50
+ /**
51
+ * Async spawn with timeout and proper process cleanup.
52
+ *
53
+ * Unlike spawnSync, this:
54
+ * - Doesn't block the event loop
55
+ * - Kills the process on timeout (preventing zombies)
56
+ * - Supports cancellation via AbortSignal
57
+ *
58
+ * @example
59
+ * const result = await safeSpawnAsync("npm", ["test"], { timeout: 30000 });
60
+ * if (result.error) console.error("Failed:", result.error);
61
+ */
62
+ export async function safeSpawnAsync(
63
+ command: string,
64
+ args: string[],
65
+ options?: SafeSpawnOptions,
66
+ ): Promise<SpawnResult> {
67
+ const timeout = options?.timeout ?? 30000;
68
+ const abortSignal = options?.signal;
69
+
70
+ return new Promise((resolve) => {
71
+ // Check for early abort
72
+ if (abortSignal?.aborted) {
73
+ resolve({
74
+ stdout: "",
75
+ stderr: "",
76
+ status: null,
77
+ error: new Error("Spawn aborted before start"),
78
+ });
79
+ return;
80
+ }
81
+
82
+ let stdout = "";
83
+ let stderr = "";
84
+ let timedOut = false;
85
+ let killed = false;
86
+
87
+ // Spawn the process (non-blocking)
88
+ // On Windows, use shell mode for .cmd files (like pyright, biome).
89
+ // Bake args into the command string when shell:true to avoid DEP0190.
90
+ const isWindows = process.platform === "win32";
91
+ const spawnCmd = isWindows
92
+ ? [command, ...args.map(cmdEscapeArg)].join(" ")
93
+ : command;
94
+ const spawnArgs = isWindows ? [] : args;
95
+ const child = spawn(spawnCmd, spawnArgs, {
96
+ cwd: options?.cwd,
97
+ env: { ...process.env, ...options?.env },
98
+ windowsHide: true,
99
+ shell: isWindows,
100
+ });
101
+
102
+ // On Windows, shell:true means child.pid is cmd.exe — child.kill() only
103
+ // kills the wrapper, leaving the actual subprocess (e.g. knip/npx) alive
104
+ // as an orphan. Use taskkill /F /T to kill the full process tree instead.
105
+ const killTree = () => {
106
+ if (isWindows && child.pid && child.pid > 0) {
107
+ const taskkill = `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\taskkill.exe`;
108
+ try {
109
+ spawn(taskkill, ["/F", "/T", "/PID", String(child.pid)], {
110
+ shell: false,
111
+ windowsHide: true,
112
+ });
113
+ } catch {
114
+ child.kill("SIGKILL");
115
+ }
116
+ } else {
117
+ child.kill("SIGTERM");
118
+ setTimeout(() => {
119
+ if (!child.killed) child.kill("SIGKILL");
120
+ }, 1000);
121
+ }
122
+ };
123
+
124
+ // Handle abort signal
125
+ const onAbort = () => {
126
+ if (!killed && !child.killed) {
127
+ killed = true;
128
+ killTree();
129
+ }
130
+ };
131
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
132
+
133
+ // Collect output
134
+ child.stdout?.setEncoding("utf-8");
135
+ child.stderr?.setEncoding("utf-8");
136
+ child.stdout?.on("data", (data) => (stdout += data));
137
+ child.stderr?.on("data", (data) => (stderr += data));
138
+
139
+ // Timeout handling - KILL the process, don't just abandon it
140
+ const timeoutId = setTimeout(() => {
141
+ timedOut = true;
142
+ if (!killed && !child.killed) {
143
+ killed = true;
144
+ killTree();
145
+ }
146
+ }, timeout);
147
+
148
+ // Process completion
149
+ child.on("close", (code, signal) => {
150
+ clearTimeout(timeoutId);
151
+ abortSignal?.removeEventListener("abort", onAbort);
152
+
153
+ if (timedOut) {
154
+ resolve({
155
+ stdout,
156
+ stderr,
157
+ status: null,
158
+ error: new Error(
159
+ `Process timed out after ${timeout}ms (killed with ${signal || "SIGTERM"})`,
160
+ ),
161
+ });
162
+ } else if (signal) {
163
+ resolve({
164
+ stdout,
165
+ stderr,
166
+ status: null,
167
+ error: new Error(`Process killed by signal: ${signal}`),
168
+ });
169
+ } else {
170
+ resolve({ stdout, stderr, status: code });
171
+ }
172
+ });
173
+
174
+ child.on("error", (err) => {
175
+ clearTimeout(timeoutId);
176
+ abortSignal?.removeEventListener("abort", onAbort);
177
+ resolve({ stdout, stderr, status: null, error: err });
178
+ });
179
+ });
180
+ }
181
+
182
+ /**
183
+ * Run multiple commands concurrently with limited concurrency.
184
+ *
185
+ * This prevents resource contention when running many linters.
186
+ * Uses async spawn with concurrency limiting built-in.
187
+ *
188
+ * @example
189
+ * const results = await safeSpawnBatch([
190
+ * { command: "biome", args: ["check", "file.ts"] },
191
+ * { command: "ruff", args: ["check", "file.py"] },
192
+ * ], 3); // Max 3 concurrent
193
+ */
194
+ export async function safeSpawnBatch(
195
+ commands: Array<{
196
+ command: string;
197
+ args: string[];
198
+ options?: SafeSpawnOptions;
199
+ }>,
200
+ concurrency = 3,
201
+ ): Promise<SpawnResult[]> {
202
+ const results: SpawnResult[] = [];
203
+
204
+ // Process in batches to limit concurrent processes
205
+ for (let i = 0; i < commands.length; i += concurrency) {
206
+ const batch = commands.slice(i, i + concurrency);
207
+ const batchResults = await Promise.all(
208
+ batch.map(({ command, args, options }) =>
209
+ safeSpawnAsync(command, args, options),
210
+ ),
211
+ );
212
+ results.push(...batchResults);
213
+ }
214
+
215
+ return results;
216
+ }
217
+
218
+ /**
219
+ * Check if a command is available in PATH (async version)
220
+ */
221
+ export async function isCommandAvailableAsync(
222
+ command: string,
223
+ ): Promise<boolean> {
224
+ const finder = process.platform === "win32" ? "where" : "which";
225
+ const result = await safeSpawnAsync(finder, [command], { timeout: 5000 });
226
+ return result.status === 0 && !result.error;
227
+ }
228
+
229
+ /**
230
+ * Find the full path to a command (async version)
231
+ */
232
+ export async function findCommandAsync(
233
+ command: string,
234
+ ): Promise<string | null> {
235
+ const finder = process.platform === "win32" ? "where" : "which";
236
+ const result = await safeSpawnAsync(finder, [command], { timeout: 5000 });
237
+
238
+ if (result.status !== 0 || result.error) return null;
239
+
240
+ // Take first line (first match)
241
+ return result.stdout.trim().split("\n")[0] || null;
242
+ }
243
+
244
+ // ============================================================================
245
+ // SYNC VERSION (Deprecated - Blocking, for backward compatibility)
246
+ // ============================================================================
247
+
248
+ /**
249
+ * Escape an argument for Windows shell execution.
250
+ * Handles spaces, quotes, $variables, and special characters.
251
+ */
252
+ function escapeWindowsArg(arg: string): string {
253
+ if (arg.includes("$")) {
254
+ return `'${arg.replace(/'/g, "'\\''")}'`;
255
+ }
256
+ if (!/[\s"]/.test(arg)) return arg;
257
+ return `"${arg.replace(/"/g, '""')}"`;
258
+ }
259
+
260
+ /**
261
+ * Construct a command string for Windows shell execution.
262
+ */
263
+ function buildWindowsCommand(command: string, args: string[]): string {
264
+ const escapedArgs = args.map(escapeWindowsArg).join(" ");
265
+ return `${command} ${escapedArgs}`;
266
+ }
267
+
268
+ /**
269
+ * ⚠️ DEPRECATED: Use safeSpawnAsync instead.
270
+ *
271
+ * This blocks the entire Node.js event loop until the process exits.
272
+ * If the process hangs, pi will freeze.
273
+ *
274
+ * Kept for backward compatibility during migration.
275
+ */
276
+ export function safeSpawn(
277
+ command: string,
278
+ args: string[],
279
+ options?: SafeSpawnOptions,
280
+ ): SpawnResult {
281
+ if (process.platform === "win32") {
282
+ // shell:true here is justified only because this deprecated sync function
283
+ // predates safeSpawnAsync. It will be eliminated when safeSpawn is removed.
284
+ const fullCommand = buildWindowsCommand(command, args);
285
+ const result = spawnSync(fullCommand, {
286
+ ...(options as SpawnOptions),
287
+ encoding: "utf-8",
288
+ shell: true,
289
+ windowsHide: true,
290
+ });
291
+
292
+ return {
293
+ stdout: result.stdout?.toString() || "",
294
+ stderr: result.stderr?.toString() || "",
295
+ status: result.status,
296
+ error: result.error,
297
+ };
298
+ }
299
+
300
+ const result = spawnSync(command, args, {
301
+ ...(options as SpawnOptions),
302
+ encoding: "utf-8",
303
+ shell: false,
304
+ windowsHide: true,
305
+ });
306
+
307
+ return {
308
+ stdout: result.stdout?.toString() || "",
309
+ stderr: result.stderr?.toString() || "",
310
+ status: result.status,
311
+ error: result.error,
312
+ };
313
+ }
314
+
315
+ /**
316
+ * Check if a command is available in PATH (sync version - deprecated)
317
+ * @deprecated Use isCommandAvailableAsync
318
+ */
319
+ export function isCommandAvailable(command: string): boolean {
320
+ const result = safeSpawn(
321
+ process.platform === "win32" ? "where" : "which",
322
+ [command],
323
+ { timeout: 5000 },
324
+ );
325
+ return result.status === 0;
326
+ }
327
+
328
+ /**
329
+ * Find the full path to a command (sync version - deprecated)
330
+ * @deprecated Use findCommandAsync
331
+ */
332
+ export function findCommand(command: string): string | null {
333
+ const finder = process.platform === "win32" ? "where" : "which";
334
+ const result = safeSpawn(finder, [command], { timeout: 5000 });
335
+
336
+ if (result.status !== 0) return null;
337
+
338
+ return result.stdout.trim().split("\n")[0] || null;
339
+ }
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Content-level secrets scanner
3
+ *
4
+ * Scans file content for potential secret patterns before write.
5
+ * Works on all file types via regex matching.
6
+ *
7
+ * Detected patterns:
8
+ * - Stripe/OpenAI keys (sk-*)
9
+ * - GitHub tokens (ghp_*, gho_*, github_pat_*)
10
+ * - AWS keys (AKIA*)
11
+ * - Slack tokens (xoxp-*, xoxb-*)
12
+ * - Private keys (BEGIN PRIVATE KEY)
13
+ * - Generic API key/password patterns
14
+ */
15
+
16
+ import { isTestFile } from "./file-utils.js";
17
+
18
+ interface SecretPattern {
19
+ pattern: RegExp;
20
+ name: string;
21
+ message: string;
22
+ }
23
+
24
+ const SAFE_HEADER_KEYS = new Set([
25
+ "user-agent",
26
+ "accept",
27
+ "accept-language",
28
+ "accept-encoding",
29
+ "content-type",
30
+ "content-length",
31
+ "origin",
32
+ "referer",
33
+ "host",
34
+ "connection",
35
+ "cache-control",
36
+ "pragma",
37
+ "x-requested-with",
38
+ ]);
39
+
40
+ function extractHeaderKey(line: string): string | null {
41
+ const m = line.match(/["']([A-Za-z][A-Za-z0-9-]{0,63})["']\s*:\s*["'][^"']+/);
42
+ if (!m) return null;
43
+ return m[1].toLowerCase();
44
+ }
45
+
46
+ function shouldIgnorePatternMatch(line: string, patternName: string): boolean {
47
+ // Ignore obvious non-secret HTTP header literals such as "User-Agent".
48
+ if (
49
+ patternName === "hardcoded-secret" ||
50
+ patternName === "hardcoded-password"
51
+ ) {
52
+ const key = extractHeaderKey(line);
53
+ if (key && SAFE_HEADER_KEYS.has(key)) {
54
+ return true;
55
+ }
56
+ }
57
+
58
+ return false;
59
+ }
60
+
61
+ /**
62
+ * Check if a string value looks like an environment variable name.
63
+ * Env var names typically use UPPERCASE_SNAKE_CASE.
64
+ * Used to filter false positives like: api_key = "FIREWORKS_API_KEY"
65
+ * where the value is just referencing the env var name, not a secret.
66
+ */
67
+ function looksLikeEnvVarName(value: string): boolean {
68
+ // Must be all uppercase with underscores (no lowercase letters)
69
+ // Must start with a letter and contain at least one underscore
70
+ return /^[A-Z][A-Z0-9_]*$/.test(value) && value.includes("_");
71
+ }
72
+
73
+ /**
74
+ * Extract the quoted value from a hardcoded secret pattern match.
75
+ * Returns null if no quoted value found.
76
+ */
77
+ function extractQuotedValue(line: string): string | null {
78
+ // Match content inside quotes after : or =
79
+ const match = line.match(/[:=]\s*["']([^"']+)["']/);
80
+ return match ? match[1] : null;
81
+ }
82
+
83
+ // Patterns ordered by specificity - first match wins per line
84
+ const SECRET_PATTERNS: SecretPattern[] = [
85
+ // High-confidence: specific key prefixes
86
+ {
87
+ pattern: /sk-[a-zA-Z0-9-]{20,}/g,
88
+ name: "stripe-openai-key",
89
+ message: "Possible Stripe or OpenAI API key (sk-*)",
90
+ },
91
+ {
92
+ pattern: /ghp_[a-zA-Z0-9]{36}/g,
93
+ name: "github-personal-token",
94
+ message: "GitHub personal access token (ghp_*)",
95
+ },
96
+ {
97
+ pattern: /gho_[a-zA-Z0-9]{36}/g,
98
+ name: "github-oauth-token",
99
+ message: "GitHub OAuth token (gho_*)",
100
+ },
101
+ {
102
+ pattern: /github_pat_[a-zA-Z_]{82}/g,
103
+ name: "github-fine-grained-pat",
104
+ message: "GitHub fine-grained PAT (github_pat_*)",
105
+ },
106
+ {
107
+ pattern: /AKIA[0-9A-Z]{16}/g,
108
+ name: "aws-access-key",
109
+ message: "AWS access key ID (AKIA*)",
110
+ },
111
+ {
112
+ pattern: /xox[bp]-[a-zA-Z0-9]{10,}/g,
113
+ name: "slack-token",
114
+ message: "Slack token (xoxb-*/xoxp-*)",
115
+ },
116
+ {
117
+ pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE KEY-----/g,
118
+ name: "private-key",
119
+ message: "Private key material detected",
120
+ },
121
+ // Medium-confidence: quoted credentials
122
+ {
123
+ pattern: /password\s*[:=]\s*["'][^"']{4,}["']/gi,
124
+ name: "hardcoded-password",
125
+ message: "Possible hardcoded password",
126
+ },
127
+ {
128
+ pattern:
129
+ /\b(secret|api_?key|token|access_?key)\b\s*[:=]\s*["']([a-zA-Z0-9_./-]{8,})["']/gi,
130
+ name: "hardcoded-secret",
131
+ message: "Possible hardcoded secret or API key",
132
+ },
133
+ // .env format: KEY=VALUE (no quotes)
134
+ {
135
+ pattern:
136
+ /^(?:API_?KEY|SECRET|TOKEN|PASSWORD|AWS_?ACCESS_?KEY)\s*=\s*\S{8,}/gim,
137
+ name: "env-file-secret",
138
+ message: "Possible secret in .env format",
139
+ },
140
+ ];
141
+
142
+ export interface SecretFinding {
143
+ line: number;
144
+ message: string;
145
+ }
146
+
147
+ /**
148
+ * Scan content for potential secrets
149
+ * Returns findings with line numbers.
150
+ * Skips test files to avoid false positives.
151
+ */
152
+ export function scanForSecrets(
153
+ content: string,
154
+ filePath?: string,
155
+ ): SecretFinding[] {
156
+ // Skip test files — secrets in tests are usually fake/test values
157
+ if (filePath && isTestFile(filePath)) {
158
+ return [];
159
+ }
160
+
161
+ const findings: SecretFinding[] = [];
162
+ const lines = content.split("\n");
163
+
164
+ for (let i = 0; i < lines.length; i++) {
165
+ const line = lines[i];
166
+ for (const pattern of SECRET_PATTERNS) {
167
+ // Reset lastIndex before each test (important for global regex)
168
+ const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags);
169
+ const match = regex.exec(line);
170
+ if (match) {
171
+ if (shouldIgnorePatternMatch(line, pattern.name)) {
172
+ continue;
173
+ }
174
+ // For hardcoded-secret pattern, check if the value looks like an env var name
175
+ // This prevents false positives like: api_key = "FIREWORKS_API_KEY"
176
+ if (pattern.name === "hardcoded-secret") {
177
+ const value = extractQuotedValue(line);
178
+ if (value && looksLikeEnvVarName(value)) {
179
+ continue; // Skip - just referencing env var name, not a secret
180
+ }
181
+ }
182
+ findings.push({
183
+ line: i + 1,
184
+ message: pattern.message,
185
+ });
186
+ break; // One finding per line
187
+ }
188
+ }
189
+ }
190
+
191
+ return findings;
192
+ }
193
+
194
+ /**
195
+ * Format secrets findings for terminal output
196
+ */
197
+ export function formatSecrets(
198
+ findings: SecretFinding[],
199
+ filePath: string,
200
+ ): string {
201
+ if (findings.length === 0) return "";
202
+
203
+ const lines = [
204
+ `🔴 STOP — ${findings.length} potential secret(s) in ${filePath}:`,
205
+ ];
206
+ for (const f of findings.slice(0, 5)) {
207
+ lines.push(` L${f.line}: ${f.message}`);
208
+ }
209
+ if (findings.length > 5) {
210
+ lines.push(` ... and ${findings.length - 5} more`);
211
+ }
212
+ lines.push(" → Remove before continuing. Use env vars instead.");
213
+ return lines.join("\n");
214
+ }