ultimate-pi 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. package/.agents/skills/harness-debate-plan/SKILL.md +1 -1
  2. package/.agents/skills/harness-decisions/SKILL.md +2 -3
  3. package/.agents/skills/harness-governor/SKILL.md +6 -5
  4. package/.agents/skills/harness-orchestration/SKILL.md +4 -4
  5. package/.agents/skills/harness-review/SKILL.md +7 -7
  6. package/.agents/skills/harness-sentrux-setup/SKILL.md +4 -3
  7. package/.agents/skills/harness-steer/SKILL.md +1 -1
  8. package/.agents/skills/sentrux/SKILL.md +9 -9
  9. package/.pi/PACKAGING.md +4 -4
  10. package/.pi/SYSTEM.md +54 -120
  11. package/.pi/agents/harness/incident-recorder.md +0 -1
  12. package/.pi/agents/harness/planning/decompose.md +1 -3
  13. package/.pi/agents/harness/planning/execution-plan-author.md +0 -2
  14. package/.pi/agents/harness/planning/hypothesis-validator.md +0 -2
  15. package/.pi/agents/harness/planning/hypothesis.md +0 -2
  16. package/.pi/agents/harness/planning/implementation-researcher.md +0 -2
  17. package/.pi/agents/harness/planning/plan-adversary.md +0 -2
  18. package/.pi/agents/harness/planning/plan-evaluator.md +1 -3
  19. package/.pi/agents/harness/planning/planning-context.md +0 -2
  20. package/.pi/agents/harness/planning/review-integrator.md +0 -2
  21. package/.pi/agents/harness/planning/sprint-contract-auditor.md +0 -2
  22. package/.pi/agents/harness/planning/stack-researcher.md +0 -2
  23. package/.pi/agents/harness/{adversary.md → reviewing/adversary.md} +0 -2
  24. package/.pi/agents/harness/{evaluator.md → reviewing/evaluator.md} +0 -2
  25. package/.pi/agents/harness/{tie-breaker.md → reviewing/tie-breaker.md} +0 -2
  26. package/.pi/agents/harness/{executor.md → running/executor.md} +0 -2
  27. package/.pi/agents/harness/sentrux-bootstrap.md +0 -1
  28. package/.pi/agents/harness/sentrux-steward.md +0 -2
  29. package/.pi/agents/harness/trace-librarian.md +0 -1
  30. package/.pi/extensions/00-harness-project-control.ts +133 -0
  31. package/.pi/extensions/00-posthog-network-bootstrap.ts +1 -1
  32. package/.pi/extensions/agt-kill-switch.ts +57 -0
  33. package/.pi/extensions/agt-prompt-guard.ts +32 -0
  34. package/.pi/extensions/budget-guard.ts +2 -0
  35. package/.pi/extensions/custom-footer.ts +46 -145
  36. package/.pi/extensions/custom-header.ts +1 -1
  37. package/.pi/extensions/custom-system-prompt.ts +1 -1
  38. package/.pi/extensions/debate-orchestrator.ts +7 -5
  39. package/.pi/extensions/harness-ask-user.ts +8 -8
  40. package/.pi/extensions/harness-debate-tools.ts +27 -43
  41. package/.pi/extensions/harness-lens.ts +94 -0
  42. package/.pi/extensions/harness-live-widget.ts +33 -2
  43. package/.pi/extensions/harness-plan-approval.ts +12 -12
  44. package/.pi/extensions/harness-run-context.ts +1214 -852
  45. package/.pi/extensions/harness-subagent-governance.ts +8 -0
  46. package/.pi/extensions/harness-subagent-submit.ts +36 -164
  47. package/.pi/extensions/harness-subagents.ts +4 -4
  48. package/.pi/extensions/harness-telemetry.ts +3 -1
  49. package/.pi/extensions/harness-web-tools.ts +3 -3
  50. package/.pi/extensions/observation-bus.ts +2 -0
  51. package/.pi/extensions/policy-gate.ts +27 -5
  52. package/.pi/extensions/review-integrity.ts +91 -10
  53. package/.pi/extensions/sentrux-rules-sync.ts +3 -1
  54. package/.pi/extensions/subagent-governance.ts +92 -0
  55. package/.pi/extensions/test-diff-integrity.ts +1 -0
  56. package/.pi/extensions/trace-recorder.ts +3 -1
  57. package/.pi/extensions/{ultimate-pi-vcc.ts → vcc-compaction.ts} +1 -1
  58. package/.pi/harness/README.md +6 -2
  59. package/.pi/harness/agents.manifest.json +38 -49
  60. package/.pi/harness/agents.policy.yaml +275 -0
  61. package/.pi/harness/corpus/graphify-kb-updater.config.json +55 -0
  62. package/.pi/harness/docs/adrs/0006-sentrux-dual-layer.md +2 -1
  63. package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +1 -1
  64. package/.pi/harness/docs/adrs/0035-plan-phase-review-gate.md +1 -1
  65. package/.pi/harness/docs/adrs/0044-harness-steer-loop.md +3 -2
  66. package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
  67. package/.pi/harness/docs/adrs/0045-phase-scoped-agent-directories.md +33 -0
  68. package/.pi/harness/docs/adrs/0046-agt-policy-engine.md +51 -0
  69. package/.pi/harness/docs/adrs/0047-agt-layered-security.md +39 -0
  70. package/.pi/harness/docs/adrs/0048-tool-call-hook-order.md +25 -0
  71. package/.pi/harness/docs/adrs/0049-agents-policy-manifest.md +36 -0
  72. package/.pi/harness/docs/adrs/README.md +6 -0
  73. package/.pi/harness/docs/graphify-kb-updater-runbook.md +11 -5
  74. package/.pi/harness/docs/practice-map.md +2 -2
  75. package/.pi/harness/evolution/README.md +1 -2
  76. package/.pi/harness/examples/agents.policy.project.yaml +19 -0
  77. package/.pi/harness/examples/policies/custom-deny-bash.yaml +9 -0
  78. package/.pi/harness/policies/bash-denylists.yaml +5 -0
  79. package/.pi/harness/policies/defaults.yaml +51 -0
  80. package/.pi/harness/policies/orchestrator.yaml +18 -0
  81. package/.pi/harness/policies/phases.yaml +10 -0
  82. package/.pi/harness/policies/roles.yaml +5 -0
  83. package/.pi/harness/policies/web-guard.yaml +5 -0
  84. package/.pi/harness/policies/workflow-sequences.yaml +9 -0
  85. package/.pi/harness/sentrux/architecture.manifest.json +26 -4
  86. package/.pi/harness/specs/harness-spawn-context.schema.json +1 -1
  87. package/.pi/harness/specs/observation.schema.json +2 -1
  88. package/.pi/lib/agents-policy.d.mts +70 -0
  89. package/.pi/lib/agents-policy.mjs +325 -0
  90. package/.pi/lib/agents-policy.ts +19 -0
  91. package/.pi/lib/agt/audit-run-sink.ts +52 -0
  92. package/.pi/lib/agt/build-evaluation-context.ts +285 -0
  93. package/.pi/lib/agt/config.ts +28 -0
  94. package/.pi/lib/agt/delegation.ts +69 -0
  95. package/.pi/lib/agt/evaluate-policy.ts +56 -0
  96. package/.pi/lib/agt/identity-registry.ts +41 -0
  97. package/.pi/lib/agt/index.ts +55 -0
  98. package/.pi/lib/agt/kill-switch-state.ts +11 -0
  99. package/.pi/lib/agt/legacy-evaluate.ts +101 -0
  100. package/.pi/lib/agt/policy-engine.ts +154 -0
  101. package/.pi/lib/agt/rings.ts +21 -0
  102. package/.pi/lib/agt/sre-hooks.ts +45 -0
  103. package/.pi/lib/agt/trust-run-store.ts +26 -0
  104. package/.pi/lib/agt/workflow-history.ts +29 -0
  105. package/.pi/lib/agt-governance-active.ts +14 -0
  106. package/.pi/lib/agt-tool-guard.ts +78 -0
  107. package/.pi/lib/ask-user/dialog.ts +314 -0
  108. package/.pi/{extensions/lib → lib}/debate-bus-core.ts +10 -10
  109. package/.pi/{extensions/lib → lib}/debate-bus-state.ts +1 -1
  110. package/.pi/{extensions/lib → lib}/extension-load-guard.ts +21 -0
  111. package/.pi/lib/harness-agt-tool-guard.ts +5 -0
  112. package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +6 -16
  113. package/.pi/lib/harness-debate-core-deps.ts +14 -0
  114. package/.pi/lib/harness-debate-workflow-deps.ts +43 -0
  115. package/.pi/lib/harness-lens/.gitattributes +1 -0
  116. package/.pi/lib/harness-lens/clients/edit-autopatch.ts +88 -0
  117. package/.pi/lib/harness-lens/clients/file-kinds.ts +380 -0
  118. package/.pi/lib/harness-lens/clients/file-time.ts +215 -0
  119. package/.pi/lib/harness-lens/clients/file-utils.ts +484 -0
  120. package/.pi/lib/harness-lens/clients/format-service.ts +276 -0
  121. package/.pi/lib/harness-lens/clients/formatters.ts +1000 -0
  122. package/.pi/lib/harness-lens/clients/git-guard.ts +31 -0
  123. package/.pi/lib/harness-lens/clients/indent-retarget.ts +90 -0
  124. package/.pi/lib/harness-lens/clients/installer/index.ts +2368 -0
  125. package/.pi/lib/harness-lens/clients/latency-logger.ts +80 -0
  126. package/.pi/lib/harness-lens/clients/lens-config.ts +43 -0
  127. package/.pi/lib/harness-lens/clients/lens-events.ts +164 -0
  128. package/.pi/lib/harness-lens/clients/lsp/aggregation.ts +91 -0
  129. package/.pi/lib/harness-lens/clients/lsp/client.ts +1466 -0
  130. package/.pi/lib/harness-lens/clients/lsp/config.ts +216 -0
  131. package/.pi/lib/harness-lens/clients/lsp/edits.ts +297 -0
  132. package/.pi/lib/harness-lens/clients/lsp/index.ts +1355 -0
  133. package/.pi/lib/harness-lens/clients/lsp/interactive-install.ts +424 -0
  134. package/.pi/lib/harness-lens/clients/lsp/language.ts +223 -0
  135. package/.pi/lib/harness-lens/clients/lsp/launch.ts +939 -0
  136. package/.pi/lib/harness-lens/clients/lsp/lsp-index.ts +11 -0
  137. package/.pi/lib/harness-lens/clients/lsp/path-utils.ts +12 -0
  138. package/.pi/lib/harness-lens/clients/lsp/server-strategies.ts +81 -0
  139. package/.pi/lib/harness-lens/clients/lsp/server.ts +1971 -0
  140. package/.pi/lib/harness-lens/clients/path-utils.ts +182 -0
  141. package/.pi/lib/harness-lens/clients/pipeline.ts +360 -0
  142. package/.pi/lib/harness-lens/clients/project-profile.ts +117 -0
  143. package/.pi/lib/harness-lens/clients/runtime-agent-end.ts +112 -0
  144. package/.pi/lib/harness-lens/clients/runtime-config.ts +33 -0
  145. package/.pi/lib/harness-lens/clients/runtime-coordinator.ts +186 -0
  146. package/.pi/lib/harness-lens/clients/runtime-tool-result.ts +171 -0
  147. package/.pi/lib/harness-lens/clients/safe-spawn.ts +339 -0
  148. package/.pi/lib/harness-lens/clients/secrets-scanner.ts +214 -0
  149. package/.pi/lib/harness-lens/clients/tool-policy.ts +2072 -0
  150. package/.pi/lib/harness-lens/clients/types.ts +59 -0
  151. package/.pi/lib/harness-lens/clients/widget-state.ts +283 -0
  152. package/.pi/lib/harness-lens/index.ts +532 -0
  153. package/.pi/lib/harness-lens/tools/lsp-diagnostics.ts +706 -0
  154. package/.pi/lib/harness-lens/tools/lsp-navigation.ts +1246 -0
  155. package/.pi/{extensions/lib → lib}/harness-posthog.ts +3 -0
  156. package/.pi/lib/harness-project-config.ts +91 -0
  157. package/.pi/lib/harness-run-context-responses.ts +9 -0
  158. package/.pi/lib/harness-run-context.ts +1 -3
  159. package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +4 -3
  160. package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +5 -28
  161. package/.pi/lib/harness-subagent-auth.ts +51 -0
  162. package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +13 -10
  163. package/.pi/{extensions/lib → lib}/harness-subagent-submit-pipeline.ts +3 -3
  164. package/.pi/lib/harness-subagent-submit-register.ts +163 -0
  165. package/.pi/{extensions/lib → lib}/harness-subagent-submit-registry.ts +1 -55
  166. package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +53 -14
  167. package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
  168. package/.pi/lib/harness-ui-state.ts +27 -12
  169. package/.pi/{extensions/lib → lib}/plan-approval/create-plan.ts +2 -2
  170. package/.pi/{extensions/lib → lib}/plan-approval/format-plan.ts +2 -2
  171. package/.pi/{extensions/lib → lib}/plan-approval/plan-review.ts +162 -201
  172. package/.pi/{extensions/lib → lib}/plan-approval/render.ts +1 -1
  173. package/.pi/{extensions/lib → lib}/plan-approval/resolve-disk.ts +2 -2
  174. package/.pi/{extensions/lib → lib}/plan-approval/types.ts +1 -1
  175. package/.pi/{extensions/lib → lib}/plan-approval/validate.ts +3 -3
  176. package/.pi/{extensions/lib → lib}/plan-approval-readiness.ts +3 -52
  177. package/.pi/{extensions/lib → lib}/plan-debate-envelope.ts +1 -1
  178. package/.pi/{extensions/lib → lib}/plan-debate-gate.ts +1 -1
  179. package/.pi/{extensions/lib → lib}/plan-debate-lane.ts +1 -4
  180. package/.pi/{extensions/lib → lib}/plan-messenger.ts +1 -1
  181. package/.pi/prompts/harness-auto.md +2 -2
  182. package/.pi/prompts/harness-plan.md +4 -6
  183. package/.pi/prompts/harness-review.md +9 -9
  184. package/.pi/prompts/harness-run.md +7 -7
  185. package/.pi/prompts/harness-setup.md +42 -68
  186. package/.pi/prompts/harness-steer.md +2 -2
  187. package/.pi/scripts/README.md +3 -5
  188. package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
  189. package/.pi/scripts/graphify-kb-updater.mjs +48 -8
  190. package/.pi/scripts/harness-agents-manifest.mjs +61 -4
  191. package/.pi/scripts/harness-agt-doctor.ts +36 -0
  192. package/.pi/scripts/harness-cli-verify.sh +9 -2
  193. package/.pi/scripts/harness-project-toggle.mjs +129 -0
  194. package/.pi/scripts/harness-sentrux-cli.mjs +142 -0
  195. package/.pi/scripts/harness-verify.mjs +113 -39
  196. package/.pi/scripts/harness-web-policy-guard.mjs +2 -2
  197. package/.pi/scripts/validate-plan-dag.mjs +65 -74
  198. package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +2 -2
  199. package/.pi/scripts/vendor-sync-pi-vcc.sh +1 -1
  200. package/.pi/skills/architecture/broker-domain/SKILL.md +65 -0
  201. package/.pi/skills/architecture/cqrs/SKILL.md +63 -0
  202. package/.pi/skills/architecture/event-driven/SKILL.md +60 -0
  203. package/.pi/skills/architecture/hexagonal-ports-adapters/SKILL.md +66 -0
  204. package/.pi/skills/architecture/layered/SKILL.md +68 -0
  205. package/.pi/skills/architecture/microkernel/SKILL.md +62 -0
  206. package/.pi/skills/architecture/microservices/SKILL.md +64 -0
  207. package/.pi/skills/architecture/modular-monolith/SKILL.md +65 -0
  208. package/.pi/skills/architecture/orchestration-driven-soa/SKILL.md +61 -0
  209. package/.pi/skills/architecture/pipeline/SKILL.md +63 -0
  210. package/.pi/skills/architecture/service-based/SKILL.md +64 -0
  211. package/.pi/skills/architecture/service-mesh/SKILL.md +60 -0
  212. package/.pi/skills/architecture/space-based/SKILL.md +60 -0
  213. package/.pi/skills/ast-grep/SKILL.md +40 -321
  214. package/.pi/skills/delivery/debugging-discipline/SKILL.md +36 -0
  215. package/.pi/skills/delivery/documentation-update/SKILL.md +33 -0
  216. package/.pi/skills/delivery/requirements-to-implementation/SKILL.md +34 -0
  217. package/.pi/skills/delivery/risk-based-verification/SKILL.md +43 -0
  218. package/.pi/skills/delivery/tradeoff-analysis/SKILL.md +34 -0
  219. package/.pi/skills/engineering/api-contract-design/SKILL.md +38 -0
  220. package/.pi/skills/engineering/cohesion-coupling/SKILL.md +43 -0
  221. package/.pi/skills/engineering/complexity-control/SKILL.md +31 -0
  222. package/.pi/skills/engineering/defensive-programming/SKILL.md +38 -0
  223. package/.pi/skills/engineering/dependency-management/SKILL.md +29 -0
  224. package/.pi/skills/engineering/domain-modeling/SKILL.md +32 -0
  225. package/.pi/skills/engineering/error-handling/SKILL.md +37 -0
  226. package/.pi/skills/engineering/legacy-code-seams/SKILL.md +35 -0
  227. package/.pi/skills/engineering/naming-and-intent/SKILL.md +29 -0
  228. package/.pi/skills/engineering/refactoring-safe-evolution/SKILL.md +35 -0
  229. package/.pi/skills/engineering/routine-function-design/SKILL.md +34 -0
  230. package/.pi/skills/engineering/small-change-discipline/SKILL.md +35 -0
  231. package/.pi/skills/lsp-navigation/SKILL.md +89 -0
  232. package/.pi/skills/quality/code-review-self-check/SKILL.md +35 -0
  233. package/.pi/skills/quality/privacy-data-handling/SKILL.md +26 -0
  234. package/.pi/skills/quality/security-review/SKILL.md +34 -0
  235. package/.pi/skills/quality/test-strategy/SKILL.md +33 -0
  236. package/.pi/skills/quality/testability-design/SKILL.md +33 -0
  237. package/.pi/skills/systems/concurrency-safety/SKILL.md +32 -0
  238. package/.pi/skills/systems/data-modeling-migrations/SKILL.md +31 -0
  239. package/.pi/skills/systems/observability-instrumentation/SKILL.md +32 -0
  240. package/.pi/skills/systems/performance-measurement/SKILL.md +35 -0
  241. package/.pi/skills/systems/reliability-design/SKILL.md +32 -0
  242. package/.sentrux/rules.toml +20 -4
  243. package/AGENTS.md +5 -0
  244. package/CHANGELOG.md +26 -0
  245. package/README.md +85 -58
  246. package/THIRD_PARTY_NOTICES.md +12 -21
  247. package/package.json +15 -7
  248. package/vendor/pi-subagents/src/agents.ts +45 -1
  249. package/vendor/pi-subagents/src/subagents.ts +866 -811
  250. package/vendor/pi-vcc/src/core/brief.ts +68 -99
  251. package/vendor/pi-vcc/src/core/settings.ts +2 -2
  252. package/.agents/skills/caveman/SKILL.md +0 -67
  253. package/.pi/agents/harness/meta-optimizer.md +0 -36
  254. package/.pi/agents/harness/planning/scout-graphify.md +0 -39
  255. package/.pi/agents/harness/planning/scout-semantic.md +0 -41
  256. package/.pi/agents/harness/planning/scout-structure.md +0 -37
  257. package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
  258. package/.pi/extensions/lib/harness-subagent-auth.ts +0 -209
  259. package/.pi/extensions/lib/harness-subagent-policy.ts +0 -236
  260. package/.pi/extensions/pi-model-router-harness.ts +0 -42
  261. package/.pi/harness/evolution/meta-optimizer.mjs +0 -99
  262. package/.pi/harness/specs/router-tuning-proposal.schema.json +0 -114
  263. package/.pi/model-router.example.json +0 -36
  264. package/.pi/prompts/harness-critic.md +0 -10
  265. package/.pi/prompts/harness-eval.md +0 -10
  266. package/.pi/prompts/harness-router-tune.md +0 -52
  267. package/.pi/scripts/harness-generate-model-router.mjs +0 -327
  268. package/.pi/scripts/harness-model-router-routing.test.mjs +0 -97
  269. package/.pi/scripts/harness-sync-model-router.mjs +0 -97
  270. package/.pi/scripts/vendor-sync-pi-model-router.sh +0 -47
  271. package/vendor/pi-model-router/.prettierignore +0 -4
  272. package/vendor/pi-model-router/.prettierrc +0 -5
  273. package/vendor/pi-model-router/AGENTS.md +0 -39
  274. package/vendor/pi-model-router/LICENSE +0 -21
  275. package/vendor/pi-model-router/README.md +0 -99
  276. package/vendor/pi-model-router/UPSTREAM_PIN.md +0 -10
  277. package/vendor/pi-model-router/docs/ARCHITECTURE.md +0 -54
  278. package/vendor/pi-model-router/extensions/commands.ts +0 -720
  279. package/vendor/pi-model-router/extensions/config.ts +0 -348
  280. package/vendor/pi-model-router/extensions/constants.ts +0 -1
  281. package/vendor/pi-model-router/extensions/index.ts +0 -478
  282. package/vendor/pi-model-router/extensions/provider.ts +0 -580
  283. package/vendor/pi-model-router/extensions/routing.ts +0 -564
  284. package/vendor/pi-model-router/extensions/state.ts +0 -52
  285. package/vendor/pi-model-router/extensions/types.ts +0 -95
  286. package/vendor/pi-model-router/extensions/ui.ts +0 -144
  287. package/vendor/pi-model-router/model-router.example.json +0 -48
  288. package/vendor/pi-model-router/package.json +0 -48
  289. package/vendor/pi-model-router/tsconfig.json +0 -16
  290. /package/.pi/{prompts → harness/docs}/planning-rubrics.md +0 -0
  291. /package/.pi/{extensions/lib → lib}/ask-user/fallback.ts +0 -0
  292. /package/.pi/{extensions/lib → lib}/ask-user/render.ts +0 -0
  293. /package/.pi/{extensions/lib → lib}/ask-user/schema.ts +0 -0
  294. /package/.pi/{extensions/lib → lib}/ask-user/types.ts +0 -0
  295. /package/.pi/{extensions/lib → lib}/ask-user/validate-core.mjs +0 -0
  296. /package/.pi/{extensions/lib → lib}/ask-user/validate.ts +0 -0
  297. /package/.pi/{extensions/lib → lib}/harness-cocoindex-refresh.ts +0 -0
  298. /package/.pi/{extensions/lib → lib}/harness-paths.ts +0 -0
  299. /package/.pi/{extensions/lib → lib}/harness-spawn-budget.ts +0 -0
  300. /package/.pi/{extensions/lib → lib}/harness-vcc-settings.ts +0 -0
  301. /package/.pi/{extensions/lib → lib}/harness-web/run-cli.ts +0 -0
  302. /package/.pi/{extensions/lib → lib}/plan-approval/dialog.ts +0 -0
  303. /package/.pi/{extensions/lib → lib}/plan-approval/schema.ts +0 -0
  304. /package/.pi/{extensions/lib → lib}/plan-debate-eligibility.ts +0 -0
  305. /package/.pi/{extensions/lib → lib}/plan-debate-focus.ts +0 -0
  306. /package/.pi/{extensions/lib → lib}/plan-debate-id.ts +0 -0
  307. /package/.pi/{extensions/lib → lib}/plan-debate-lanes.ts +0 -0
  308. /package/.pi/{extensions/lib → lib}/plan-debate-round-status.ts +0 -0
  309. /package/.pi/{extensions/lib → lib}/plan-debate-write-guard.ts +0 -0
  310. /package/.pi/{extensions/lib → lib}/plan-review-gate.ts +0 -0
  311. /package/.pi/{extensions/lib → lib}/plan-review-integrator-rules.ts +0 -0
  312. /package/.pi/{extensions/lib → lib}/plan-scope-guard.ts +0 -0
  313. /package/.pi/{extensions/lib → lib}/posthog-client.ts +0 -0
  314. /package/.pi/{extensions/lib → lib}/posthog-node.d.ts +0 -0
