ultimate-pi 0.18.1 → 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 (284) 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/.pi/PACKAGING.md +4 -4
  5. package/.pi/SYSTEM.md +54 -120
  6. package/.pi/agents/harness/incident-recorder.md +0 -1
  7. package/.pi/agents/harness/planning/decompose.md +0 -2
  8. package/.pi/agents/harness/planning/execution-plan-author.md +0 -2
  9. package/.pi/agents/harness/planning/hypothesis-validator.md +0 -2
  10. package/.pi/agents/harness/planning/hypothesis.md +0 -2
  11. package/.pi/agents/harness/planning/implementation-researcher.md +0 -2
  12. package/.pi/agents/harness/planning/plan-adversary.md +0 -2
  13. package/.pi/agents/harness/planning/plan-evaluator.md +1 -3
  14. package/.pi/agents/harness/planning/planning-context.md +0 -2
  15. package/.pi/agents/harness/planning/review-integrator.md +0 -2
  16. package/.pi/agents/harness/planning/sprint-contract-auditor.md +0 -2
  17. package/.pi/agents/harness/planning/stack-researcher.md +0 -2
  18. package/.pi/agents/harness/reviewing/adversary.md +0 -2
  19. package/.pi/agents/harness/reviewing/evaluator.md +0 -2
  20. package/.pi/agents/harness/reviewing/tie-breaker.md +0 -2
  21. package/.pi/agents/harness/running/executor.md +0 -2
  22. package/.pi/agents/harness/sentrux-bootstrap.md +0 -1
  23. package/.pi/agents/harness/sentrux-steward.md +0 -2
  24. package/.pi/agents/harness/trace-librarian.md +0 -1
  25. package/.pi/extensions/00-posthog-network-bootstrap.ts +1 -1
  26. package/.pi/extensions/agt-kill-switch.ts +57 -0
  27. package/.pi/extensions/agt-prompt-guard.ts +32 -0
  28. package/.pi/extensions/custom-footer.ts +46 -145
  29. package/.pi/extensions/custom-header.ts +1 -1
  30. package/.pi/extensions/custom-system-prompt.ts +1 -1
  31. package/.pi/extensions/debate-orchestrator.ts +6 -6
  32. package/.pi/extensions/harness-ask-user.ts +7 -7
  33. package/.pi/extensions/harness-debate-tools.ts +26 -42
  34. package/.pi/extensions/harness-lens.ts +94 -0
  35. package/.pi/extensions/harness-plan-approval.ts +11 -11
  36. package/.pi/extensions/harness-run-context.ts +1070 -876
  37. package/.pi/extensions/harness-subagent-governance.ts +8 -0
  38. package/.pi/extensions/harness-subagent-submit.ts +34 -163
  39. package/.pi/extensions/harness-subagents.ts +3 -3
  40. package/.pi/extensions/harness-telemetry.ts +2 -2
  41. package/.pi/extensions/harness-web-tools.ts +2 -2
  42. package/.pi/extensions/policy-gate.ts +25 -5
  43. package/.pi/extensions/sentrux-rules-sync.ts +1 -1
  44. package/.pi/extensions/subagent-governance.ts +92 -0
  45. package/.pi/extensions/trace-recorder.ts +1 -1
  46. package/.pi/extensions/{ultimate-pi-vcc.ts → vcc-compaction.ts} +1 -1
  47. package/.pi/harness/README.md +6 -2
  48. package/.pi/harness/agents.manifest.json +22 -25
  49. package/.pi/harness/agents.policy.yaml +275 -0
  50. package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +1 -1
  51. package/.pi/harness/docs/adrs/0035-plan-phase-review-gate.md +1 -1
  52. package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
  53. package/.pi/harness/docs/adrs/0046-agt-policy-engine.md +51 -0
  54. package/.pi/harness/docs/adrs/0047-agt-layered-security.md +39 -0
  55. package/.pi/harness/docs/adrs/0048-tool-call-hook-order.md +25 -0
  56. package/.pi/harness/docs/adrs/0049-agents-policy-manifest.md +36 -0
  57. package/.pi/harness/docs/adrs/README.md +5 -0
  58. package/.pi/harness/evolution/README.md +1 -2
  59. package/.pi/harness/examples/agents.policy.project.yaml +19 -0
  60. package/.pi/harness/examples/policies/custom-deny-bash.yaml +9 -0
  61. package/.pi/harness/policies/bash-denylists.yaml +5 -0
  62. package/.pi/harness/policies/defaults.yaml +51 -0
  63. package/.pi/harness/policies/orchestrator.yaml +18 -0
  64. package/.pi/harness/policies/phases.yaml +10 -0
  65. package/.pi/harness/policies/roles.yaml +5 -0
  66. package/.pi/harness/policies/web-guard.yaml +5 -0
  67. package/.pi/harness/policies/workflow-sequences.yaml +9 -0
  68. package/.pi/harness/sentrux/architecture.manifest.json +26 -4
  69. package/.pi/harness/specs/observation.schema.json +2 -1
  70. package/.pi/lib/agents-policy.d.mts +70 -0
  71. package/.pi/lib/agents-policy.mjs +325 -0
  72. package/.pi/lib/agents-policy.ts +19 -0
  73. package/.pi/lib/agt/audit-run-sink.ts +52 -0
  74. package/.pi/lib/agt/build-evaluation-context.ts +285 -0
  75. package/.pi/lib/agt/config.ts +28 -0
  76. package/.pi/lib/agt/delegation.ts +69 -0
  77. package/.pi/lib/agt/evaluate-policy.ts +56 -0
  78. package/.pi/lib/agt/identity-registry.ts +41 -0
  79. package/.pi/lib/agt/index.ts +55 -0
  80. package/.pi/lib/agt/kill-switch-state.ts +11 -0
  81. package/.pi/lib/agt/legacy-evaluate.ts +101 -0
  82. package/.pi/lib/agt/policy-engine.ts +154 -0
  83. package/.pi/lib/agt/rings.ts +21 -0
  84. package/.pi/lib/agt/sre-hooks.ts +45 -0
  85. package/.pi/lib/agt/trust-run-store.ts +26 -0
  86. package/.pi/lib/agt/workflow-history.ts +29 -0
  87. package/.pi/lib/agt-governance-active.ts +14 -0
  88. package/.pi/lib/agt-tool-guard.ts +78 -0
  89. package/.pi/lib/ask-user/dialog.ts +314 -0
  90. package/.pi/{extensions/lib → lib}/debate-bus-core.ts +10 -10
  91. package/.pi/{extensions/lib → lib}/debate-bus-state.ts +1 -1
  92. package/.pi/{extensions/lib → lib}/extension-load-guard.ts +13 -2
  93. package/.pi/lib/harness-agt-tool-guard.ts +5 -0
  94. package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +1 -1
  95. package/.pi/lib/harness-debate-core-deps.ts +14 -0
  96. package/.pi/lib/harness-debate-workflow-deps.ts +43 -0
  97. package/.pi/lib/harness-lens/.gitattributes +1 -0
  98. package/.pi/lib/harness-lens/clients/edit-autopatch.ts +88 -0
  99. package/.pi/lib/harness-lens/clients/file-kinds.ts +380 -0
  100. package/.pi/lib/harness-lens/clients/file-time.ts +215 -0
  101. package/.pi/lib/harness-lens/clients/file-utils.ts +484 -0
  102. package/.pi/lib/harness-lens/clients/format-service.ts +276 -0
  103. package/.pi/lib/harness-lens/clients/formatters.ts +1000 -0
  104. package/.pi/lib/harness-lens/clients/git-guard.ts +31 -0
  105. package/.pi/lib/harness-lens/clients/indent-retarget.ts +90 -0
  106. package/.pi/lib/harness-lens/clients/installer/index.ts +2368 -0
  107. package/.pi/lib/harness-lens/clients/latency-logger.ts +80 -0
  108. package/.pi/lib/harness-lens/clients/lens-config.ts +43 -0
  109. package/.pi/lib/harness-lens/clients/lens-events.ts +164 -0
  110. package/.pi/lib/harness-lens/clients/lsp/aggregation.ts +91 -0
  111. package/.pi/lib/harness-lens/clients/lsp/client.ts +1466 -0
  112. package/.pi/lib/harness-lens/clients/lsp/config.ts +216 -0
  113. package/.pi/lib/harness-lens/clients/lsp/edits.ts +297 -0
  114. package/.pi/lib/harness-lens/clients/lsp/index.ts +1355 -0
  115. package/.pi/lib/harness-lens/clients/lsp/interactive-install.ts +424 -0
  116. package/.pi/lib/harness-lens/clients/lsp/language.ts +223 -0
  117. package/.pi/lib/harness-lens/clients/lsp/launch.ts +939 -0
  118. package/.pi/lib/harness-lens/clients/lsp/lsp-index.ts +11 -0
  119. package/.pi/lib/harness-lens/clients/lsp/path-utils.ts +12 -0
  120. package/.pi/lib/harness-lens/clients/lsp/server-strategies.ts +81 -0
  121. package/.pi/lib/harness-lens/clients/lsp/server.ts +1971 -0
  122. package/.pi/lib/harness-lens/clients/path-utils.ts +182 -0
  123. package/.pi/lib/harness-lens/clients/pipeline.ts +360 -0
  124. package/.pi/lib/harness-lens/clients/project-profile.ts +117 -0
  125. package/.pi/lib/harness-lens/clients/runtime-agent-end.ts +112 -0
  126. package/.pi/lib/harness-lens/clients/runtime-config.ts +33 -0
  127. package/.pi/lib/harness-lens/clients/runtime-coordinator.ts +186 -0
  128. package/.pi/lib/harness-lens/clients/runtime-tool-result.ts +171 -0
  129. package/.pi/lib/harness-lens/clients/safe-spawn.ts +339 -0
  130. package/.pi/lib/harness-lens/clients/secrets-scanner.ts +214 -0
  131. package/.pi/lib/harness-lens/clients/tool-policy.ts +2072 -0
  132. package/.pi/lib/harness-lens/clients/types.ts +59 -0
  133. package/.pi/lib/harness-lens/clients/widget-state.ts +283 -0
  134. package/.pi/lib/harness-lens/index.ts +532 -0
  135. package/.pi/lib/harness-lens/tools/lsp-diagnostics.ts +706 -0
  136. package/.pi/lib/harness-lens/tools/lsp-navigation.ts +1246 -0
  137. package/.pi/{extensions/lib → lib}/harness-posthog.ts +3 -0
  138. package/.pi/lib/harness-run-context-responses.ts +9 -0
  139. package/.pi/lib/harness-run-context.ts +0 -2
  140. package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +1 -0
  141. package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +1 -1
  142. package/.pi/lib/harness-subagent-auth.ts +51 -0
  143. package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +10 -7
  144. package/.pi/{extensions/lib → lib}/harness-subagent-submit-pipeline.ts +3 -3
  145. package/.pi/lib/harness-subagent-submit-register.ts +163 -0
  146. package/.pi/{extensions/lib → lib}/harness-subagent-submit-registry.ts +1 -37
  147. package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +53 -14
  148. package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
  149. package/.pi/{extensions/lib → lib}/plan-approval/create-plan.ts +2 -2
  150. package/.pi/{extensions/lib → lib}/plan-approval/format-plan.ts +2 -2
  151. package/.pi/{extensions/lib → lib}/plan-approval/plan-review.ts +162 -201
  152. package/.pi/{extensions/lib → lib}/plan-approval/render.ts +1 -1
  153. package/.pi/{extensions/lib → lib}/plan-approval/resolve-disk.ts +2 -2
  154. package/.pi/{extensions/lib → lib}/plan-approval/types.ts +1 -1
  155. package/.pi/{extensions/lib → lib}/plan-approval/validate.ts +3 -3
  156. package/.pi/{extensions/lib → lib}/plan-debate-envelope.ts +1 -1
  157. package/.pi/{extensions/lib → lib}/plan-debate-gate.ts +1 -1
  158. package/.pi/{extensions/lib → lib}/plan-debate-lane.ts +1 -4
  159. package/.pi/{extensions/lib → lib}/plan-messenger.ts +1 -1
  160. package/.pi/prompts/harness-plan.md +1 -1
  161. package/.pi/prompts/harness-setup.md +37 -64
  162. package/.pi/scripts/README.md +2 -5
  163. package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
  164. package/.pi/scripts/harness-agents-manifest.mjs +60 -3
  165. package/.pi/scripts/harness-agt-doctor.ts +36 -0
  166. package/.pi/scripts/harness-cli-verify.sh +9 -2
  167. package/.pi/scripts/harness-verify.mjs +113 -39
  168. package/.pi/scripts/harness-web-policy-guard.mjs +2 -2
  169. package/.pi/scripts/validate-plan-dag.mjs +65 -74
  170. package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +2 -2
  171. package/.pi/scripts/vendor-sync-pi-vcc.sh +1 -1
  172. package/.pi/skills/architecture/broker-domain/SKILL.md +65 -0
  173. package/.pi/skills/architecture/cqrs/SKILL.md +63 -0
  174. package/.pi/skills/architecture/event-driven/SKILL.md +60 -0
  175. package/.pi/skills/architecture/hexagonal-ports-adapters/SKILL.md +66 -0
  176. package/.pi/skills/architecture/layered/SKILL.md +68 -0
  177. package/.pi/skills/architecture/microkernel/SKILL.md +62 -0
  178. package/.pi/skills/architecture/microservices/SKILL.md +64 -0
  179. package/.pi/skills/architecture/modular-monolith/SKILL.md +65 -0
  180. package/.pi/skills/architecture/orchestration-driven-soa/SKILL.md +61 -0
  181. package/.pi/skills/architecture/pipeline/SKILL.md +63 -0
  182. package/.pi/skills/architecture/service-based/SKILL.md +64 -0
  183. package/.pi/skills/architecture/service-mesh/SKILL.md +60 -0
  184. package/.pi/skills/architecture/space-based/SKILL.md +60 -0
  185. package/.pi/skills/ast-grep/SKILL.md +40 -321
  186. package/.pi/skills/delivery/debugging-discipline/SKILL.md +36 -0
  187. package/.pi/skills/delivery/documentation-update/SKILL.md +33 -0
  188. package/.pi/skills/delivery/requirements-to-implementation/SKILL.md +34 -0
  189. package/.pi/skills/delivery/risk-based-verification/SKILL.md +43 -0
  190. package/.pi/skills/delivery/tradeoff-analysis/SKILL.md +34 -0
  191. package/.pi/skills/engineering/api-contract-design/SKILL.md +38 -0
  192. package/.pi/skills/engineering/cohesion-coupling/SKILL.md +43 -0
  193. package/.pi/skills/engineering/complexity-control/SKILL.md +31 -0
  194. package/.pi/skills/engineering/defensive-programming/SKILL.md +38 -0
  195. package/.pi/skills/engineering/dependency-management/SKILL.md +29 -0
  196. package/.pi/skills/engineering/domain-modeling/SKILL.md +32 -0
  197. package/.pi/skills/engineering/error-handling/SKILL.md +37 -0
  198. package/.pi/skills/engineering/legacy-code-seams/SKILL.md +35 -0
  199. package/.pi/skills/engineering/naming-and-intent/SKILL.md +29 -0
  200. package/.pi/skills/engineering/refactoring-safe-evolution/SKILL.md +35 -0
  201. package/.pi/skills/engineering/routine-function-design/SKILL.md +34 -0
  202. package/.pi/skills/engineering/small-change-discipline/SKILL.md +35 -0
  203. package/.pi/skills/lsp-navigation/SKILL.md +89 -0
  204. package/.pi/skills/quality/code-review-self-check/SKILL.md +35 -0
  205. package/.pi/skills/quality/privacy-data-handling/SKILL.md +26 -0
  206. package/.pi/skills/quality/security-review/SKILL.md +34 -0
  207. package/.pi/skills/quality/test-strategy/SKILL.md +33 -0
  208. package/.pi/skills/quality/testability-design/SKILL.md +33 -0
  209. package/.pi/skills/systems/concurrency-safety/SKILL.md +32 -0
  210. package/.pi/skills/systems/data-modeling-migrations/SKILL.md +31 -0
  211. package/.pi/skills/systems/observability-instrumentation/SKILL.md +32 -0
  212. package/.pi/skills/systems/performance-measurement/SKILL.md +35 -0
  213. package/.pi/skills/systems/reliability-design/SKILL.md +32 -0
  214. package/.sentrux/rules.toml +20 -4
  215. package/AGENTS.md +5 -0
  216. package/CHANGELOG.md +14 -0
  217. package/README.md +3 -12
  218. package/THIRD_PARTY_NOTICES.md +12 -21
  219. package/package.json +15 -7
  220. package/vendor/pi-subagents/src/agents.ts +45 -1
  221. package/vendor/pi-subagents/src/subagents.ts +866 -811
  222. package/vendor/pi-vcc/src/core/brief.ts +68 -99
  223. package/vendor/pi-vcc/src/core/settings.ts +2 -2
  224. package/.agents/skills/caveman/SKILL.md +0 -67
  225. package/.pi/agents/harness/meta-optimizer.md +0 -36
  226. package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
  227. package/.pi/extensions/lib/harness-subagent-auth.ts +0 -207
  228. package/.pi/extensions/lib/harness-subagent-policy.ts +0 -236
  229. package/.pi/extensions/pi-model-router-harness.ts +0 -42
  230. package/.pi/harness/evolution/meta-optimizer.mjs +0 -99
  231. package/.pi/harness/specs/router-tuning-proposal.schema.json +0 -114
  232. package/.pi/model-router.example.json +0 -36
  233. package/.pi/prompts/harness-critic.md +0 -10
  234. package/.pi/prompts/harness-eval.md +0 -10
  235. package/.pi/prompts/harness-router-tune.md +0 -52
  236. package/.pi/scripts/harness-generate-model-router.mjs +0 -327
  237. package/.pi/scripts/harness-model-router-routing.test.mjs +0 -97
  238. package/.pi/scripts/harness-sync-model-router.mjs +0 -97
  239. package/.pi/scripts/vendor-sync-pi-model-router.sh +0 -47
  240. package/vendor/pi-model-router/.prettierignore +0 -4
  241. package/vendor/pi-model-router/.prettierrc +0 -5
  242. package/vendor/pi-model-router/AGENTS.md +0 -39
  243. package/vendor/pi-model-router/LICENSE +0 -21
  244. package/vendor/pi-model-router/README.md +0 -99
  245. package/vendor/pi-model-router/UPSTREAM_PIN.md +0 -10
  246. package/vendor/pi-model-router/docs/ARCHITECTURE.md +0 -54
  247. package/vendor/pi-model-router/extensions/commands.ts +0 -720
  248. package/vendor/pi-model-router/extensions/config.ts +0 -348
  249. package/vendor/pi-model-router/extensions/constants.ts +0 -1
  250. package/vendor/pi-model-router/extensions/index.ts +0 -478
  251. package/vendor/pi-model-router/extensions/provider.ts +0 -580
  252. package/vendor/pi-model-router/extensions/routing.ts +0 -564
  253. package/vendor/pi-model-router/extensions/state.ts +0 -52
  254. package/vendor/pi-model-router/extensions/types.ts +0 -95
  255. package/vendor/pi-model-router/extensions/ui.ts +0 -144
  256. package/vendor/pi-model-router/model-router.example.json +0 -48
  257. package/vendor/pi-model-router/package.json +0 -48
  258. package/vendor/pi-model-router/tsconfig.json +0 -16
  259. /package/.pi/{prompts → harness/docs}/planning-rubrics.md +0 -0
  260. /package/.pi/{extensions/lib → lib}/ask-user/fallback.ts +0 -0
  261. /package/.pi/{extensions/lib → lib}/ask-user/render.ts +0 -0
  262. /package/.pi/{extensions/lib → lib}/ask-user/schema.ts +0 -0
  263. /package/.pi/{extensions/lib → lib}/ask-user/types.ts +0 -0
  264. /package/.pi/{extensions/lib → lib}/ask-user/validate-core.mjs +0 -0
  265. /package/.pi/{extensions/lib → lib}/ask-user/validate.ts +0 -0
  266. /package/.pi/{extensions/lib → lib}/harness-cocoindex-refresh.ts +0 -0
  267. /package/.pi/{extensions/lib → lib}/harness-paths.ts +0 -0
  268. /package/.pi/{extensions/lib → lib}/harness-spawn-budget.ts +0 -0
  269. /package/.pi/{extensions/lib → lib}/harness-vcc-settings.ts +0 -0
  270. /package/.pi/{extensions/lib → lib}/harness-web/run-cli.ts +0 -0
  271. /package/.pi/{extensions/lib → lib}/plan-approval/dialog.ts +0 -0
  272. /package/.pi/{extensions/lib → lib}/plan-approval/schema.ts +0 -0
  273. /package/.pi/{extensions/lib → lib}/plan-approval-readiness.ts +0 -0
  274. /package/.pi/{extensions/lib → lib}/plan-debate-eligibility.ts +0 -0
  275. /package/.pi/{extensions/lib → lib}/plan-debate-focus.ts +0 -0
  276. /package/.pi/{extensions/lib → lib}/plan-debate-id.ts +0 -0
  277. /package/.pi/{extensions/lib → lib}/plan-debate-lanes.ts +0 -0
  278. /package/.pi/{extensions/lib → lib}/plan-debate-round-status.ts +0 -0
  279. /package/.pi/{extensions/lib → lib}/plan-debate-write-guard.ts +0 -0
  280. /package/.pi/{extensions/lib → lib}/plan-review-gate.ts +0 -0
  281. /package/.pi/{extensions/lib → lib}/plan-review-integrator-rules.ts +0 -0
  282. /package/.pi/{extensions/lib → lib}/plan-scope-guard.ts +0 -0
  283. /package/.pi/{extensions/lib → lib}/posthog-client.ts +0 -0
  284. /package/.pi/{extensions/lib → lib}/posthog-node.d.ts +0 -0
