pi-harness-runtime 1.1.439 → 1.1.441

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 (359) hide show
  1. package/harness/e2e/auto-test-loop.ts +8 -2
  2. package/harness/e2e/browser-scrapers/base-browser-scraper.ts +2 -0
  3. package/harness/e2e/browser-scrapers/chrome-profile-manager.ts +2 -0
  4. package/harness/e2e/browser-scrapers/codex-browser-scraper.ts +2 -0
  5. package/harness/e2e/tools-detector.ts +2 -0
  6. package/harness/index.ts +2 -1
  7. package/harness/key-loader.ts +2 -0
  8. package/harness/langchain/checkpointer.ts +2 -0
  9. package/harness/langchain/cron-cli.ts +2 -0
  10. package/harness/langchain/graph.ts +2 -0
  11. package/harness/master-planner.ts +1 -1
  12. package/harness/notification-center.ts +2 -0
  13. package/harness/output-limit-handler.ts +1 -1
  14. package/harness/project-detector/detector.ts +2 -4
  15. package/harness/secret-provider.ts +2 -0
  16. package/harness/task-graph.ts +460 -113
  17. package/index.ts +16 -7
  18. package/package.json +7 -1
  19. package/packages/a2a-adapter/package.json +1 -1
  20. package/packages/agent-policy/dist/extension.d.ts.map +1 -1
  21. package/packages/agent-policy/dist/extension.js +2 -0
  22. package/packages/agent-policy/dist/extension.js.map +1 -1
  23. package/packages/agent-policy/package.json +1 -1
  24. package/packages/agent-policy/src/extension.ts +2 -0
  25. package/packages/architecture-generator/package.json +1 -1
  26. package/packages/auth/dist/minimax-browser-auth.d.ts.map +1 -1
  27. package/packages/auth/dist/minimax-browser-auth.js +23 -1
  28. package/packages/auth/dist/minimax-browser-auth.js.map +1 -1
  29. package/packages/auth/package.json +1 -1
  30. package/packages/auth/src/minimax-browser-auth.ts +30 -5
  31. package/packages/autonomous-refactor/package.json +1 -1
  32. package/packages/autonomous-runtime/dist/inbox.d.ts.map +1 -1
  33. package/packages/autonomous-runtime/dist/inbox.js +2 -0
  34. package/packages/autonomous-runtime/dist/inbox.js.map +1 -1
  35. package/packages/autonomous-runtime/package.json +1 -1
  36. package/packages/autonomous-runtime/src/inbox.ts +2 -0
  37. package/packages/cache-strategy/package.json +1 -1
  38. package/packages/capability-registry/package.json +1 -1
  39. package/packages/checkpoint/package.json +1 -1
  40. package/packages/cli-plugin-sdk/package.json +1 -1
  41. package/packages/clipboard/dist/src/clipboard.d.ts.map +1 -1
  42. package/packages/clipboard/dist/src/clipboard.js +2 -0
  43. package/packages/clipboard/dist/src/clipboard.js.map +1 -1
  44. package/packages/clipboard/dist/src/copy-sync.d.ts.map +1 -1
  45. package/packages/clipboard/dist/src/copy-sync.js +2 -0
  46. package/packages/clipboard/dist/src/copy-sync.js.map +1 -1
  47. package/packages/clipboard/dist/src/gist-relay.d.ts.map +1 -1
  48. package/packages/clipboard/dist/src/gist-relay.js +2 -0
  49. package/packages/clipboard/dist/src/gist-relay.js.map +1 -1
  50. package/packages/clipboard/package.json +1 -1
  51. package/packages/clipboard/src/clipboard.ts +2 -0
  52. package/packages/clipboard/src/copy-sync.ts +2 -0
  53. package/packages/clipboard/src/gist-relay.ts +2 -0
  54. package/packages/clipboard-plugin/dist/types.d.ts +9 -2
  55. package/packages/clipboard-plugin/dist/types.d.ts.map +1 -1
  56. package/packages/clipboard-plugin/package.json +1 -1
  57. package/packages/clipboard-plugin/src/types.ts +9 -2
  58. package/packages/code-generation/package.json +1 -1
  59. package/packages/code-review/package.json +1 -1
  60. package/packages/codex-adapter/package.json +1 -1
  61. package/packages/codex-watcher/package.json +1 -1
  62. package/packages/config-capture/package.json +1 -1
  63. package/packages/connection-runtime/package.json +1 -1
  64. package/packages/context-compiler/package.json +1 -1
  65. package/packages/context-discovery/package.json +1 -1
  66. package/packages/context-manager/package.json +1 -1
  67. package/packages/contracts/dist/delegation-store.js +1 -4
  68. package/packages/contracts/dist/workspace-env.js +28 -1
  69. package/packages/contracts/package.json +1 -1
  70. package/packages/contracts/src/delegation-store.ts +9 -4
  71. package/packages/contracts/src/workspace-env.ts +29 -4
  72. package/packages/cookie-sanitizer/package.json +1 -1
  73. package/packages/cost-optimizer/package.json +1 -1
  74. package/packages/dependency-analyzer/package.json +1 -1
  75. package/packages/django-plugin/package.json +1 -1
  76. package/packages/doc-generator/package.json +1 -1
  77. package/packages/durable-review/package.json +1 -1
  78. package/packages/e2e-tester/package.json +1 -1
  79. package/packages/evaluation-engine/package.json +1 -1
  80. package/packages/evaluation-runner/package.json +1 -1
  81. package/packages/event-bus/package.json +1 -1
  82. package/packages/event-sink/package.json +1 -1
  83. package/packages/event-store/dist/src/store.d.ts.map +1 -1
  84. package/packages/event-store/dist/src/store.js +2 -0
  85. package/packages/event-store/dist/src/store.js.map +1 -1
  86. package/packages/event-store/package.json +1 -1
  87. package/packages/event-store/src/store.ts +3 -0
  88. package/packages/experience-replay/package.json +1 -1
  89. package/packages/feedback-collector/package.json +1 -1
  90. package/packages/file-copy-helper/package.json +1 -1
  91. package/packages/framework-detector/package.json +1 -1
  92. package/packages/framework-plugin-sdk/package.json +1 -1
  93. package/packages/frappe-plugin/package.json +1 -1
  94. package/packages/generic-web-plugin/dist/analyzer.d.ts.map +1 -1
  95. package/packages/generic-web-plugin/dist/analyzer.js +2 -0
  96. package/packages/generic-web-plugin/dist/analyzer.js.map +1 -1
  97. package/packages/generic-web-plugin/package.json +1 -1
  98. package/packages/generic-web-plugin/src/analyzer.ts +3 -0
  99. package/packages/health-monitor/package.json +1 -1
  100. package/packages/intent-analyzer/package.json +1 -1
  101. package/packages/jev-judge/package.json +1 -1
  102. package/packages/knowledge-graph/package.json +1 -1
  103. package/packages/knowledge-retrieval/dist/mcp-client.d.ts.map +1 -1
  104. package/packages/knowledge-retrieval/dist/mcp-client.js +0 -1
  105. package/packages/knowledge-retrieval/dist/mcp-client.js.map +1 -1
  106. package/packages/knowledge-retrieval/package.json +1 -4
  107. package/packages/knowledge-retrieval/src/mcp-client.ts +0 -1
  108. package/packages/laravel-plugin/package.json +1 -1
  109. package/packages/learning-engine/package.json +1 -1
  110. package/packages/logging/package.json +1 -1
  111. package/packages/mcp-adapter/dist/server.d.ts.map +1 -1
  112. package/packages/mcp-adapter/dist/server.js +2 -0
  113. package/packages/mcp-adapter/dist/server.js.map +1 -1
  114. package/packages/mcp-adapter/package.json +1 -1
  115. package/packages/mcp-adapter/src/server.ts +3 -0
  116. package/packages/memory-engine/package.json +1 -1
  117. package/packages/milestone-manager/package.json +1 -1
  118. package/packages/model-registry/package.json +1 -1
  119. package/packages/nextjs-plugin/package.json +1 -1
  120. package/packages/notification/package.json +1 -1
  121. package/packages/observability/package.json +1 -1
  122. package/packages/okf-indexer/package.json +1 -1
  123. package/packages/paperclip-integration/dist/index.d.ts.map +1 -1
  124. package/packages/paperclip-integration/dist/index.js +2 -0
  125. package/packages/paperclip-integration/dist/index.js.map +1 -1
  126. package/packages/paperclip-integration/package.json +1 -1
  127. package/packages/paperclip-integration/src/index.ts +2 -0
  128. package/packages/performance-optimizer/package.json +1 -1
  129. package/packages/permission-mode/package.json +1 -1
  130. package/packages/privilege-broker/dist/audit.d.ts.map +1 -1
  131. package/packages/privilege-broker/dist/audit.js +2 -0
  132. package/packages/privilege-broker/dist/audit.js.map +1 -1
  133. package/packages/privilege-broker/package.json +1 -1
  134. package/packages/privilege-broker/src/audit.ts +2 -0
  135. package/packages/project-analyzer/package.json +1 -1
  136. package/packages/project-bootstrap/package.json +1 -1
  137. package/packages/projection-engine/package.json +1 -1
  138. package/packages/prompt-compiler/dist/compiler.d.ts.map +1 -1
  139. package/packages/prompt-compiler/dist/compiler.js +2 -0
  140. package/packages/prompt-compiler/dist/compiler.js.map +1 -1
  141. package/packages/prompt-compiler/package.json +1 -1
  142. package/packages/prompt-compiler/src/compiler.ts +2 -0
  143. package/packages/prompt-versioning/package.json +1 -1
  144. package/packages/provider-adapter-sdk/package.json +1 -1
  145. package/packages/provider-router/package.json +1 -1
  146. package/packages/provider-selector/package.json +1 -1
  147. package/packages/providers/package.json +1 -1
  148. package/packages/qdrant-skills/package.json +1 -1
  149. package/packages/quota-manager/package.json +1 -1
  150. package/packages/rate-limiter/package.json +1 -1
  151. package/packages/react-vite-plugin/package.json +1 -1
  152. package/packages/relay/package.json +1 -1
  153. package/packages/release-manager/package.json +1 -1
  154. package/packages/requirement-compiler/package.json +1 -1
  155. package/packages/runtime/package.json +1 -1
  156. package/packages/scheduler/package.json +1 -1
  157. package/packages/scheduler-adapter/package.json +1 -1
  158. package/packages/session/package.json +1 -1
  159. package/packages/session-api/package.json +1 -1
  160. package/packages/session-export/package.json +1 -1
  161. package/packages/shared-context/package.json +1 -1
  162. package/packages/skill-mcp-client/dist/client.d.ts.map +1 -1
  163. package/packages/skill-mcp-client/dist/client.js +0 -1
  164. package/packages/skill-mcp-client/dist/client.js.map +1 -1
  165. package/packages/skill-mcp-client/package.json +1 -4
  166. package/packages/skill-mcp-client/src/client.ts +0 -1
  167. package/packages/skill-registry/package.json +1 -1
  168. package/packages/skills/dist/parser.d.ts.map +1 -1
  169. package/packages/skills/dist/parser.js +2 -0
  170. package/packages/skills/dist/parser.js.map +1 -1
  171. package/packages/skills/dist/skill-versioning.d.ts.map +1 -1
  172. package/packages/skills/dist/skill-versioning.js +2 -0
  173. package/packages/skills/dist/skill-versioning.js.map +1 -1
  174. package/packages/skills/package.json +1 -1
  175. package/packages/skills/src/parser.ts +3 -0
  176. package/packages/skills/src/skill-versioning.ts +2 -0
  177. package/packages/sprint-planner/package.json +1 -1
  178. package/packages/subscription-engine/package.json +1 -1
  179. package/packages/task-compiler/package.json +1 -1
  180. package/packages/tencentdb-memory/package.json +1 -1
  181. package/packages/tencentdb-sync/package.json +1 -1
  182. package/packages/test-data-generator/package.json +1 -1
  183. package/packages/test-generator/package.json +1 -1
  184. package/packages/todo-bd-sync/package.json +1 -1
  185. package/packages/token-estimation/package.json +1 -1
  186. package/packages/token-optimizer/package.json +1 -1
  187. package/packages/tooling-preference/package.json +1 -1
  188. package/packages/trajectory/package.json +1 -1
  189. package/packages/tui/package.json +1 -1
  190. package/packages/two-phase-review/package.json +1 -1
  191. package/packages/types/package.json +1 -1
  192. package/packages/voice-api/package.json +1 -1
  193. package/packages/webmcp-tester/dist/index.js +0 -2
  194. package/packages/webmcp-tester/package.json +1 -1
  195. package/packages/webmcp-tester/src/index.ts +0 -3
  196. package/packages/wiki/package.json +1 -1
  197. package/packages/workflow-events/package.json +1 -1
  198. package/packages/workspace-scanner/package.json +1 -1
  199. package/packages/worktree/package.json +1 -1
  200. package/packages/write-review/dist/trigger.d.ts.map +1 -1
  201. package/packages/write-review/dist/trigger.js +1 -2
  202. package/packages/write-review/dist/trigger.js.map +1 -1
  203. package/packages/write-review/package.json +1 -1
  204. package/packages/write-review/src/trigger.ts +1 -2
  205. package/scripts/lib/runtime-imports.ts +189 -3
  206. package/scripts/release-all.ts +5 -3
  207. package/scripts/telegram-webhook-server.ts +2 -0
  208. package/scripts/typecheck-packages.mjs +7 -4
  209. package/scripts/verify-package-contents.ts +161 -2
  210. package/harness/e2e/tools-detector.test.ts +0 -156
  211. package/harness/glm-quota-countdown.test.ts +0 -323
  212. package/harness/langchain/agents.test.ts +0 -39
  213. package/harness/langchain/checkpointer.test.ts +0 -243
  214. package/harness/langchain/daemon.test.ts +0 -459
  215. package/harness/langchain/model-router.test.ts +0 -191
  216. package/harness/langchain/ping-pong-middleware.test.ts +0 -69
  217. package/harness/langchain/scoreboard.test.ts +0 -245
  218. package/harness/langchain/status-line.test.ts +0 -106
  219. package/harness/langchain/surge.test.ts +0 -467
  220. package/harness/langchain/widget.test.ts +0 -251
  221. package/harness/skill-sync.test.ts +0 -57
  222. package/harness/ssh-detach-interceptor.test.ts +0 -263
  223. package/harness/ssh-hang-recovery.test.ts +0 -86
  224. package/packages/a2a-adapter/test/a2a.test.ts +0 -151
  225. package/packages/agent-policy/test/interlock.test.ts +0 -101
  226. package/packages/agent-policy/test/policy-retention.test.ts +0 -380
  227. package/packages/agent-policy/test/policy.test.ts +0 -387
  228. package/packages/auth/test/auth.test.ts +0 -238
  229. package/packages/autonomous-refactor/test/refactor.test.ts +0 -202
  230. package/packages/autonomous-runtime/test/types.test.ts +0 -95
  231. package/packages/cache-strategy/test/cache.test.ts +0 -137
  232. package/packages/capability-registry/test/registry.test.ts +0 -204
  233. package/packages/checkpoint/test/engine.test.ts +0 -265
  234. package/packages/cli-plugin-sdk/test/cli.test.ts +0 -45
  235. package/packages/code-generation/test/generator.test.ts +0 -238
  236. package/packages/code-review/test/engine.test.ts +0 -302
  237. package/packages/codex-adapter/test/provider.test.ts +0 -142
  238. package/packages/codex-watcher/test/watch.test.ts +0 -453
  239. package/packages/context-compiler/test/context-compiler.test.ts +0 -746
  240. package/packages/context-manager/test/context.test.ts +0 -198
  241. package/packages/contracts/test/delegation.test.ts +0 -350
  242. package/packages/contracts/test/workspace-env.test.ts +0 -802
  243. package/packages/cookie-sanitizer/test/infer.test.ts +0 -110
  244. package/packages/cookie-sanitizer/test/normalize.test.ts +0 -113
  245. package/packages/cookie-sanitizer/test/parse.test.ts +0 -204
  246. package/packages/cookie-sanitizer/test/sync.test.ts +0 -237
  247. package/packages/cookie-sanitizer/test/watcher.test.ts +0 -27
  248. package/packages/cost-optimizer/test/cost-optimizer.test.ts +0 -438
  249. package/packages/dependency-analyzer/test/analyzer.test.ts +0 -49
  250. package/packages/django-plugin/test/analyzer.test.ts +0 -195
  251. package/packages/doc-generator/test/docs.test.ts +0 -168
  252. package/packages/durable-review/test/acceptance.test.ts +0 -357
  253. package/packages/durable-review/test/smoke.test.ts +0 -107
  254. package/packages/evaluation-engine/test/engine.test.ts +0 -277
  255. package/packages/evaluation-runner/test/runner.test.ts +0 -168
  256. package/packages/event-bus/test/bus.test.ts +0 -100
  257. package/packages/event-store/test/store.test.ts +0 -115
  258. package/packages/experience-replay/test/replay.test.ts +0 -267
  259. package/packages/feedback-collector/test/collector.test.ts +0 -142
  260. package/packages/framework-detector/test/detector.test.ts +0 -75
  261. package/packages/framework-plugin-sdk/test/manager.test.ts +0 -320
  262. package/packages/frappe-plugin/test/analyzer.test.ts +0 -250
  263. package/packages/generic-web-plugin/test/analyzer.test.ts +0 -134
  264. package/packages/health-monitor/test/health.test.ts +0 -231
  265. package/packages/intent-analyzer/test/analyzer.test.ts +0 -72
  266. package/packages/intent-analyzer/test/ping-pong.test.ts +0 -96
  267. package/packages/jev-judge/tests/auto-continue-context.test.ts +0 -280
  268. package/packages/jev-judge/tests/continuation-controller.test.ts +0 -1396
  269. package/packages/jev-judge/tests/jev-provider-chain.test.ts +0 -536
  270. package/packages/jev-judge/tests/outcome-application.test.ts +0 -132
  271. package/packages/jev-judge/tests/question-risk.test.ts +0 -129
  272. package/packages/jev-judge/tests/typesafe-provider.test.ts +0 -640
  273. package/packages/jev-judge/tests/validation-ledger.test.ts +0 -181
  274. package/packages/jev-judge/tests/validation-plan.test.ts +0 -170
  275. package/packages/jev-judge/tests/validation-tie-breaker.test.ts +0 -88
  276. package/packages/laravel-plugin/test/analyzer.test.ts +0 -220
  277. package/packages/learning-engine/test/engine.test.ts +0 -331
  278. package/packages/logging/test/buffer.test.ts +0 -44
  279. package/packages/logging/test/classification.test.ts +0 -137
  280. package/packages/logging/test/config.test.ts +0 -97
  281. package/packages/logging/test/fanout.test.ts +0 -186
  282. package/packages/logging/test/identity-transport.test.ts +0 -197
  283. package/packages/logging/test/incidents.test.ts +0 -404
  284. package/packages/logging/test/ingest-schema.test.ts +0 -184
  285. package/packages/logging/test/integration.test.ts +0 -140
  286. package/packages/logging/test/log-http.test.ts +0 -246
  287. package/packages/logging/test/redact.test.ts +0 -109
  288. package/packages/logging/test/sampler.test.ts +0 -57
  289. package/packages/logging/test/server.test.ts +0 -444
  290. package/packages/logging/test/shipper.test.ts +0 -152
  291. package/packages/logging/test/spool.test.ts +0 -96
  292. package/packages/mcp-adapter/test/server.test.ts +0 -91
  293. package/packages/memory-engine/test/engine.test.ts +0 -456
  294. package/packages/model-registry/test/registry.test.ts +0 -342
  295. package/packages/nextjs-plugin/test/analyzer.test.ts +0 -149
  296. package/packages/notification/test/approval-payload.test.ts +0 -269
  297. package/packages/notification/test/detail-format.test.ts +0 -106
  298. package/packages/notification/test/notification.test.ts +0 -375
  299. package/packages/notification/test/pending-question-lifecycle.test.ts +0 -195
  300. package/packages/notification/test/pending-question.test.ts +0 -331
  301. package/packages/notification/test/tooling-proposal-payload.test.ts +0 -212
  302. package/packages/observability/test/observability.test.ts +0 -1350
  303. package/packages/performance-optimizer/test/optimizer.test.ts +0 -267
  304. package/packages/project-analyzer/test/index.test.ts +0 -1719
  305. package/packages/prompt-compiler/test/prompt-compiler.test.ts +0 -813
  306. package/packages/prompt-versioning/test/versioning.test.ts +0 -112
  307. package/packages/provider-adapter-sdk/test/sdk.test.ts +0 -220
  308. package/packages/provider-router/test/provider-router.test.ts +0 -405
  309. package/packages/provider-selector/test/selector.test.ts +0 -192
  310. package/packages/providers/test/providers.test.ts +0 -225
  311. package/packages/qdrant-skills/test/collection-info.test.ts +0 -165
  312. package/packages/qdrant-skills/test/embedder-batch.test.ts +0 -184
  313. package/packages/qdrant-skills/test/embedder.test.ts +0 -97
  314. package/packages/quota-manager/test/quota.test.ts +0 -432
  315. package/packages/rate-limiter/test/limiter.test.ts +0 -128
  316. package/packages/react-vite-plugin/test/analyzer.test.ts +0 -139
  317. package/packages/relay/test/client.test.ts +0 -446
  318. package/packages/relay/test/relay-e2e.test.ts +0 -299
  319. package/packages/relay/test/relay-endpoint.test.ts +0 -278
  320. package/packages/release-manager/test/release.test.ts +0 -215
  321. package/packages/requirement-compiler/test/requirement-compiler.test.ts +0 -743
  322. package/packages/runtime/test/runtime-api.test.ts +0 -169
  323. package/packages/runtime/test/runtime.test.ts +0 -297
  324. package/packages/scheduler/test/scheduler.test.ts +0 -125
  325. package/packages/session/test/manager.test.ts +0 -233
  326. package/packages/shared-context/test/shared-context.test.ts +0 -114
  327. package/packages/skill-registry/test/registry.test.ts +0 -508
  328. package/packages/skills/test/init-skills.test.ts +0 -114
  329. package/packages/skills/test/remote-skills.test.ts +0 -360
  330. package/packages/skills/test/remote-source.test.ts +0 -248
  331. package/packages/skills/test/sanitize.test.ts +0 -250
  332. package/packages/skills/test/vector-indexing.test.ts +0 -205
  333. package/packages/skills/test/vector-schema.test.ts +0 -180
  334. package/packages/skills/test/vector-threshold.test.ts +0 -108
  335. package/packages/sprint-planner/test/planner.test.ts +0 -187
  336. package/packages/task-compiler/test/task-compiler.test.ts +0 -628
  337. package/packages/test-data-generator/test/generator.test.ts +0 -265
  338. package/packages/test-generator/test/generator.test.ts +0 -156
  339. package/packages/token-estimation/test/token-estimation.test.ts +0 -207
  340. package/packages/token-optimizer/test/optimizer.test.ts +0 -141
  341. package/packages/tooling-preference/tests/changed-files.test.ts +0 -124
  342. package/packages/tooling-preference/tests/detect.test.ts +0 -188
  343. package/packages/tooling-preference/tests/proposal.test.ts +0 -107
  344. package/packages/tooling-preference/tests/quality-check.test.ts +0 -272
  345. package/packages/tooling-preference/tests/registry.test.ts +0 -51
  346. package/packages/tooling-preference/tests/store.test.ts +0 -99
  347. package/packages/trajectory/test/store.test.ts +0 -250
  348. package/packages/tui/test/harness-footer.test.ts +0 -559
  349. package/packages/tui/test/harness-header.test.ts +0 -590
  350. package/packages/two-phase-review/test/classify.test.ts +0 -102
  351. package/packages/two-phase-review/test/helpers.ts +0 -72
  352. package/packages/two-phase-review/test/rules.test.ts +0 -150
  353. package/packages/two-phase-review/test/runtime.test.ts +0 -362
  354. package/packages/two-phase-review/test/scope.test.ts +0 -186
  355. package/packages/two-phase-review/test/signals.test.ts +0 -183
  356. package/packages/two-phase-review/test/state.test.ts +0 -201
  357. package/packages/wiki/test/basic.test.ts +0 -242
  358. package/packages/workspace-scanner/test/scanner.test.ts +0 -43
  359. package/packages/worktree/test/worktree.test.ts +0 -163