@@ -0,0 +1,380 @@
1
+ /**
2
+ * File Kind Detection for pi-lens
3
+ *
4
+ * Centralized file type detection to avoid duplication across clients.
5
+ * Maps file extensions and paths to semantic file kinds.
6
+ */
7
+
8
+ import { basename, extname } from "node:path";
9
+
10
+ // --- Types ---
11
+
12
+ export type FileKind =
13
+ | "clojure" // Clojure
14
+ | "cmake" // CMake
15
+ | "csharp" // C#
16
+ | "css" // CSS
17
+ | "cxx" // C/C++
18
+ | "dart" // Dart
19
+ | "docker" // Dockerfile
20
+ | "elixir" // Elixir
21
+ | "fish" // Fish shell
22
+ | "fsharp" // F#
23
+ | "gleam" // Gleam
24
+ | "go" // Go
25
+ | "haskell" // Haskell
26
+ | "html" // HTML
27
+ | "java" // Java
28
+ | "json" // JSON
29
+ | "jsts" // JavaScript/TypeScript/frameworks
30
+ | "kotlin" // Kotlin
31
+ | "lua" // Lua
32
+ | "markdown" // Markdown
33
+ | "nix" // Nix
34
+ | "ocaml" // OCaml
35
+ | "php" // PHP
36
+ | "powershell" // PowerShell
37
+ | "prisma" // Prisma schema
38
+ | "python" // Python
39
+ | "ruby" // Ruby
40
+ | "rust" // Rust
41
+ | "shell" // Shell
42
+ | "sql" // SQL
43
+ | "swift" // Swift
44
+ | "terraform" // Terraform
45
+ | "toml" // TOML
46
+ | "yaml" // YAML
47
+ | "zig"; // Zig
48
+
49
+ // --- Extension Maps ---
50
+
51
+ export const KIND_EXTENSIONS: Record<FileKind, readonly string[]> = {
52
+ clojure: [".clj", ".cljc", ".cljs", ".edn"],
53
+ cmake: [".cmake"],
54
+ csharp: [".cs"],
55
+ css: [".css", ".less", ".sass", ".scss"],
56
+ // From llvm-project/clang/lib/Driver/Types.cpp clang::driver::types::lookupTypeForExtension:
57
+ cxx: [
58
+ // C
59
+ ".c",
60
+ ".h",
61
+ // C++
62
+ ".c++",
63
+ ".cc",
64
+ ".cp",
65
+ ".cpp",
66
+ ".cxx",
67
+ ".hh",
68
+ ".hpp",
69
+ ".hxx",
70
+ // C++ include files
71
+ ".inl",
72
+ ".ipp",
73
+ ".tpp",
74
+ ".txx",
75
+ // C++20 module interface files
76
+ ".c++m",
77
+ ".cppm",
78
+ ".cxxm",
79
+ ".ixx",
80
+ // CUDA
81
+ ".cu",
82
+ // HIP
83
+ ".hip",
84
+ // Objective-C
85
+ ".m",
86
+ ".mm",
87
+ // OpenCL
88
+ ".cl",
89
+ ".clcpp",
90
+ ],
91
+ dart: [".dart"],
92
+ docker: [".dockerfile"],
93
+ elixir: [".ex", ".exs"],
94
+ fish: [".fish"],
95
+ fsharp: [".fs", ".fsi", ".fsx"],
96
+ gleam: [".gleam"],
97
+ go: [".go"],
98
+ haskell: [".hs", ".lhs"],
99
+ html: [".htm", ".html"],
100
+ java: [".java"],
101
+ json: [".json", ".json5", ".jsonc"],
102
+ jsts: [
103
+ ".cjs",
104
+ ".cts",
105
+ ".js",
106
+ ".jsx",
107
+ ".mjs",
108
+ ".mts",
109
+ ".svelte",
110
+ ".ts",
111
+ ".tsx",
112
+ ".vue",
113
+ ],
114
+ kotlin: [".kt", ".kts"],
115
+ lua: [".lua"],
116
+ markdown: [".md", ".mdx"],
117
+ nix: [".nix"],
118
+ ocaml: [".ml", ".mli"],
119
+ php: [".php"],
120
+ powershell: [".ps1", ".psm1", ".psd1"],
121
+ prisma: [".prisma"],
122
+ python: [".py", ".pyi"],
123
+ ruby: [".gemspec", ".rake", ".rb", ".ru"],
124
+ rust: [".rs"],
125
+ shell: [".bash", ".sh", ".zsh"],
126
+ sql: [".sql"],
127
+ swift: [".swift"],
128
+ terraform: [".tf", ".tfvars"],
129
+ toml: [".toml"],
130
+ yaml: [".yaml", ".yml"],
131
+ zig: [".zig", ".zon"],
132
+ };
133
+
134
+ // Reverse map: extension → file kind (for fast lookup)
135
+ const EXT_TO_KIND = new Map<string, FileKind>();
136
+ for (const [kind, exts] of Object.entries(KIND_EXTENSIONS)) {
137
+ for (const ext of exts) {
138
+ EXT_TO_KIND.set(ext.toLowerCase(), kind as FileKind);
139
+ }
140
+ // Also register without leading dot
141
+ for (const ext of exts) {
142
+ if (ext.startsWith(".")) {
143
+ EXT_TO_KIND.set(ext.slice(1).toLowerCase(), kind as FileKind);
144
+ }
145
+ }
146
+ }
147
+
148
+ // Special filenames that indicate a file kind
149
+ const SPECIAL_FILENAMES: Array<{ pattern: RegExp; kind: FileKind }> = [
150
+ { pattern: /^CMakeLists\.txt$/i, kind: "cmake" },
151
+ { pattern: /^Makefile$/i, kind: "shell" },
152
+ { pattern: /^Dockerfile(\.\w+)?$/i, kind: "docker" },
153
+ ];
154
+
155
+ // --- Detection Functions ---
156
+
157
+ /**
158
+ * Detect the file kind from a file path.
159
+ * Returns the semantic file kind or undefined if unknown.
160
+ */
161
+ export function detectFileKind(filePath: string): FileKind | undefined {
162
+ if (!filePath || typeof filePath !== "string") {
163
+ return undefined;
164
+ }
165
+
166
+ // Check special filenames first
167
+ const base = basename(filePath);
168
+ for (const { pattern, kind } of SPECIAL_FILENAMES) {
169
+ if (pattern.test(base)) {
170
+ return kind;
171
+ }
172
+ }
173
+
174
+ // Check by extension
175
+ const ext = extname(filePath).toLowerCase();
176
+ return EXT_TO_KIND.get(ext);
177
+ }
178
+
179
+ /**
180
+ * Check if a file kind is supported by a specific tool or capability.
181
+ *
182
+ * @example
183
+ * // Check if TypeScript file
184
+ * if (isFileKind(filePath, "jsts")) { ... }
185
+ *
186
+ * // Check for multiple kinds
187
+ * if (isFileKind(filePath, ["jsts", "python"])) { ... }
188
+ */
189
+ export function isFileKind(
190
+ filePath: string,
191
+ kind: FileKind | FileKind[],
192
+ ): boolean {
193
+ const detected = detectFileKind(filePath);
194
+ if (!detected) return false;
195
+
196
+ if (Array.isArray(kind)) {
197
+ return kind.includes(detected);
198
+ }
199
+
200
+ return detected === kind;
201
+ }
202
+
203
+ /**
204
+ * Get all file kinds that match a given file extension.
205
+ * Useful for listing which tools might handle a file.
206
+ */
207
+ export function getFileKindsForExtension(ext: string): FileKind[] {
208
+ const normalizedExt = ext.startsWith(".") ? ext : `.${ext}`;
209
+ const kind = EXT_TO_KIND.get(normalizedExt.toLowerCase());
210
+ return kind ? [kind] : [];
211
+ }
212
+
213
+ /**
214
+ * Check if a file kind represents a code file (not config/markdown).
215
+ */
216
+ export function isCodeKind(kind: FileKind): boolean {
217
+ return [
218
+ "jsts",
219
+ "python",
220
+ "go",
221
+ "rust",
222
+ "cxx",
223
+ "fish",
224
+ "shell",
225
+ "ruby",
226
+ "html",
227
+ "php",
228
+ "powershell",
229
+ "prisma",
230
+ "csharp",
231
+ "fsharp",
232
+ "java",
233
+ "kotlin",
234
+ "swift",
235
+ "dart",
236
+ "lua",
237
+ "zig",
238
+ "haskell",
239
+ "elixir",
240
+ "gleam",
241
+ "ocaml",
242
+ "clojure",
243
+ "terraform",
244
+ "nix",
245
+ ].includes(kind);
246
+ }
247
+
248
+ /**
249
+ * Check if a file kind represents a text/config file.
250
+ */
251
+ export function isConfigKind(kind: FileKind): boolean {
252
+ return [
253
+ "json",
254
+ "yaml",
255
+ "markdown",
256
+ "css",
257
+ "sql",
258
+ "docker",
259
+ "cmake",
260
+ "toml",
261
+ ].includes(kind);
262
+ }
263
+
264
+ /**
265
+ * Get human-readable description of a file kind.
266
+ */
267
+ export function getFileKindLabel(kind: FileKind): string {
268
+ const labels: Record<FileKind, string> = {
269
+ jsts: "JavaScript/TypeScript",
270
+ python: "Python",
271
+ go: "Go",
272
+ rust: "Rust",
273
+ cxx: "C/C++",
274
+ cmake: "CMake",
275
+ shell: "Shell",
276
+ json: "JSON",
277
+ markdown: "Markdown",
278
+ css: "CSS",
279
+ yaml: "YAML",
280
+ sql: "SQL",
281
+ ruby: "Ruby",
282
+ html: "HTML",
283
+ docker: "Dockerfile",
284
+ php: "PHP",
285
+ powershell: "PowerShell",
286
+ prisma: "Prisma",
287
+ csharp: "C#",
288
+ fish: "Fish shell",
289
+ fsharp: "F#",
290
+ java: "Java",
291
+ kotlin: "Kotlin",
292
+ swift: "Swift",
293
+ dart: "Dart",
294
+ lua: "Lua",
295
+ zig: "Zig",
296
+ haskell: "Haskell",
297
+ elixir: "Elixir",
298
+ gleam: "Gleam",
299
+ ocaml: "OCaml",
300
+ clojure: "Clojure",
301
+ terraform: "Terraform",
302
+ nix: "Nix",
303
+ toml: "TOML",
304
+ };
305
+ return labels[kind] ?? kind;
306
+ }
307
+
308
+ /**
309
+ * Get file extensions for a file kind.
310
+ */
311
+ export function getExtensionsForKind(kind: FileKind): string[] {
312
+ return [...(KIND_EXTENSIONS[kind] ?? [])];
313
+ }
314
+
315
+ /**
316
+ * Check if a file should be scanned for linting/formatting.
317
+ * Excludes test files, generated files, etc.
318
+ */
319
+ export function isScannableFile(filePath: string): boolean {
320
+ const kind = detectFileKind(filePath);
321
+ if (!kind) return false;
322
+
323
+ // Exclude test files for most kinds
324
+ const base = basename(filePath);
325
+ if (
326
+ base.includes(".test.") ||
327
+ base.includes(".spec.") ||
328
+ base.startsWith("test-") ||
329
+ base.startsWith("spec-")
330
+ ) {
331
+ return false;
332
+ }
333
+
334
+ // Only scan code and config files
335
+ return isCodeKind(kind) || isConfigKind(kind);
336
+ }
337
+
338
+ /**
339
+ * Get the language identifier for LSP/tools that use language IDs.
340
+ */
341
+ export function getLanguageId(kind: FileKind): string {
342
+ const languageIds: Record<FileKind, string> = {
343
+ jsts: "typescript",
344
+ python: "python",
345
+ go: "go",
346
+ rust: "rust",
347
+ cxx: "cpp",
348
+ cmake: "cmake",
349
+ shell: "shell",
350
+ json: "json",
351
+ markdown: "markdown",
352
+ css: "css",
353
+ yaml: "yaml",
354
+ sql: "sql",
355
+ ruby: "ruby",
356
+ html: "html",
357
+ docker: "dockerfile",
358
+ php: "php",
359
+ powershell: "powershell",
360
+ prisma: "prisma",
361
+ csharp: "csharp",
362
+ fish: "fish",
363
+ fsharp: "fsharp",
364
+ java: "java",
365
+ kotlin: "kotlin",
366
+ swift: "swift",
367
+ dart: "dart",
368
+ lua: "lua",
369
+ zig: "zig",
370
+ haskell: "haskell",
371
+ elixir: "elixir",
372
+ gleam: "gleam",
373
+ ocaml: "ocaml",
374
+ clojure: "clojure",
375
+ terraform: "terraform",
376
+ nix: "nix",
377
+ toml: "toml",
378
+ };
379
+ return languageIds[kind] ?? "plaintext";
380
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * FileTime Tracking for pi-lens
3
+ *
4
+ * Prevents race conditions when auto-formatting or external tools modify files.
5
+ * Tracks file modification times and sizes to detect external changes.
6
+ *
7
+ * Inspired by OpenCode's FileTime system - ensures agents re-read files
8
+ * that have been modified externally (including by formatters).
9
+ */
10
+
11
+ import * as fs from "node:fs";
12
+ import * as path from "node:path";
13
+
14
+ // --- Types ---
15
+
16
+ export interface FileStamp {
17
+ readAt: Date;
18
+ mtime: number | undefined;
19
+ ctime: number | undefined;
20
+ size: number | undefined;
21
+ }
22
+
23
+ interface FileTimeState {
24
+ reads: Map<string, Map<string, FileStamp>>; // sessionID -> filePath -> stamp
25
+ locks: Map<string, Promise<void>>; // filePath -> lock promise
26
+ }
27
+
28
+ // --- Singleton State ---
29
+
30
+ const globalState: FileTimeState = {
31
+ reads: new Map(),
32
+ locks: new Map(),
33
+ };
34
+
35
+ // --- Public API ---
36
+
37
+ export class FileTime {
38
+ private sessionID: string;
39
+
40
+ constructor(sessionID: string) {
41
+ this.sessionID = sessionID;
42
+ }
43
+
44
+ /**
45
+ * Record a file read with current stats
46
+ * Call this after ANY file modification (including formatting)
47
+ */
48
+ read(filePath: string): FileStamp {
49
+ const absolutePath = path.resolve(filePath);
50
+ const stamp = createStamp(absolutePath);
51
+
52
+ let sessionReads = globalState.reads.get(this.sessionID);
53
+ if (!sessionReads) {
54
+ sessionReads = new Map();
55
+ globalState.reads.set(this.sessionID, sessionReads);
56
+ }
57
+
58
+ sessionReads.set(absolutePath, stamp);
59
+ return stamp;
60
+ }
61
+
62
+ /**
63
+ * Get last recorded stamp for a file
64
+ */
65
+ get(filePath: string): FileStamp | undefined {
66
+ const absolutePath = path.resolve(filePath);
67
+ const sessionReads = globalState.reads.get(this.sessionID);
68
+ return sessionReads?.get(absolutePath);
69
+ }
70
+
71
+ /**
72
+ * Assert file hasn't changed since last read
73
+ * Throws error if file modified externally - forces agent to re-read
74
+ */
75
+ assert(filePath: string): void {
76
+ const absolutePath = path.resolve(filePath);
77
+ const sessionReads = globalState.reads.get(this.sessionID);
78
+ const recorded = sessionReads?.get(absolutePath);
79
+
80
+ if (!recorded) {
81
+ throw new FileTimeError(
82
+ `You must read file ${absolutePath} before modifying it. Use the read tool first.`,
83
+ absolutePath,
84
+ "not-read",
85
+ );
86
+ }
87
+
88
+ const current = createStamp(absolutePath);
89
+ const changed =
90
+ current.mtime !== recorded.mtime ||
91
+ current.ctime !== recorded.ctime ||
92
+ current.size !== recorded.size;
93
+
94
+ if (changed) {
95
+ throw new FileTimeError(
96
+ `File ${absolutePath} has been modified since it was last read.\n` +
97
+ `Last modification: ${new Date(current.mtime ?? Date.now()).toISOString()}\n` +
98
+ `Last read: ${recorded.readAt.toISOString()}\n\n` +
99
+ `Please read the file again before modifying it.`,
100
+ absolutePath,
101
+ "modified",
102
+ );
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Check if file has changed (non-throwing version of assert)
108
+ */
109
+ hasChanged(filePath: string): boolean {
110
+ const absolutePath = path.resolve(filePath);
111
+ const sessionReads = globalState.reads.get(this.sessionID);
112
+ const recorded = sessionReads?.get(absolutePath);
113
+
114
+ if (!recorded) return true; // Never read = changed
115
+
116
+ const current = createStamp(absolutePath);
117
+ return (
118
+ current.mtime !== recorded.mtime ||
119
+ current.ctime !== recorded.ctime ||
120
+ current.size !== recorded.size
121
+ );
122
+ }
123
+
124
+ /**
125
+ * Acquire exclusive lock on file
126
+ * Prevents concurrent modifications to same file
127
+ */
128
+ async withLock<T>(filePath: string, fn: () => Promise<T>): Promise<T> {
129
+ const absolutePath = path.resolve(filePath);
130
+
131
+ // Wait for existing lock
132
+ while (globalState.locks.has(absolutePath)) {
133
+ const existing = globalState.locks.get(absolutePath);
134
+ if (existing) await existing;
135
+ }
136
+
137
+ // Create new lock
138
+ const lockPromise = fn().finally(() => {
139
+ globalState.locks.delete(absolutePath);
140
+ });
141
+
142
+ globalState.locks.set(
143
+ absolutePath,
144
+ lockPromise.then(() => {}),
145
+ );
146
+ return lockPromise;
147
+ }
148
+
149
+ /**
150
+ * Clear all tracked files for this session
151
+ */
152
+ clear(): void {
153
+ globalState.reads.delete(this.sessionID);
154
+ }
155
+
156
+ /**
157
+ * Clear specific file tracking
158
+ */
159
+ clearFile(filePath: string): void {
160
+ const absolutePath = path.resolve(filePath);
161
+ const sessionReads = globalState.reads.get(this.sessionID);
162
+ sessionReads?.delete(absolutePath);
163
+ }
164
+ }
165
+
166
+ // --- Error Type ---
167
+
168
+ export class FileTimeError extends Error {
169
+ readonly filePath: string;
170
+ readonly reason: "not-read" | "modified";
171
+
172
+ constructor(
173
+ message: string,
174
+ filePath: string,
175
+ reason: "not-read" | "modified",
176
+ ) {
177
+ super(message);
178
+ this.name = "FileTimeError";
179
+ this.filePath = filePath;
180
+ this.reason = reason;
181
+ }
182
+ }
183
+
184
+ // --- Utilities ---
185
+
186
+ function createStamp(filePath: string): FileStamp {
187
+ try {
188
+ const stats = fs.statSync(filePath);
189
+ return {
190
+ readAt: new Date(),
191
+ mtime: stats.mtime.getTime(),
192
+ ctime: stats.ctime.getTime(),
193
+ size: stats.size,
194
+ };
195
+ } catch {
196
+ // File doesn't exist - return empty stamp
197
+ return {
198
+ readAt: new Date(),
199
+ mtime: undefined,
200
+ ctime: undefined,
201
+ size: undefined,
202
+ };
203
+ }
204
+ }
205
+
206
+ // --- Global Helpers ---
207
+
208
+ export function createFileTime(sessionID: string): FileTime {
209
+ return new FileTime(sessionID);
210
+ }
211
+
212
+ export function clearAllSessions(): void {
213
+ globalState.reads.clear();
214
+ globalState.locks.clear();
215
+ }