@@ -128,75 +128,47 @@ export interface TranscriptEntry {
128
128
  count?: number;
129
129
  }
130
130
 
131
- /**
132
- * Build BriefLine sections from NormalizedBlocks.
133
- */
134
- export const buildBriefSections = (blocks: NormalizedBlock[]): BriefLine[] => {
135
- const sections: BriefLine[] = [];
136
- let lastHeader = "";
137
-
138
- const push = (header: string, line: string) => {
139
- if (header === lastHeader && sections.length > 0) {
140
- sections[sections.length - 1].lines.push(line);
141
- return;
142
- }
143
- sections.push({ header, lines: [line] });
144
- lastHeader = header;
145
- };
131
+ const stripAssistantSelfTalk = (text: string): string => {
132
+ let raw = text;
133
+ for (let i = 0; i < 2; i++) {
134
+ const stripped = raw.replace(SELF_TALK_PREFIX_RE, "");
135
+ if (stripped === raw) break;
136
+ raw = stripped;
137
+ }
138
+ return raw;
139
+ };
146
140
 
147
- for (const b of blocks) {
148
- switch (b.kind) {
149
- case "user": {
150
- if (isNoiseUser(b.text)) break;
151
- const text = truncateTokens(collapseSkillText(b.text), TRUNCATE_USER);
152
- if (text) {
153
- const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
154
- push("[user]", text + ref);
155
- }
156
- lastHeader = "[user]";
157
- break;
158
- }
159
- case "assistant": {
160
- let raw = b.text;
161
- // Strip leading self-talk prefix (up to 2x; assistants sometimes chain "Hmm, actually, ...")
162
- for (let i = 0; i < 2; i++) {
163
- const stripped = raw.replace(SELF_TALK_PREFIX_RE, "");
164
- if (stripped === raw) break;
165
- raw = stripped;
166
- }
167
- const text = truncateTokens(raw, TRUNCATE_ASSISTANT);
168
- if (text) {
169
- const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
170
- push("[assistant]", text + ref);
171
- }
172
- break;
173
- }
174
- case "tool_call": {
175
- // Skip malformed tool calls from streaming providers (empty name / fragmented args).
176
- if (!b.name || b.name.trim() === "") break;
177
- const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
178
- const summary = toolOneLiner(b.name, b.args) + ref;
179
- push("[assistant]", summary);
180
- break;
181
- }
182
- case "tool_result": {
183
- if (b.isError) {
184
- const body = firstLine(b.text, 150);
185
- // Drop empty/placeholder error bodies — keep the line only if it carries info.
186
- if (!body || body === "(no output)") break;
187
- const ref = b.sourceIndex != null ? ` (#${b.sourceIndex})` : "";
188
- const header = `[tool_error] ${b.name}${ref}`;
189
- push(header, body);
190
- lastHeader = header;
191
- }
192
- break;
193
- }
194
- case "thinking":
195
- break;
196
- }
141
+ const appendBlockSection = (
142
+ b: NormalizedBlock,
143
+ push: (header: string, line: string) => void,
144
+ ): string | null => {
145
+ if (b.kind === "user") {
146
+ if (isNoiseUser(b.text)) return null;
147
+ const text = truncateTokens(collapseSkillText(b.text), TRUNCATE_USER);
148
+ if (text) push("[user]", text + (b.sourceIndex != null ? ` (#${b.sourceIndex})` : ""));
149
+ return "[user]";
150
+ }
151
+ if (b.kind === "assistant") {
152
+ const text = truncateTokens(stripAssistantSelfTalk(b.text), TRUNCATE_ASSISTANT);
153
+ if (text) push("[assistant]", text + (b.sourceIndex != null ? ` (#${b.sourceIndex})` : ""));
154
+ return null;
155
+ }
156
+ if (b.kind === "tool_call") {
157
+ if (!b.name || b.name.trim() === "") return null;
158
+ push("[assistant]", toolOneLiner(b.name, b.args) + (b.sourceIndex != null ? ` (#${b.sourceIndex})` : ""));
159
+ return null;
197
160
  }
161
+ if (b.kind === "tool_result" && b.isError) {
162
+ const body = firstLine(b.text, 150);
163
+ if (!body || body === "(no output)") return null;
164
+ const header = `[tool_error] ${b.name}${b.sourceIndex != null ? ` (#${b.sourceIndex})` : ""}`;
165
+ push(header, body);
166
+ return header;
167
+ }
168
+ return null;
169
+ };
198
170
 
199
- // Collapse consecutive identical tool lines (same text, different #ref)
171
+ const collapseAssistantToolLines = (sections: BriefLine[]): void => {
200
172
  for (const sec of sections) {
201
173
  if (sec.header !== "[assistant]") continue;
202
174
  const out: string[] = [];
@@ -206,26 +178,19 @@ export const buildBriefSections = (blocks: NormalizedBlock[]): BriefLine[] => {
206
178
  const base = ref ? line.slice(0, -(ref.length + 3)).trimEnd() : line;
207
179
  const last = out.length > 0 ? out[out.length - 1] : "";
208
180
  const m = last.match(/^(.*) \((#[\d, #]+)\) x(\d+)$/);
209
- if (m && m[1] === base) {
210
- out[out.length - 1] = `${base} (${m[2]}, #${ref}) x${parseInt(m[3]) + 1}`;
211
- } else if (last.match(/\(#\d+\)$/) && last.replace(/\s*\(#\d+\)$/, "") === base) {
212
- const prevRef = last.match(/\(#(\d+)\)$/)?.[1];
213
- out[out.length - 1] = `${base} (#${prevRef}, #${ref}) x2`;
214
- } else {
215
- out.push(line);
216
- }
181
+ if (m && m[1] === base) out[out.length - 1] = `${base} (${m[2]}, #${ref}) x${parseInt(m[3]) + 1}`;
182
+ else if (last.match(/\(#\d+\)$/) && last.replace(/\s*\(#\d+\)$/, "") === base) out[out.length - 1] = `${base} (#${last.match(/\(#(\d+)\)$/)?.[1]}, #${ref}) x2`;
183
+ else out.push(line);
217
184
  }
218
185
  sec.lines = out;
219
186
  }
187
+ };
220
188
 
221
- // Cap tool calls per [assistant] turn keep tail (latest actions tend to
222
- // be the deciding edits/writes; head is usually exploration noise).
189
+ const capAssistantToolLines = (sections: BriefLine[]): void => {
223
190
  const TOOL_CALLS_PER_TURN = 8;
224
191
  for (const sec of sections) {
225
192
  if (sec.header !== "[assistant]") continue;
226
- const toolIdxs = sec.lines
227
- .map((l, i) => (l.startsWith("* ") ? i : -1))
228
- .filter((i) => i >= 0);
193
+ const toolIdxs = sec.lines.map((l, i) => (l.startsWith("* ") ? i : -1)).filter((i) => i >= 0);
229
194
  if (toolIdxs.length <= TOOL_CALLS_PER_TURN) continue;
230
195
  const dropCount = toolIdxs.length - TOOL_CALLS_PER_TURN;
231
196
  const dropSet = new Set(toolIdxs.slice(0, dropCount));
@@ -242,36 +207,40 @@ export const buildBriefSections = (blocks: NormalizedBlock[]): BriefLine[] => {
242
207
  }
243
208
  sec.lines = next;
244
209
  }
210
+ };
245
211
 
246
- // Collapse consecutive identical [tool_error] sections (same tool, same body).
247
- // E.g. 20 back-to-back `[tool_error] bash (#N) ... Command aborted` become one
248
- // `[tool_error] bash (#refs...) x20` entry.
212
+ const collapseConsecutiveToolErrors = (sections: BriefLine[]): BriefLine[] => {
249
213
  const collapsedErrors: BriefLine[] = [];
250
214
  for (const sec of sections) {
251
215
  const m = sec.header.match(/^\[tool_error\]\s+(\S+?)(?:\s*\(#(\d+)\))?$/);
252
- if (!m || sec.lines.length !== 1) {
253
- collapsedErrors.push(sec);
254
- continue;
255
- }
256
- const tool = m[1];
257
- const ref = m[2];
258
- const body = sec.lines[0];
259
- const prev = collapsedErrors[collapsedErrors.length - 1];
260
- const prevMatch = prev?.header.match(
261
- /^\[tool_error\]\s+(\S+?)\s*\(((?:#\d+(?:,\s*)?)+)\)(?:\s*x(\d+))?$/,
262
- );
216
+ if (!m || sec.lines.length !== 1) { collapsedErrors.push(sec); continue; }
217
+ const [tool, ref, body, prev] = [m[1], m[2], sec.lines[0], collapsedErrors[collapsedErrors.length - 1]];
218
+ const prevMatch = prev?.header.match(/^\[tool_error\]\s+(\S+?)\s*\(((?:#\d+(?:,\s*)?)+)\)(?:\s*x(\d+))?$/);
263
219
  if (prev && prevMatch && prevMatch[1] === tool && prev.lines.length === 1 && prev.lines[0] === body) {
264
220
  const refs = prevMatch[2] + (ref ? `, #${ref}` : "");
265
221
  const count = prevMatch[3] ? parseInt(prevMatch[3]) + 1 : 2;
266
222
  prev.header = `[tool_error] ${tool} (${refs}) x${count}`;
267
- } else {
268
- collapsedErrors.push(sec);
269
- }
223
+ } else collapsedErrors.push(sec);
270
224
  }
271
- sections.length = 0;
272
- sections.push(...collapsedErrors);
225
+ return collapsedErrors;
226
+ };
227
+
228
+ /**
229
+ * Build BriefLine sections from NormalizedBlocks.
230
+ */
231
+ export const buildBriefSections = (blocks: NormalizedBlock[]): BriefLine[] => {
232
+ let lastHeader = "";
233
+ const sections: BriefLine[] = [];
234
+ const push = (header: string, line: string) => {
235
+ if (header === lastHeader && sections.length > 0) sections[sections.length - 1].lines.push(line);
236
+ else sections.push({ header, lines: [line] });
237
+ lastHeader = header;
238
+ };
273
239
 
274
- return sections;
240
+ for (const b of blocks) lastHeader = appendBlockSection(b, push) ?? lastHeader;
241
+ collapseAssistantToolLines(sections);
242
+ capAssistantToolLines(sections);
243
+ return collapseConsecutiveToolErrors(sections);
275
244
  };
276
245
 
277
246
  /**
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * ultimate-pi harness settings (env-only). Re-exported for vendored pi-vcc layout.
3
3
  */
4
- export type { PiVccSettings } from "../../../../.pi/extensions/lib/harness-vcc-settings.js";
4
+ export type { PiVccSettings } from "../../../../.pi/lib/harness-vcc-settings.js";
5
5
  export {
6
6
  loadSettings,
7
7
  scaffoldSettings,
8
- } from "../../../../.pi/extensions/lib/harness-vcc-settings.js";
8
+ } from "../../../../.pi/lib/harness-vcc-settings.js";
@@ -1,67 +0,0 @@
1
- ---
2
- name: caveman
3
- description: >
4
- Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman
5
- while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra,
6
- wenyan-lite, wenyan-full, wenyan-ultra.
7
- Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens",
8
- "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
9
- ---
10
-
11
- Respond terse like smart caveman. All technical substance stay. Only fluff die.
12
-
13
- ## Persistence
14
-
15
- ACTIVE EVERY RESPONSE. No revert after many turns. No filler drift. Still active if unsure. Off only: "stop caveman" / "normal mode".
16
-
17
- Default: **full**. Switch: `/caveman lite|full|ultra`.
18
-
19
- ## Rules
20
-
21
- Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). Technical terms exact. Code blocks unchanged. Errors quoted exact.
22
-
23
- Pattern: `[thing] [action] [reason]. [next step].`
24
-
25
- Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
26
- Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
27
-
28
- ## Intensity
29
-
30
- | Level | What change |
31
- |-------|------------|
32
- | **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight |
33
- | **full** | Drop articles, fragments OK, short synonyms. Classic caveman |
34
- | **ultra** | Abbreviate (DB/auth/config/req/res/fn/impl), strip conjunctions, arrows for causality (X → Y), one word when one word enough |
35
- | **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register |
36
- | **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) |
37
- | **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse |
38
-
39
- Example — "Why React component re-render?"
40
- - lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
41
- - full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."
42
- - ultra: "Inline obj prop → new ref → re-render. `useMemo`."
43
- - wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"
44
- - wenyan-full: "物出新參照,致重繪。useMemo .Wrap之。"
45
- - wenyan-ultra: "新參照→重繪。useMemo Wrap。"
46
-
47
- Example — "Explain database connection pooling."
48
- - lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead."
49
- - full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
50
- - ultra: "Pool = reuse DB conn. Skip handshake → fast under load."
51
- - wenyan-full: "池reuse open connection。不每req新開。skip handshake overhead。"
52
- - wenyan-ultra: "池reuse conn。skip handshake → fast。"
53
-
54
- ## Auto-Clarity
55
-
56
- Drop caveman for: security warnings, irreversible action confirmations, multi-step sequences where fragment order risks misread, user asks to clarify or repeats question. Resume caveman after clear part done.
57
-
58
- Example — destructive op:
59
- > **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
60
- > ```sql
61
- > DROP TABLE users;
62
- > ```
63
- > Caveman resume. Verify backup exist first.
64
-
65
- ## Boundaries
66
-
67
- Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
@@ -1,36 +0,0 @@
1
- ---
2
- description: Harness meta optimizer proposing policy/prompt/router improvements from trace evidence.
3
- tools: read, grep, find, ls, submit_human_required
4
- extensions: false
5
- disallowed_tools: ask_user
6
- thinking: high
7
- max_turns: 25
8
- ---
9
-
10
- You are the Harness Meta Optimizer.
11
-
12
- ## Mission
13
-
14
- Generate conservative, evidence-backed router-tuning proposals from spawn context (`mode: tune`). Never write `.pi/model-router.json` or call `ask_user` — parent runs proposal scripts and approval.
15
-
16
- ## Process
17
-
18
- 1. Validate evidence completeness: sample count, success-rate delta, cost-per-task delta, regression guard status.
19
- 2. Rank proposals by quality/cost impact and implementation risk.
20
- 3. Emit proposal JSON compatible with router-tuning workflow; reject incomplete evidence with `tuning_status: human_required`.
21
-
22
- ## Guardrails
23
-
24
- - Read-only — no live router mutation.
25
- - Never speculate without concrete benchmark evidence.
26
- - Never set `inherit_context: true` on harness agents.
27
-
28
- ## Output
29
-
30
- ```json
31
- {
32
- "tuning_status": "proposed",
33
- "proposal_summary": "…",
34
- "evidence_gates": { "sample_ok": true, "regression_guard": "pass" }
35
- }
36
- ```
@@ -1,260 +0,0 @@
1
- import type { ExtensionUIContext } from "@earendil-works/pi-coding-agent";
2
- import {
3
- Editor,
4
- type EditorTheme,
5
- Key,
6
- matchesKey,
7
- truncateToWidth,
8
- } from "@earendil-works/pi-tui";
9
- import type { AskResponse, DialogResult, ValidatedAskParams } from "./types.js";
10
-
11
- type DisplayOption = {
12
- title: string;
13
- description?: string;
14
- isFreeform?: boolean;
15
- };
16
-
17
- interface CustomAnswer {
18
- response: AskResponse;
19
- }
20
-
21
- function withTimeout<T>(
22
- promise: Promise<T | null>,
23
- ms: number | undefined,
24
- ): Promise<T | null> {
25
- if (!ms) return promise;
26
- return Promise.race([
27
- promise,
28
- new Promise<null>((resolve) => {
29
- setTimeout(() => resolve(null), ms);
30
- }),
31
- ]);
32
- }
33
-
34
- export async function runAskDialog(
35
- ui: ExtensionUIContext,
36
- validated: ValidatedAskParams,
37
- ): Promise<DialogResult> {
38
- const { question, context, options, allowMultiple, allowFreeform } =
39
- validated;
40
-
41
- const displayOptions: DisplayOption[] = [...options];
42
- if (allowFreeform) {
43
- displayOptions.push({
44
- title: "Type something…",
45
- isFreeform: true,
46
- });
47
- }
48
-
49
- // Freeform-only: no listed options
50
- if (displayOptions.length === 0) {
51
- const text = await ui.input(question, "");
52
- if (!text?.trim()) {
53
- return { response: null, cancelled: true };
54
- }
55
- return {
56
- response: { kind: "freeform", text: text.trim() },
57
- cancelled: false,
58
- };
59
- }
60
-
61
- const result = await withTimeout(
62
- ui.custom<CustomAnswer | null>((tui, theme, _kb, done) => {
63
- let optionIndex = 0;
64
- let editMode = false;
65
- const selected = new Set<number>();
66
- let cachedLines: string[] | undefined;
67
-
68
- const editorTheme: EditorTheme = {
69
- borderColor: (s) => theme.fg("accent", s),
70
- selectList: {
71
- selectedPrefix: (t) => theme.fg("accent", t),
72
- selectedText: (t) => theme.fg("accent", t),
73
- description: (t) => theme.fg("muted", t),
74
- scrollInfo: (t) => theme.fg("dim", t),
75
- noMatch: (t) => theme.fg("warning", t),
76
- },
77
- };
78
- const editor = new Editor(tui, editorTheme);
79
-
80
- editor.onSubmit = (value) => {
81
- const trimmed = value.trim();
82
- if (trimmed) {
83
- done({ response: { kind: "freeform", text: trimmed } });
84
- } else {
85
- editMode = false;
86
- editor.setText("");
87
- refresh();
88
- }
89
- };
90
-
91
- function refresh() {
92
- cachedLines = undefined;
93
- tui.requestRender();
94
- }
95
-
96
- function submitSelection() {
97
- if (allowMultiple) {
98
- const titles = [...selected]
99
- .sort((a, b) => a - b)
100
- .map((i) => displayOptions[i].title)
101
- .filter((t) => t !== "Type something…");
102
- if (titles.length === 0) return;
103
- done({ response: { kind: "selection", selections: titles } });
104
- return;
105
- }
106
- const opt = displayOptions[optionIndex];
107
- if (opt.isFreeform) {
108
- editMode = true;
109
- refresh();
110
- return;
111
- }
112
- done({
113
- response: { kind: "selection", selections: [opt.title] },
114
- });
115
- }
116
-
117
- function handleInput(data: string) {
118
- if (editMode) {
119
- if (matchesKey(data, Key.escape)) {
120
- editMode = false;
121
- editor.setText("");
122
- refresh();
123
- return;
124
- }
125
- editor.handleInput(data);
126
- refresh();
127
- return;
128
- }
129
-
130
- if (matchesKey(data, Key.up)) {
131
- optionIndex = Math.max(0, optionIndex - 1);
132
- refresh();
133
- return;
134
- }
135
- if (matchesKey(data, Key.down)) {
136
- optionIndex = Math.min(displayOptions.length - 1, optionIndex + 1);
137
- refresh();
138
- return;
139
- }
140
-
141
- if (allowMultiple && matchesKey(data, Key.space)) {
142
- const opt = displayOptions[optionIndex];
143
- if (!opt.isFreeform) {
144
- if (selected.has(optionIndex)) {
145
- selected.delete(optionIndex);
146
- } else {
147
- selected.add(optionIndex);
148
- }
149
- refresh();
150
- }
151
- return;
152
- }
153
-
154
- if (matchesKey(data, Key.enter)) {
155
- submitSelection();
156
- return;
157
- }
158
-
159
- if (matchesKey(data, Key.escape)) {
160
- done(null);
161
- }
162
- }
163
-
164
- function render(width: number): string[] {
165
- if (cachedLines) return cachedLines;
166
-
167
- const lines: string[] = [];
168
- const add = (s: string) => lines.push(truncateToWidth(s, width));
169
- const useOverlay = validated.displayMode !== "inline";
170
-
171
- if (useOverlay) {
172
- add(theme.fg("accent", "─".repeat(width)));
173
- }
174
-
175
- if (context) {
176
- for (const line of context.split("\n")) {
177
- add(theme.fg("muted", ` ${line}`));
178
- }
179
- lines.push("");
180
- }
181
-
182
- add(theme.fg("text", ` ${question}`));
183
- lines.push("");
184
-
185
- for (let i = 0; i < displayOptions.length; i++) {
186
- const opt = displayOptions[i];
187
- const isFreeform = opt.isFreeform === true;
188
- const focused = i === optionIndex;
189
- const checked = selected.has(i);
190
- let prefix = " ";
191
- if (allowMultiple && !isFreeform) {
192
- prefix = checked ? theme.fg("accent", "[x] ") : "[ ] ";
193
- } else if (focused) {
194
- prefix = theme.fg("accent", "> ");
195
- }
196
-
197
- const num = `${i + 1}. `;
198
- const label = opt.title;
199
- if (isFreeform && editMode && focused) {
200
- add(prefix + theme.fg("accent", `${num}${label} ✎`));
201
- } else if (focused && !allowMultiple) {
202
- add(prefix + theme.fg("accent", `${num}${label}`));
203
- } else {
204
- add(`${prefix}${theme.fg("text", `${num}${label}`)}`);
205
- }
206
-
207
- if (opt.description) {
208
- add(` ${theme.fg("muted", opt.description)}`);
209
- }
210
- }
211
-
212
- if (editMode) {
213
- lines.push("");
214
- add(theme.fg("muted", " Your answer:"));
215
- for (const line of editor.render(width - 2)) {
216
- add(` ${line}`);
217
- }
218
- }
219
-
220
- lines.push("");
221
- if (editMode) {
222
- add(theme.fg("dim", " Enter to submit • Esc to go back"));
223
- } else if (allowMultiple) {
224
- add(
225
- theme.fg(
226
- "dim",
227
- " ↑↓ navigate • Space toggle • Enter confirm • Esc cancel",
228
- ),
229
- );
230
- } else {
231
- add(
232
- theme.fg("dim", " ↑↓ navigate • Enter to select • Esc to cancel"),
233
- );
234
- }
235
-
236
- if (useOverlay) {
237
- add(theme.fg("accent", "─".repeat(width)));
238
- }
239
-
240
- cachedLines = lines;
241
- return lines;
242
- }
243
-
244
- return {
245
- render,
246
- invalidate: () => {
247
- cachedLines = undefined;
248
- },
249
- handleInput,
250
- };
251
- }),
252
- validated.timeout,
253
- );
254
-
255
- if (!result) {
256
- return { response: null, cancelled: true };
257
- }
258
-
259
- return { response: result.response, cancelled: false };
260
- }