@@ -1,143 +1,490 @@
1
1
  /**
2
- * Task Graph Manager — RFC-0028 Phase 3
2
+ * Task Graph — RFC-0016 (DAG) with the RFC-0028 compact view.
3
3
  *
4
- * Manages task dependency graph for compact-aware scheduling.
5
- * Currently a stub — integrates with CompactOrchestrator for
6
- * dependency-aware compaction prioritization.
4
+ * There is one implementation and one API. The concrete RFC-0016 graph owns
5
+ * the dependency tracking, the status transitions, the retry state, the
6
+ * persistence and the topological order. RFC-0028 only added a
7
+ * compact-priority view on top of a task list, so that view is adapted onto
8
+ * the concrete task nodes here instead of living in a second, incompatible
9
+ * implementation.
7
10
  *
8
- * Future work:
9
- * - Track task dependencies (blocking/ready tasks)
10
- * - Prioritize compaction to keep blocking path messages
11
- * - Track which tasks depend on which checkpoint artifacts
11
+ * A task is READY only when all of its dependencies are DONE.
12
12
  */
13
13
 
14
- import type { RuntimeTask } from "../packages/types/src/runtime-types.js";
14
+ import type {
15
+ TaskGraph,
16
+ TaskNode,
17
+ TaskStatus,
18
+ } from "../packages/types/dist/runtime-types.js";
19
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
20
+ import { dirname, join } from "node:path";
15
21
 
