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
@@ -5,14 +5,14 @@ import {
5
5
  canonicalPlanReviewPath,
6
6
  type HarnessRunContext,
7
7
  type PlanPacketLike,
8
- } from "../../../lib/harness-run-context.js";
8
+ } from "../harness-run-context.js";
9
9
  import { formatPlanPacketYaml } from "./format-plan.js";
10
10
  import type { PlanResearchBrief } from "./types.js";
11
11
 
12
12
  export {
13
13
  canonicalPlanReviewPath,
14
14
  PLAN_REVIEW_BASENAME,
15
- } from "../../../lib/harness-run-context.js";
15
+ } from "../harness-run-context.js";
16
16
 
17
17
  export type PlanReviewStatus = "draft" | "approved" | "committed";
18
18
 
@@ -33,223 +33,184 @@ function strList(value: unknown): string[] {
33
33
  .filter((item): item is string => Boolean(item));
34
34
  }
35
35
 
36
- /** Render Darwin research sections for plan-review.md. */
37
- export function formatResearchBriefMarkdown(
38
- research: PlanResearchBrief | null | undefined,
39
- ): string {
40
- if (!research) return "";
41
- const lines: string[] = [];
42
- const decomp = asRecord(research.decomposition);
43
- const hyp = asRecord(research.hypothesis);
44
- const evalBrief = asRecord(research.eval);
36
+ function pushListSection(
37
+ lines: string[],
38
+ title: string,
39
+ items: string[],
40
+ ): void {
41
+ if (!items.length) return;
42
+ lines.push(`**${title}:**`);
43
+ for (const item of items) lines.push(`- ${item}`);
44
+ lines.push("");
45
+ }
45
46
 
46
- if (decomp) {
47
- lines.push("## Phase 1 — Problem decomposition");
47
+ function appendDecompositionMarkdown(
48
+ lines: string[],
49
+ decomp: Record<string, unknown>,
50
+ ): void {
51
+ lines.push("## Phase 1 — Problem decomposition", "");
52
+ const restate = str(decomp.problem_restatement);
53
+ if (restate) lines.push("**What is being asked?**", "", restate, "");
54
+ const types = strList(decomp.problem_types);
55
+ if (types.length) lines.push(`**Problem type(s):** ${types.join(", ")}`, "");
56
+ const scope = asRecord(decomp.scope);
57
+ if (scope) {
58
+ const focus = str(scope.narrowed_focus);
59
+ if (focus) lines.push("**Scope:**", "", focus, "");
60
+ pushListSection(lines, "Excluded", strList(scope.excluded));
61
+ }
62
+ for (const [label, key] of [
63
+ ["Hard constraints", "hard_constraints"],
64
+ ["Soft constraints", "soft_constraints"],
65
+ ["Success metrics", "success_metrics"],
66
+ ] as const) {
67
+ pushListSection(lines, label, strList(decomp[key]));
68
+ }
69
+ const prior = asRecord(decomp.prior_art);
70
+ if (prior) {
71
+ lines.push("**Prior art:**", "");
72
+ const best = str(prior.best_approach);
73
+ const gap = str(prior.gap);
74
+ if (best) lines.push(`- Best approach: ${best}`);
75
+ if (gap) lines.push(`- Gap: ${gap}`);
76
+ for (const dead of strList(prior.dead_ends))
77
+ lines.push(`- Dead end: ${dead}`);
48
78
  lines.push("");
49
- const restate = str(decomp.problem_restatement);
50
- if (restate) {
51
- lines.push("**What is being asked?**");
52
- lines.push("");
53
- lines.push(restate);
54
- lines.push("");
55
- }
56
- const types = strList(decomp.problem_types);
57
- if (types.length) {
58
- lines.push(`**Problem type(s):** ${types.join(", ")}`);
59
- lines.push("");
60
- }
61
- const scope = asRecord(decomp.scope);
62
- if (scope) {
63
- const focus = str(scope.narrowed_focus);
64
- if (focus) {
65
- lines.push("**Scope:**");
66
- lines.push("");
67
- lines.push(focus);
68
- lines.push("");
69
- }
70
- const excluded = strList(scope.excluded);
71
- if (excluded.length) {
72
- lines.push("**Excluded:**");
73
- for (const item of excluded) lines.push(`- ${item}`);
74
- lines.push("");
75
- }
76
- }
79
+ }
80
+ const core = str(decomp.core_tension);
81
+ if (core) lines.push("**Core tension:**", "", core, "");
82
+ }
83
+
84
+ function appendHypothesisMarkdown(
85
+ lines: string[],
86
+ hyp: Record<string, unknown>,
87
+ ): void {
88
+ lines.push("## Phase 2 — DARWIN hypothesis", "");
89
+ const primary = asRecord(hyp.primary);
90
+ if (primary) {
77
91
  for (const [label, key] of [
78
- ["Hard constraints", "hard_constraints"],
79
- ["Soft constraints", "soft_constraints"],
80
- ["Success metrics", "success_metrics"],
92
+ ["Claim", "claim"],
93
+ ["Mechanism", "mechanism"],
94
+ ["Prediction", "prediction"],
95
+ ["Experiment", "experiment"],
96
+ ["Resolves tension", "tension_resolution"],
81
97
  ] as const) {
82
- const items = strList(decomp[key]);
83
- if (items.length) {
84
- lines.push(`**${label}:**`);
85
- for (const item of items) lines.push(`- ${item}`);
86
- lines.push("");
87
- }
88
- }
89
- const prior = asRecord(decomp.prior_art);
90
- if (prior) {
91
- lines.push("**Prior art:**");
92
- lines.push("");
93
- const best = str(prior.best_approach);
94
- const gap = str(prior.gap);
95
- if (best) lines.push(`- Best approach: ${best}`);
96
- if (gap) lines.push(`- Gap: ${gap}`);
97
- for (const dead of strList(prior.dead_ends)) {
98
- lines.push(`- Dead end: ${dead}`);
99
- }
100
- lines.push("");
101
- }
102
- const core = str(decomp.core_tension);
103
- if (core) {
104
- lines.push("**Core tension:**");
105
- lines.push("");
106
- lines.push(core);
107
- lines.push("");
98
+ const text = str(primary[key]);
99
+ if (text) lines.push(`**${label}:** ${text}`, "");
108
100
  }
109
101
  }
110
-
111
- if (hyp) {
112
- lines.push("## Phase 2 — DARWIN hypothesis");
102
+ const fork = asRecord(hyp.dialectical_fork);
103
+ if (fork) {
104
+ const forkText = str(fork.fork);
105
+ if (forkText) lines.push(`**Dialectical fork:** ${forkText}`, "");
106
+ const pathA = str(fork.path_a);
107
+ const pathB = str(fork.path_b);
108
+ if (pathA) lines.push(`- **Path A:** ${pathA}`);
109
+ if (pathB) lines.push(`- **Path B:** ${pathB}`);
113
110
  lines.push("");
114
- const primary = asRecord(hyp.primary);
115
- if (primary) {
116
- for (const [label, key] of [
117
- ["Claim", "claim"],
118
- ["Mechanism", "mechanism"],
119
- ["Prediction", "prediction"],
120
- ["Experiment", "experiment"],
121
- ["Resolves tension", "tension_resolution"],
122
- ] as const) {
123
- const text = str(primary[key]);
124
- if (text) {
125
- lines.push(`**${label}:** ${text}`);
126
- lines.push("");
127
- }
128
- }
129
- }
130
- const fork = asRecord(hyp.dialectical_fork);
131
- if (fork) {
132
- const forkText = str(fork.fork);
133
- if (forkText) {
134
- lines.push(`**Dialectical fork:** ${forkText}`);
135
- lines.push("");
136
- }
137
- const pathA = str(fork.path_a);
138
- const pathB = str(fork.path_b);
139
- if (pathA) lines.push(`- **Path A:** ${pathA}`);
140
- if (pathB) lines.push(`- **Path B:** ${pathB}`);
141
- lines.push("");
142
- }
143
- const alts = Array.isArray(hyp.alternatives) ? hyp.alternatives : [];
144
- if (alts.length) {
145
- lines.push("**Alternatives:**");
146
- for (const alt of alts) {
147
- const rec = asRecord(alt);
148
- if (!rec) continue;
149
- const claim = str(rec.claim);
150
- const bet = str(rec.key_bet);
151
- if (claim) lines.push(`- ${claim}${bet ? ` (bet: ${bet})` : ""}`);
152
- }
153
- lines.push("");
154
- }
155
- const steps = strList(hyp.recommended_next_steps);
156
- if (steps.length) {
157
- lines.push("**Recommended next steps:**");
158
- for (const step of steps) lines.push(`1. ${step}`);
159
- lines.push("");
111
+ }
112
+ const alts = Array.isArray(hyp.alternatives) ? hyp.alternatives : [];
113
+ if (alts.length) {
114
+ lines.push("**Alternatives:**");
115
+ for (const alt of alts) {
116
+ const rec = asRecord(alt);
117
+ const claim = rec ? str(rec.claim) : null;
118
+ const bet = rec ? str(rec.key_bet) : null;
119
+ if (claim) lines.push(`- ${claim}${bet ? ` (bet: ${bet})` : ""}`);
160
120
  }
121
+ lines.push("");
161
122
  }
162
-
163
- const impl = asRecord(research.implementation);
164
- if (impl) {
165
- lines.push("## Phase 3.5 — Implementation research");
123
+ const steps = strList(hyp.recommended_next_steps);
124
+ if (steps.length) {
125
+ lines.push("**Recommended next steps:**");
126
+ for (const step of steps) lines.push(`1. ${step}`);
166
127
  lines.push("");
167
- const framing = str(impl.problem_framing);
168
- if (framing) {
169
- lines.push("**Problem framing:**");
170
- lines.push("");
171
- lines.push(framing);
172
- lines.push("");
173
- }
174
- const rec = asRecord(impl.recommended_approach);
175
- if (rec) {
176
- const summary = str(rec.summary);
177
- const conf = str(rec.recommended_approach_confidence);
178
- if (summary) {
179
- lines.push(
180
- `**Recommended approach**${conf ? ` (${conf} confidence)` : ""}:`,
181
- );
182
- lines.push("");
183
- lines.push(summary);
184
- lines.push("");
185
- }
186
- const rationale = str(rec.confidence_rationale);
187
- if (rationale) {
188
- lines.push(`*Rationale:* ${rationale}`);
189
- lines.push("");
190
- }
191
- }
192
- const patterns = Array.isArray(impl.solution_patterns)
193
- ? impl.solution_patterns
194
- : [];
195
- if (patterns.length) {
196
- lines.push("**Solution patterns:**");
197
- for (const p of patterns) {
198
- const pat = asRecord(p);
199
- const name = pat ? str(pat.name) : null;
200
- const fit = pat ? str(pat.fit) : null;
201
- if (name) lines.push(`- **${name}**${fit ? `: ${fit}` : ""}`);
202
- }
203
- lines.push("");
204
- }
205
- const openQs = strList(impl.open_questions);
206
- if (openQs.length) {
207
- lines.push("**Open questions:**");
208
- for (const q of openQs) lines.push(`- ${q}`);
209
- lines.push("");
210
- }
211
- const anti = strList(impl.anti_patterns);
212
- if (anti.length) {
213
- lines.push("**Anti-patterns:**");
214
- for (const a of anti) lines.push(`- ${a}`);
215
- lines.push("");
216
- }
217
128
  }
129
+ }
218
130
 
219
- if (evalBrief) {
220
- lines.push("## Self-evaluation");
221
- lines.push("");
222
- lines.push("| Dimension | Score | Rationale |");
223
- lines.push("|-----------|-------|-----------|");
224
- const dims = asRecord(evalBrief.dimensions);
225
- if (dims) {
226
- for (const name of [
227
- "novelty",
228
- "coherence",
229
- "testability",
230
- "impact",
231
- ] as const) {
232
- const dim = asRecord(dims[name]);
233
- if (!dim) continue;
234
- const score = typeof dim.score === "number" ? String(dim.score) : "?";
235
- const rationale = str(dim.rationale) ?? "";
236
- lines.push(`| ${name} | ${score}/100 | ${rationale} |`);
237
- }
131
+ function appendImplementationMarkdown(
132
+ lines: string[],
133
+ impl: Record<string, unknown>,
134
+ ): void {
135
+ lines.push("## Phase 3.5 — Implementation research", "");
136
+ const framing = str(impl.problem_framing);
137
+ if (framing) lines.push("**Problem framing:**", "", framing, "");
138
+ const rec = asRecord(impl.recommended_approach);
139
+ if (rec) {
140
+ const summary = str(rec.summary);
141
+ const conf = str(rec.recommended_approach_confidence);
142
+ if (summary) {
143
+ lines.push(
144
+ `**Recommended approach**${conf ? ` (${conf} confidence)` : ""}:`,
145
+ );
146
+ lines.push("", summary, "");
238
147
  }
239
- const rel = asRecord(evalBrief.relevance);
240
- if (rel) {
241
- const passes = rel.passes === true ? "✓" : "✗";
242
- const rationale = str(rel.rationale) ?? "";
243
- lines.push(`| Relevance | ${passes} | ${rationale} |`);
148
+ const rationale = str(rec.confidence_rationale);
149
+ if (rationale) lines.push(`*Rationale:* ${rationale}`, "");
150
+ }
151
+ const patterns = Array.isArray(impl.solution_patterns)
152
+ ? impl.solution_patterns
153
+ : [];
154
+ if (patterns.length) {
155
+ lines.push("**Solution patterns:**");
156
+ for (const p of patterns) {
157
+ const pat = asRecord(p);
158
+ const name = pat ? str(pat.name) : null;
159
+ const fit = pat ? str(pat.fit) : null;
160
+ if (name) lines.push(`- **${name}**${fit ? `: ${fit}` : ""}`);
244
161
  }
245
162
  lines.push("");
246
- const summary = str(evalBrief.human_summary);
247
- if (summary) {
248
- lines.push(summary);
249
- lines.push("");
163
+ }
164
+ pushListSection(lines, "Open questions", strList(impl.open_questions));
165
+ pushListSection(lines, "Anti-patterns", strList(impl.anti_patterns));
166
+ }
167
+
168
+ function appendEvaluationMarkdown(
169
+ lines: string[],
170
+ evalBrief: Record<string, unknown>,
171
+ ): void {
172
+ lines.push("## Self-evaluation", "");
173
+ lines.push("| Dimension | Score | Rationale |");
174
+ lines.push("|-----------|-------|-----------|");
175
+ const dims = asRecord(evalBrief.dimensions);
176
+ if (dims) {
177
+ for (const name of [
178
+ "novelty",
179
+ "coherence",
180
+ "testability",
181
+ "impact",
182
+ ] as const) {
183
+ const dim = asRecord(dims[name]);
184
+ if (!dim) continue;
185
+ const score = typeof dim.score === "number" ? String(dim.score) : "?";
186
+ lines.push(`| ${name} | ${score}/100 | ${str(dim.rationale) ?? ""} |`);
250
187
  }
251
188
  }
189
+ const rel = asRecord(evalBrief.relevance);
190
+ if (rel) {
191
+ const passes = rel.passes === true ? "✓" : "✗";
192
+ lines.push(`| Relevance | ${passes} | ${str(rel.rationale) ?? ""} |`);
193
+ }
194
+ lines.push("");
195
+ const summary = str(evalBrief.human_summary);
196
+ if (summary) lines.push(summary, "");
197
+ }
252
198
 
199
+ /** Render Darwin research sections for plan-review.md. */
200
+ export function formatResearchBriefMarkdown(
201
+ research: PlanResearchBrief | null | undefined,
202
+ ): string {
203
+ if (!research) return "";
204
+ const lines: string[] = [];
205
+ const sections = [
206
+ [asRecord(research.decomposition), appendDecompositionMarkdown],
207
+ [asRecord(research.hypothesis), appendHypothesisMarkdown],
208
+ [asRecord(research.implementation), appendImplementationMarkdown],
209
+ [asRecord(research.eval), appendEvaluationMarkdown],
210
+ ] as const;
211
+ for (const [section, append] of sections) {
212
+ if (section) append(lines, section);
213
+ }
253
214
  return lines.length ? `${lines.join("\n")}\n` : "";
254
215
  }
255
216
 
@@ -4,7 +4,7 @@ import type {
4
4
  ToolRenderResultOptions,
5
5
  } from "@earendil-works/pi-coding-agent";
6
6
  import { Text, truncateToWidth } from "@earendil-works/pi-tui";
7
- import type { PlanPacketLike } from "../../../lib/harness-run-context.js";
7
+ import type { PlanPacketLike } from "../harness-run-context.js";
8
8
  import { formatPlanPacketLines } from "./format-plan.js";
9
9
  import type { ApprovePlanToolDetails } from "./types.js";
10
10
 
@@ -7,8 +7,8 @@ import {
7
7
  RESEARCH_BRIEF_BASENAME,
8
8
  readPlanPacketFromPath,
9
9
  validatePlanPacket,
10
- } from "../../../lib/harness-run-context.js";
11
- import { readYamlFile } from "../../../lib/harness-yaml.js";
10
+ } from "../harness-run-context.js";
11
+ import { readYamlFile } from "../harness-yaml.js";
12
12
  import type { ApprovePlanParams, PlanResearchBrief } from "./types.js";
13
13
 
14
14
  function isNonEmptyPacket(
@@ -1,5 +1,5 @@
1
- import type { PlanPacketLike } from "../../../lib/harness-run-context.js";
2
1
  import type { AskResponse, DialogResult } from "../ask-user/types.js";
2
+ import type { PlanPacketLike } from "../harness-run-context.js";
3
3
 
4
4
  export const DEFAULT_PLAN_APPROVAL_OPTIONS = [
5
5
  "Approve",
@@ -1,9 +1,9 @@
1
+ import type { AskResponse } from "../ask-user/types.js";
2
+ import { formatResultText } from "../ask-user/validate.js";
1
3
  import {
2
4
  type PlanPacketLike,
3
5
  validatePlanPacket,
4
- } from "../../../lib/harness-run-context.js";
5
- import type { AskResponse } from "../ask-user/types.js";
6
- import { formatResultText } from "../ask-user/validate.js";
6
+ } from "../harness-run-context.js";
7
7
  import type {
8
8
  ApprovePlanParams,
9
9
  ApprovePlanToolDetails,
@@ -2,7 +2,7 @@
2
2
  * Plan Review Gate — convert integrator YAML to debate bus round JSON.
3
3
  */
4
4
 
5
- import type { DebateParticipant } from "../../lib/debate-orchestrator-types.js";
5
+ import type { DebateParticipant } from "./debate-orchestrator-types.js";
6
6
 
7
7
  export interface PlanReviewRoundDraft {
8
8
  schema_version: string;
@@ -5,8 +5,8 @@
5
5
  import { constants } from "node:fs";
6
6
  import { access, readFile } from "node:fs/promises";
7
7
  import { join } from "node:path";
8
- import { isHarnessBudgetEnforceOn } from "../../lib/harness-budget-enforce.js";
9
8
  import { capsForDebate } from "./debate-bus-core.js";
9
+ import { isHarnessBudgetEnforceOn } from "./harness-budget-enforce.js";
10
10
  import type { DebateEligibilityResult } from "./plan-debate-eligibility.js";
11
11
  import {
12
12
  getPlanFocusCoverage,
@@ -5,10 +5,7 @@
5
5
  import { constants } from "node:fs";
6
6
  import { access, mkdir } from "node:fs/promises";
7
7
  import { dirname, join } from "node:path";
8
- import {
9
- parseStructuredDocument,
10
- writeYamlFile,
11
- } from "../../lib/harness-yaml.js";
8
+ import { parseStructuredDocument, writeYamlFile } from "./harness-yaml.js";
12
9
  import { postMessengerMessage } from "./plan-messenger.js";
13
10
 
14
11
  export type DebateLaneKind =
@@ -16,7 +16,7 @@ import {
16
16
  writeFile,
17
17
  } from "node:fs/promises";
18
18
  import { join } from "node:path";
19
- import type { DebateParticipant } from "../../lib/debate-orchestrator-types.js";
19
+ import type { DebateParticipant } from "./debate-orchestrator-types.js";
20
20
  import type { DebateProfile } from "./plan-debate-eligibility.js";
21
21
  import type { PlanDebateFocus } from "./plan-debate-focus.js";
22
22
 
@@ -211,7 +211,7 @@ Med/low non-fork plans with clear stack and no implementation `open_questions` d
211
211
 
212
212
  ## Phase 5 — Structured inspection / Review Gate (Fagan-style)
213
213
 
214
- **Practice:** Code Complete collaborative construction; Fagan inspection with rubrics in `planning-rubrics.md`. Parent is **chair**; one debate agent per `subagent` batch.
214
+ **Practice:** Code Complete collaborative construction; Fagan inspection with rubrics in `.pi/harness/docs/planning-rubrics.md`. Parent is **chair**; one debate agent per `subagent` batch.
215
215
 
216
216
  **Forbidden:** parallel `subagent` calls for any debate lane agent in one batch.
217
217