16
- export interface TaskNode {
17
- task: RuntimeTask;
18
- dependencies: Set<string>;
19
- dependents: Set<string>;
20
- status: "pending" | "ready" | "running" | "done" | "blocked";
22
+ /**
23
+ * Write a JSON file, creating the parent directory when needed.
24
+ *
25
+ * The two helpers below are local on purpose: this module is loaded by the
26
+ * node test suite, and node resolves a module path literally. A cross
27
+ * directory import would either need the compiled ".js" convention (which
28
+ * node cannot map back to a TypeScript source) or a ".ts" specifier (which
29
+ * the compiler rejects unless a project opts into it).
30
+ */
31
+ function writeJsonFile(path: string, data: unknown): void {
32
+ mkdirSync(dirname(path), { recursive: true });
33
+ writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`, "utf-8");
34
+ }
35
+
36
+ /** Read a JSON file. Returns null when it is missing or unreadable. */
37
+ function readJsonFile(path: string): unknown | null {
38
+ try {
39
+ return JSON.parse(readFileSync(path, "utf-8"));
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+
45
+ export interface TaskGraphOptions {
46
+ jobId: string;
47
+ rootDir?: string;
48
+ }
49
+
50
+ /**
51
+ * A task that is added to the graph.
52
+ *
53
+ * `status` is optional. When it is missing the status is derived from the
54
+ * dependencies: a task without dependencies is READY, a task with
55
+ * dependencies waits in PENDING until they are done.
56
+ */
57
+ export interface TaskDescription {
58
+ id: string;
59
+ title: string;
60
+ description: string;
61
+ status?: TaskStatus;
62
+ dependencies?: string[];
63
+ acceptanceCriteria?: string[];
21
64
  }
22
65
 
23
- export interface TaskGraphManager {
24
- /** Add a task to the graph */
25
- addTask(task: RuntimeTask): void;
66
+ export class TaskGraphManager {
67
+ private graph: TaskGraph;
68
+ private dirty = false;
69
+
70
+ constructor(options: TaskGraphOptions) {
71
+ this.graph = {
72
+ jobId: options.jobId,
73
+ nodes: {},
74
+ topologicalOrder: [],
75
+ };
76
+ }
77
+
78
+ /**
79
+ * Wrap an existing graph, for example a planned graph or a loaded one.
80
+ * The manager then works on that graph instead of an empty one.
81
+ */
82
+ static fromGraph(graph: TaskGraph): TaskGraphManager {
83
+ const manager = new TaskGraphManager({ jobId: graph.jobId });
84
+ manager.graph = graph;
85
+ return manager;
86
+ }
87
+
88
+ /**
89
+ * Add a task node to the graph.
90
+ *
91
+ * Both call forms are supported: the planner describes a task by its
92
+ * parts, and the runtime hands over a task object it already holds.
93
+ */
94
+ addTask(task: TaskDescription): TaskNode;
95
+ addTask(
96
+ id: string,
97
+ title: string,
98
+ description: string,
99
+ dependencies?: string[],
100
+ acceptanceCriteria?: string[],
101
+ ): TaskNode;
102
+ addTask(
103
+ taskOrId: TaskDescription | string,
104
+ title?: string,
105
+ description?: string,
106
+ dependencies: string[] = [],
107
+ acceptanceCriteria?: string[],
108
+ ): TaskNode {
109
+ const spec: TaskDescription =
110
+ typeof taskOrId === "string"
111
+ ? {
112
+ id: taskOrId,
113
+ title: title ?? "",
114
+ description: description ?? "",
115
+ dependencies,
116
+ acceptanceCriteria,
117
+ }
118
+ : taskOrId;
119
+
120
+ const id = spec.id;
121
+ if (this.graph.nodes[id]) {
122
+ throw new Error(`Task ${id} already exists`);
123
+ }
124
+
125
+ const deps = spec.dependencies ?? [];
126
+
127
+ // Validate dependencies exist
128
+ for (const depId of deps) {
129
+ if (!this.graph.nodes[depId] && depId !== id) {
130
+ console.warn(
131
+ `Warning: dependency ${depId} does not exist yet (task ${id})`,
132
+ );
133
+ }
134
+ }
135
+
136
+ const now = new Date().toISOString();
137
+ const node: TaskNode = {
138
+ id,
139
+ title: spec.title,
140
+ description: spec.description,
141
+ status: spec.status ?? (deps.length === 0 ? "ready" : "pending"),
142
+ dependencies: deps,
143
+ dependents: [],
144
+ acceptanceCriteria: spec.acceptanceCriteria,
145
+ retryCount: 0,
146
+ maxRetries: 3,
147
+ createdAt: now,
148
+ updatedAt: now,
149
+ };
150
+
151
+ // Update dependents of dependencies
152
+ for (const depId of deps) {
153
+ const dependency = this.graph.nodes[depId];
154
+ if (dependency && !dependency.dependents.includes(id)) {
155
+ dependency.dependents.push(id);
156
+ }
157
+ }
158
+
159
+ this.graph.nodes[id] = node;
160
+
161
+ // A task may name a dependency before that dependency is added. Now
162
+ // that the dependency is here, the waiting task becomes its dependent.
163
+ for (const other of Object.values(this.graph.nodes)) {
164
+ if (
165
+ other.id !== id &&
166
+ other.dependencies.includes(id) &&
167
+ !node.dependents.includes(other.id)
168
+ ) {
169
+ node.dependents.push(other.id);
170
+ }
171
+ }
172
+ this.recomputeTopologicalOrder();
173
+ this.dirty = true;
174
+
175
+ return node;
176
+ }
177
+
178
+ /**
179
+ * Update task status
180
+ */
181
+ updateTaskStatus(taskId: string, status: TaskStatus): TaskNode | null {
182
+ const node = this.graph.nodes[taskId];
183
+ if (!node) return null;
184
+
185
+ node.status = status;
186
+ node.updatedAt = new Date().toISOString();
187
+
188
+ // If task is done, check if dependents can now be ready
189
+ if (status === "done") {
190
+ this.updateDependentStatuses(taskId);
191
+ }
192
+
193
+ this.recomputeTopologicalOrder();
194
+ this.dirty = true;
195
+ return node;
196
+ }
197
+
198
+ /**
199
+ * Mark a task as done and update the tasks that wait for it.
200
+ */
201
+ completeTask(taskId: string): TaskNode | null {
202
+ return this.updateTaskStatus(taskId, "done");
203
+ }
26
204
 
27
- /** Mark a task as done and update dependents */
28
- completeTask(taskId: string): void;
205
+ /**
206
+ * Update dependent tasks when a dependency is completed
207
+ */
208
+ private updateDependentStatuses(completedTaskId: string): void {
209
+ for (const dependentId of this.graph.nodes[completedTaskId]?.dependents ??
210
+ []) {
211
+ const dependent = this.graph.nodes[dependentId];
212
+ if (!dependent) continue;
29
213
 
30
- /** Get tasks ready for execution */
31
- getReadyTasks(): RuntimeTask[];
214
+ // Check if ALL dependencies are done
215
+ const allDepsDone = dependent.dependencies.every(
216
+ (depId) => this.graph.nodes[depId]?.status === "done",
217
+ );
32
218
 
33
- /** Get tasks blocked by a given task */
34
- getBlockedTasks(taskId: string): RuntimeTask[];
219
+ if (allDepsDone && dependent.status === "pending") {
220
+ dependent.status = "ready";
221
+ dependent.updatedAt = new Date().toISOString();
222
+ }
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Get all tasks ready for execution (status = "ready")
228
+ */
229
+ getReadyTasks(): TaskNode[] {
230
+ return Object.values(this.graph.nodes).filter((n) => n.status === "ready");
231
+ }
232
+
233
+ /**
234
+ * Get the blocked tasks.
235
+ *
236
+ * Without an argument this returns every task that still waits for a
237
+ * dependency. With a task id it returns the tasks that wait for that
238
+ * task: once the task is done, nothing is blocked by it any more.
239
+ */
240
+ getBlockedTasks(taskId?: string): TaskNode[] {
241
+ if (taskId === undefined) {
242
+ return Object.values(this.graph.nodes).filter(
243
+ (node) => node.status === "pending" || node.status === "blocked",
244
+ );
245
+ }
246
+ const node = this.graph.nodes[taskId];
247
+ if (!node || node.status === "done") return [];
248
+ return node.dependents
249
+ .map((id) => this.graph.nodes[id])
250
+ .filter((n): n is TaskNode => n !== undefined && n.status !== "done");
251
+ }
252
+
253
+ /**
254
+ * Get all tasks that still wait for a dependency.
255
+ */
256
+ getPendingTasks(): TaskNode[] {
257
+ return Object.values(this.graph.nodes).filter((n) => n.status === "pending");
258
+ }
259
+
260
+ /**
261
+ * Get task by ID
262
+ */
263
+ getTask(taskId: string): TaskNode | null {
264
+ return this.graph.nodes[taskId] ?? null;
265
+ }
266
+
267
+ /**
268
+ * Get all tasks
269
+ */
270
+ getAllTasks(): TaskNode[] {
271
+ return Object.values(this.graph.nodes);
272
+ }
273
+
274
+ /**
275
+ * Get topological order of tasks
276
+ */
277
+ getTopologicalOrder(): string[] {
278
+ return this.graph.topologicalOrder;
279
+ }
280
+
281
+ /**
282
+ * Check if all tasks are done
283
+ */
284
+ isComplete(): boolean {
285
+ return Object.values(this.graph.nodes).every((n) => n.status === "done");
286
+ }
35
287
 
36
- /** Get all pending tasks */
37
- getPendingTasks(): RuntimeTask[];
288
+ /**
289
+ * Check if there are any failed tasks
290
+ */
291
+ hasFailedTasks(): boolean {
292
+ return Object.values(this.graph.nodes).some((n) => n.status === "failed");
293
+ }
38
294
 
39
- /** Get all tasks */
40
- getAllTasks(): RuntimeTask[];
295
+ /**
296
+ * Get failed tasks
297
+ */
298
+ getFailedTasks(): TaskNode[] {
299
+ return Object.values(this.graph.nodes).filter((n) => n.status === "failed");
300
+ }
41
301
 
42
- /** Get current progress summary */
302
+ /**
303
+ * Increment retry count for a task
304
+ */
305
+ incrementRetry(taskId: string): TaskNode | null {
306
+ const node = this.graph.nodes[taskId];
307
+ if (!node) return null;
308
+ node.retryCount = (node.retryCount ?? 0) + 1;
309
+ node.updatedAt = new Date().toISOString();
310
+ this.dirty = true;
311
+ return node;
312
+ }
313
+
314
+ /**
315
+ * Assign agent to task
316
+ */
317
+ assignAgent(
318
+ taskId: string,
319
+ agentId: string,
320
+ worktreePath?: string,
321
+ ): TaskNode | null {
322
+ const node = this.graph.nodes[taskId];
323
+ if (!node) return null;
324
+ node.assignedAgent = agentId;
325
+ if (worktreePath) node.worktreePath = worktreePath;
326
+ node.updatedAt = new Date().toISOString();
327
+ this.dirty = true;
328
+ return node;
329
+ }
330
+
331
+ /**
332
+ * Unassign agent from task
333
+ */
334
+ unassignAgent(taskId: string): TaskNode | null {
335
+ const node = this.graph.nodes[taskId];
336
+ if (!node) return null;
337
+ node.assignedAgent = undefined;
338
+ node.worktreePath = undefined;
339
+ node.updatedAt = new Date().toISOString();
340
+ this.dirty = true;
341
+ return node;
342
+ }
343
+
344
+ /**
345
+ * Check if task can be retried
346
+ */
347
+ canRetry(taskId: string): boolean {
348
+ const node = this.graph.nodes[taskId];
349
+ if (!node) return false;
350
+ const retries = node.retryCount ?? 0;
351
+ const max = node.maxRetries ?? 3;
352
+ return retries < max;
353
+ }
354
+
355
+ /**
356
+ * Get progress summary
357
+ */
43
358
  getProgressSummary(): {
44
359
  total: number;
45
360
  done: number;
46
- running: number;
47
361
  failed: number;
48
- };
362
+ pending: number;
363
+ running: number;
364
+ } {
365
+ const tasks = Object.values(this.graph.nodes);
366
+ return {
367
+ total: tasks.length,
368
+ done: tasks.filter((t) => t.status === "done").length,
369
+ failed: tasks.filter((t) => t.status === "failed").length,
370
+ pending: tasks.filter(
371
+ (t) => t.status === "pending" || t.status === "ready",
372
+ ).length,
373
+ running: tasks.filter(
374
+ (t) =>
375
+ t.status === "running" ||
376
+ t.status === "testing" ||
377
+ t.status === "reviewing",
378
+ ).length,
379
+ };
380
+ }
49
381
 
50
- /** Get compact priority: tasks to keep in context vs prune */
382
+ /**
383
+ * Get compact priority: the task ids to keep in the context and the
384
+ * task ids that can be pruned from it.
385
+ */
51
386
  getCompactPriority(): {
52
387
  keep: string[];
53
388
  prune: string[];
54
- };
55
- }
389
+ } {
390
+ const tasks = Object.values(this.graph.nodes);
391
+ return {
392
+ keep: tasks.filter((t) => t.status === "done").map((t) => t.id),
393
+ prune: tasks.filter((t) => t.status === "pending").map((t) => t.id),
394
+ };
395
+ }
56
396
 
57
- /**
58
- * Creates a new TaskGraphManager instance.
59
- * Stub implementation — returns minimal working graph.
60
- */
61
- export function createTaskGraphManager(): TaskGraphManager {
62
- const nodes = new Map<string, TaskNode>();
63
-
64
- return {
65
- addTask(task: RuntimeTask) {
66
- if (!nodes.has(task.id)) {
67
- nodes.set(task.id, {
68
- task,
69
- dependencies: new Set(),
70
- dependents: new Set(),
71
- status: "pending",
72
- });
73
- }
74
- },
397
+ /**
398
+ * Save graph to file
399
+ */
400
+ async save(rootDir: string): Promise<void> {
401
+ const path = join(rootDir, "jobs", this.graph.jobId, "task-graph.json");
402
+ writeJsonFile(path, this.graph);
403
+ this.dirty = false;
404
+ }
75
405
 
76
- completeTask(taskId: string) {
77
- const node = nodes.get(taskId);
78
- if (!node) return;
406
+ /**
407
+ * Load graph from file
408
+ */
409
+ static async load(jobId: string, rootDir: string): Promise<TaskGraphManager> {
410
+ const path = join(rootDir, "jobs", jobId, "task-graph.json");
411
+ const data = readJsonFile(path) as TaskGraph | null;
79
412
 
80
- node.status = "done";
413
+ const manager = new TaskGraphManager({ jobId });
414
+ if (data?.nodes) {
415
+ manager.graph = data as TaskGraph;
416
+ }
81
417
 
82
- // Update dependents to ready
83
- for (const depId of node.dependents) {
84
- const depNode = nodes.get(depId);
85
- if (!depNode) continue;
418
+ return manager;
419
+ }
86
420
 
87
- // Check if all dependencies are met
88
- const allDepsMet = [...depNode.dependencies].every(
89
- (depId) => nodes.get(depId)?.status === "done",
90
- );
91
- if (allDepsMet) {
92
- depNode.status = "ready";
421
+ /**
422
+ * Check if graph has unsaved changes
423
+ */
424
+ isDirty(): boolean {
425
+ return this.dirty;
426
+ }
427
+
428
+ /**
429
+ * Get the full graph
430
+ */
431
+ getGraph(): TaskGraph {
432
+ return this.graph;
433
+ }
434
+
435
+ /**
436
+ * Compute topological order using Kahn's algorithm
437
+ */
438
+ private recomputeTopologicalOrder(): void {
439
+ const order: string[] = [];
440
+ const inDegree: Record<string, number> = {};
441
+ const nodes = this.graph.nodes;
442
+
443
+ // Initialize in-degrees. A dependency that is not in the graph yet
444
+ // does not hold a task back: the order is recomputed when it arrives.
445
+ for (const id of Object.keys(nodes)) {
446
+ inDegree[id] = nodes[id].dependencies.filter(
447
+ (depId) => nodes[depId] !== undefined,
448
+ ).length;
449
+ }
450
+
451
+ // Start with nodes that have no dependencies
452
+ const queue: string[] = [];
453
+ for (const id of Object.keys(nodes)) {
454
+ if (inDegree[id] === 0) {
455
+ queue.push(id);
456
+ }
457
+ }
458
+
459
+ while (queue.length > 0) {
460
+ const current = queue.shift()!;
461
+ order.push(current);
462
+
463
+ for (const dependent of nodes[current].dependents) {
464
+ inDegree[dependent]--;
465
+ if (inDegree[dependent] === 0) {
466
+ queue.push(dependent);
93
467
  }
94
468
  }
95
- },
96
-
97
- getReadyTasks() {
98
- return [...nodes.values()]
99
- .filter((n) => n.status === "ready")
100
- .map((n) => n.task);
101
- },
102
-
103
- getBlockedTasks(_taskId: string) {
104
- // Stub: return empty array
105
- return [];
106
- },
107
-
108
- getPendingTasks() {
109
- return [...nodes.values()]
110
- .filter((n) => n.status === "pending")
111
- .map((n) => n.task);
112
- },
113
-
114
- getAllTasks() {
115
- return [...nodes.values()].map((n) => n.task);
116
- },
117
-
118
- getProgressSummary() {
119
- const allNodes = [...nodes.values()];
120
- return {
121
- total: allNodes.length,
122
- done: allNodes.filter((n) => n.status === "done").length,
123
- running: allNodes.filter((n) => n.status === "running").length,
124
- failed: allNodes.filter((n) => n.status === "blocked").length,
125
- };
126
- },
127
-
128
- getCompactPriority() {
129
- // Stub: keep done tasks, prune pending ones
130
- const done = [...nodes.values()]
131
- .filter((n) => n.status === "done")
132
- .map((n) => n.task.id);
133
- const pending = [...nodes.values()]
134
- .filter((n) => n.status === "pending")
135
- .map((n) => n.task.id);
136
-
137
- return {
138
- keep: done, // Keep done task context (they're relevant)
139
- prune: pending, // Prune pending task messages first
140
- };
141
- },
142
- };
469
+ }
470
+
471
+ // Check for cycles (shouldn't happen with valid input)
472
+ if (order.length !== Object.keys(nodes).length) {
473
+ console.warn(
474
+ "Warning: topological sort detected a cycle in the task graph",
475
+ );
476
+ }
477
+
478
+ this.graph.topologicalOrder = order;
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Create a task graph manager. The job id is optional for the callers that
484
+ * only keep the graph in memory.
485
+ */
486
+ export function createTaskGraphManager(
487
+ options: Partial<TaskGraphOptions> = {},
488
+ ): TaskGraphManager {
489
+ return new TaskGraphManager({ jobId: options.jobId ?? "" });
143
490
  }
package/index.ts CHANGED
@@ -86,10 +86,7 @@ import {
86
86
  JobStateMachine,
87
87
  type CheckpointManager,
88
88
  } from "./harness/job-state-machine.ts";
89
- import {
90
- createTaskGraphManager,
91
- type TaskGraphManager,
92
- } from "./harness/task-graph.js";
89
+ import { TaskGraphManager } from "./harness/task-graph.js";
93
90
  import { MasterPlanner } from "./harness/master-planner.ts";
94
91
  import { RepairEngine } from "./harness/repair-engine.ts";
95
92
  import {
@@ -3351,7 +3348,7 @@ async function initMemory(pi: ExtensionAPI): Promise<void> {
3351
3348
 
3352
3349
  if (!allMemory.trim()) {
3353
3350
  logToFile("[memory]", "No memory to inject");
3354
- return;
3351
+ return undefined;
3355
3352
  }
3356
3353
 
3357
3354
  // Status on first injection
@@ -3656,6 +3653,8 @@ import { homedir } from "node:os";
3656
3653
  import { existsSync, mkdirSync, readFileSync, readdirSync, symlinkSync, appendFileSync, realpathSync, statSync, chmodSync, openSync, closeSync, renameSync } from "node:fs";
3657
3654
  import { truncateToWidth } from "@earendil-works/pi-tui";
3658
3655
  import { join, dirname } from "node:path";
3656
+ import { createRequire } from "node:module";
3657
+ const require = createRequire(import.meta.url);
3659
3658
 
3660
3659
  // --- Harness Runtime State --------------------------------------------
3661
3660
  const HARNESS_ROOT_DIR = join(homedir(), ".pi-harness-runtime");
@@ -4815,6 +4814,9 @@ Server process examples that must be detached: uvicorn, fastapi dev server, guni
4815
4814
  // Return the additional prompt to append to systemPrompt
4816
4815
  return { systemPrompt: event.systemPrompt + "\n" + additionalPrompt };
4817
4816
  }
4817
+
4818
+ // Only the first turn carries the additional prompt.
4819
+ return undefined;
4818
4820
  });
4819
4821
 
4820
4822
  // --- Auto-Todo Reminder on Build Commands ---------------------------
@@ -5813,7 +5815,7 @@ Run \`bd ready\` to see current bd issues.
5813
5815
  jobId,
5814
5816
  requirement,
5815
5817
  machine,
5816
- graph: createTaskGraphManager(),
5818
+ graph: TaskGraphManager.fromGraph(planResult.graph!),
5817
5819
  blackboard,
5818
5820
  repairEngine,
5819
5821
  createdAt: new Date().toISOString(),
@@ -5829,7 +5831,14 @@ Run \`bd ready\` to see current bd issues.
5829
5831
  "info",
5830
5832
  );
5831
5833
  } catch (e) {
5832
- ctx.ui.notify(`Error starting harness: ${e}`, "error");
5834
+ // The UI can already be gone. A failing notify must not hide
5835
+ // the original error, so the log line is the durable report.
5836
+ logToFile("[Harness]", `Error starting harness: ${e}`);
5837
+ try {
5838
+ ctx.ui.notify(`Error starting harness: ${e}`, "error");
5839
+ } catch {
5840
+ // The UI is not available; the log line above is the report.
5841
+ }
5833
5842
  }
5834
5843
  },
5835
5844
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "1.1.439",
3
+ "version": "1.1.441",
4
4
  "description": "[BETA] Codex-style /usage status + autonomous coding harness for pi. Not production ready — expect breaking changes.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -37,8 +37,11 @@
37
37
  "*.ts",
38
38
  "*.md",
39
39
  "harness/**/*.ts",
40
+ "!harness/**/*.test.ts",
40
41
  "packages/**/src/**/*.{ts,js}",
41
42
  "packages/**/dist/**/*.{js,d.ts,js.map,d.ts.map}",
43
+ "!packages/**/test/**",
44
+ "!packages/**/tests/**",
42
45
  "prompts/**/*",
43
46
  "scripts/**/*",
44
47
  "plugins/**/*",
@@ -115,8 +118,11 @@
115
118
  "@qdrant/js-client-rest": "^1.20.0",
116
119
  "chokidar": "^5.0.0",
117
120
  "deepagents": "^1.10.5",
121
+ "execa": "^10.0.1",
118
122
  "langchain": "^1.5.10",
123
+ "openai": "^4.77.0",
119
124
  "ws": "^8.22.0",
125
+ "yaml": "^2.5.0",
120
126
  "zod": "^4.6.7"
121
127
  },
122
128
  "peerDependenciesMeta": {