@pennixrv/trellis 0.7.1 → 0.7.2-beta.2

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 (321) hide show
  1. package/README.md +10 -7
  2. package/dist/cli/index.d.ts.map +1 -1
  3. package/dist/cli/index.js +6 -4
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/commands/ablate.d.ts.map +1 -1
  6. package/dist/commands/ablate.js +2 -0
  7. package/dist/commands/ablate.js.map +1 -1
  8. package/dist/commands/backup.d.ts +4 -0
  9. package/dist/commands/backup.d.ts.map +1 -0
  10. package/dist/commands/backup.js +75 -0
  11. package/dist/commands/backup.js.map +1 -0
  12. package/dist/commands/init.d.ts.map +1 -1
  13. package/dist/commands/init.js +705 -681
  14. package/dist/commands/init.js.map +1 -1
  15. package/dist/commands/mem.d.ts.map +1 -1
  16. package/dist/commands/mem.js +49 -7
  17. package/dist/commands/mem.js.map +1 -1
  18. package/dist/commands/task-progress.d.ts +1 -0
  19. package/dist/commands/task-progress.d.ts.map +1 -1
  20. package/dist/commands/task-progress.js +67 -25
  21. package/dist/commands/task-progress.js.map +1 -1
  22. package/dist/commands/teamwork/adapters/acp.d.ts +20 -0
  23. package/dist/commands/teamwork/adapters/acp.d.ts.map +1 -0
  24. package/dist/commands/teamwork/adapters/acp.js +268 -0
  25. package/dist/commands/teamwork/adapters/acp.js.map +1 -0
  26. package/dist/commands/teamwork/adapters/claude.d.ts +1 -0
  27. package/dist/commands/teamwork/adapters/claude.d.ts.map +1 -1
  28. package/dist/commands/teamwork/adapters/claude.js +5 -0
  29. package/dist/commands/teamwork/adapters/claude.js.map +1 -1
  30. package/dist/commands/teamwork/adapters/codex.d.ts +3 -2
  31. package/dist/commands/teamwork/adapters/codex.d.ts.map +1 -1
  32. package/dist/commands/teamwork/adapters/codex.js +14 -15
  33. package/dist/commands/teamwork/adapters/codex.js.map +1 -1
  34. package/dist/commands/teamwork/adapters/index.d.ts +23 -1
  35. package/dist/commands/teamwork/adapters/index.d.ts.map +1 -1
  36. package/dist/commands/teamwork/adapters/index.js +163 -24
  37. package/dist/commands/teamwork/adapters/index.js.map +1 -1
  38. package/dist/commands/teamwork/agent-loader.d.ts +2 -1
  39. package/dist/commands/teamwork/agent-loader.d.ts.map +1 -1
  40. package/dist/commands/teamwork/agent-loader.js +2 -1
  41. package/dist/commands/teamwork/agent-loader.js.map +1 -1
  42. package/dist/commands/teamwork/artifact.d.ts +42 -14
  43. package/dist/commands/teamwork/artifact.d.ts.map +1 -1
  44. package/dist/commands/teamwork/artifact.js +188 -85
  45. package/dist/commands/teamwork/artifact.js.map +1 -1
  46. package/dist/commands/teamwork/batch-reservation.d.ts +16 -0
  47. package/dist/commands/teamwork/batch-reservation.d.ts.map +1 -0
  48. package/dist/commands/teamwork/batch-reservation.js +43 -0
  49. package/dist/commands/teamwork/batch-reservation.js.map +1 -0
  50. package/dist/commands/teamwork/batch.d.ts +23 -0
  51. package/dist/commands/teamwork/batch.d.ts.map +1 -0
  52. package/dist/commands/teamwork/batch.js +415 -0
  53. package/dist/commands/teamwork/batch.js.map +1 -0
  54. package/dist/commands/teamwork/context-loader.d.ts +1 -1
  55. package/dist/commands/teamwork/context-loader.d.ts.map +1 -1
  56. package/dist/commands/teamwork/context-loader.js +19 -6
  57. package/dist/commands/teamwork/context-loader.js.map +1 -1
  58. package/dist/commands/teamwork/coordination.d.ts +88 -0
  59. package/dist/commands/teamwork/coordination.d.ts.map +1 -0
  60. package/dist/commands/teamwork/coordination.js +153 -0
  61. package/dist/commands/teamwork/coordination.js.map +1 -0
  62. package/dist/commands/teamwork/coordinator.d.ts +33 -6
  63. package/dist/commands/teamwork/coordinator.d.ts.map +1 -1
  64. package/dist/commands/teamwork/coordinator.js +948 -342
  65. package/dist/commands/teamwork/coordinator.js.map +1 -1
  66. package/dist/commands/teamwork/create.d.ts +1 -0
  67. package/dist/commands/teamwork/create.d.ts.map +1 -1
  68. package/dist/commands/teamwork/create.js +2 -1
  69. package/dist/commands/teamwork/create.js.map +1 -1
  70. package/dist/commands/teamwork/dev-parse-trace.d.ts +2 -1
  71. package/dist/commands/teamwork/dev-parse-trace.d.ts.map +1 -1
  72. package/dist/commands/teamwork/dev-parse-trace.js +2 -0
  73. package/dist/commands/teamwork/dev-parse-trace.js.map +1 -1
  74. package/dist/commands/teamwork/foreground-wait.d.ts +6 -0
  75. package/dist/commands/teamwork/foreground-wait.d.ts.map +1 -0
  76. package/dist/commands/teamwork/foreground-wait.js +65 -0
  77. package/dist/commands/teamwork/foreground-wait.js.map +1 -0
  78. package/dist/commands/teamwork/guard.d.ts +2 -2
  79. package/dist/commands/teamwork/guard.d.ts.map +1 -1
  80. package/dist/commands/teamwork/guard.js +25 -7
  81. package/dist/commands/teamwork/guard.js.map +1 -1
  82. package/dist/commands/teamwork/index.d.ts.map +1 -1
  83. package/dist/commands/teamwork/index.js +163 -10
  84. package/dist/commands/teamwork/index.js.map +1 -1
  85. package/dist/commands/teamwork/kill.d.ts +2 -0
  86. package/dist/commands/teamwork/kill.d.ts.map +1 -1
  87. package/dist/commands/teamwork/kill.js +79 -38
  88. package/dist/commands/teamwork/kill.js.map +1 -1
  89. package/dist/commands/teamwork/messages.d.ts.map +1 -1
  90. package/dist/commands/teamwork/messages.js +3 -0
  91. package/dist/commands/teamwork/messages.js.map +1 -1
  92. package/dist/commands/teamwork/plan.d.ts +22 -0
  93. package/dist/commands/teamwork/plan.d.ts.map +1 -0
  94. package/dist/commands/teamwork/plan.js +288 -0
  95. package/dist/commands/teamwork/plan.js.map +1 -0
  96. package/dist/commands/teamwork/process-identity.d.ts +3 -0
  97. package/dist/commands/teamwork/process-identity.d.ts.map +1 -0
  98. package/dist/commands/teamwork/process-identity.js +24 -0
  99. package/dist/commands/teamwork/process-identity.js.map +1 -0
  100. package/dist/commands/teamwork/profiles.d.ts +43 -6
  101. package/dist/commands/teamwork/profiles.d.ts.map +1 -1
  102. package/dist/commands/teamwork/profiles.js +138 -110
  103. package/dist/commands/teamwork/profiles.js.map +1 -1
  104. package/dist/commands/teamwork/prompt.d.ts +4 -0
  105. package/dist/commands/teamwork/prompt.d.ts.map +1 -0
  106. package/dist/commands/teamwork/prompt.js +33 -0
  107. package/dist/commands/teamwork/prompt.js.map +1 -0
  108. package/dist/commands/teamwork/result.d.ts +55 -0
  109. package/dist/commands/teamwork/result.d.ts.map +1 -0
  110. package/dist/commands/teamwork/result.js +94 -0
  111. package/dist/commands/teamwork/result.js.map +1 -0
  112. package/dist/commands/teamwork/rm.d.ts.map +1 -1
  113. package/dist/commands/teamwork/rm.js +64 -64
  114. package/dist/commands/teamwork/rm.js.map +1 -1
  115. package/dist/commands/teamwork/run.d.ts +5 -0
  116. package/dist/commands/teamwork/run.d.ts.map +1 -1
  117. package/dist/commands/teamwork/run.js +120 -24
  118. package/dist/commands/teamwork/run.js.map +1 -1
  119. package/dist/commands/teamwork/runtime.d.ts +9 -0
  120. package/dist/commands/teamwork/runtime.d.ts.map +1 -0
  121. package/dist/commands/teamwork/runtime.js +401 -0
  122. package/dist/commands/teamwork/runtime.js.map +1 -0
  123. package/dist/commands/teamwork/send.d.ts +1 -0
  124. package/dist/commands/teamwork/send.d.ts.map +1 -1
  125. package/dist/commands/teamwork/send.js +2 -1
  126. package/dist/commands/teamwork/send.js.map +1 -1
  127. package/dist/commands/teamwork/spawn.d.ts +10 -3
  128. package/dist/commands/teamwork/spawn.d.ts.map +1 -1
  129. package/dist/commands/teamwork/spawn.js +42 -27
  130. package/dist/commands/teamwork/spawn.js.map +1 -1
  131. package/dist/commands/teamwork/store/lock.js +28 -4
  132. package/dist/commands/teamwork/store/lock.js.map +1 -1
  133. package/dist/commands/teamwork/supervisor/inbox.d.ts +1 -0
  134. package/dist/commands/teamwork/supervisor/inbox.d.ts.map +1 -1
  135. package/dist/commands/teamwork/supervisor/inbox.js +28 -9
  136. package/dist/commands/teamwork/supervisor/inbox.js.map +1 -1
  137. package/dist/commands/teamwork/supervisor/stdout.d.ts.map +1 -1
  138. package/dist/commands/teamwork/supervisor/stdout.js +2 -3
  139. package/dist/commands/teamwork/supervisor/stdout.js.map +1 -1
  140. package/dist/commands/teamwork/supervisor/warning.d.ts.map +1 -1
  141. package/dist/commands/teamwork/supervisor/warning.js +2 -3
  142. package/dist/commands/teamwork/supervisor/warning.js.map +1 -1
  143. package/dist/commands/teamwork/supervisor.d.ts +5 -0
  144. package/dist/commands/teamwork/supervisor.d.ts.map +1 -1
  145. package/dist/commands/teamwork/supervisor.js +21 -12
  146. package/dist/commands/teamwork/supervisor.js.map +1 -1
  147. package/dist/commands/teamwork/teammate-adapters.d.ts +0 -5
  148. package/dist/commands/teamwork/teammate-adapters.d.ts.map +1 -1
  149. package/dist/commands/teamwork/teammate-adapters.js +9 -56
  150. package/dist/commands/teamwork/teammate-adapters.js.map +1 -1
  151. package/dist/commands/teamwork/teammate-config.d.ts +5 -1
  152. package/dist/commands/teamwork/teammate-config.d.ts.map +1 -1
  153. package/dist/commands/teamwork/teammate-config.js +62 -19
  154. package/dist/commands/teamwork/teammate-config.js.map +1 -1
  155. package/dist/commands/teamwork/teammate-launch.d.ts +15 -6
  156. package/dist/commands/teamwork/teammate-launch.d.ts.map +1 -1
  157. package/dist/commands/teamwork/teammate-launch.js +129 -22
  158. package/dist/commands/teamwork/teammate-launch.js.map +1 -1
  159. package/dist/commands/teamwork/wait.d.ts +2 -0
  160. package/dist/commands/teamwork/wait.d.ts.map +1 -1
  161. package/dist/commands/teamwork/wait.js +44 -3
  162. package/dist/commands/teamwork/wait.js.map +1 -1
  163. package/dist/commands/uninstall.d.ts.map +1 -1
  164. package/dist/commands/uninstall.js +92 -84
  165. package/dist/commands/uninstall.js.map +1 -1
  166. package/dist/commands/update.d.ts.map +1 -1
  167. package/dist/commands/update.js +635 -592
  168. package/dist/commands/update.js.map +1 -1
  169. package/dist/commands/workflow.d.ts.map +1 -1
  170. package/dist/commands/workflow.js +94 -89
  171. package/dist/commands/workflow.js.map +1 -1
  172. package/dist/configurators/shared.js +2 -2
  173. package/dist/configurators/shared.js.map +1 -1
  174. package/dist/configurators/workflow.d.ts.map +1 -1
  175. package/dist/configurators/workflow.js +14 -32
  176. package/dist/configurators/workflow.js.map +1 -1
  177. package/dist/constants/paths.d.ts +3 -10
  178. package/dist/constants/paths.d.ts.map +1 -1
  179. package/dist/constants/paths.js +4 -13
  180. package/dist/constants/paths.js.map +1 -1
  181. package/dist/migrations/manifests/0.7.1-beta.0.json +9 -0
  182. package/dist/migrations/manifests/0.7.1-beta.1.json +186 -0
  183. package/dist/migrations/manifests/0.7.1-beta.10.json +9 -0
  184. package/dist/migrations/manifests/0.7.1-beta.11.json +9 -0
  185. package/dist/migrations/manifests/0.7.1-beta.12.json +9 -0
  186. package/dist/migrations/manifests/0.7.1-beta.13.json +9 -0
  187. package/dist/migrations/manifests/0.7.1-beta.14.json +11 -0
  188. package/dist/migrations/manifests/0.7.1-beta.15.json +9 -0
  189. package/dist/migrations/manifests/0.7.1-beta.16.json +9 -0
  190. package/dist/migrations/manifests/0.7.1-beta.17.json +9 -0
  191. package/dist/migrations/manifests/0.7.1-beta.18.json +9 -0
  192. package/dist/migrations/manifests/0.7.1-beta.19.json +9 -0
  193. package/dist/migrations/manifests/0.7.1-beta.2.json +522 -0
  194. package/dist/migrations/manifests/0.7.1-beta.3.json +9 -0
  195. package/dist/migrations/manifests/0.7.1-beta.4.json +9 -0
  196. package/dist/migrations/manifests/0.7.1-beta.5.json +9 -0
  197. package/dist/migrations/manifests/0.7.1-beta.6.json +10 -0
  198. package/dist/migrations/manifests/0.7.1-beta.7.json +8 -0
  199. package/dist/migrations/manifests/0.7.1-beta.8.json +481 -0
  200. package/dist/migrations/manifests/0.7.1-beta.9.json +191 -0
  201. package/dist/migrations/manifests/0.7.2-beta.0.json +11 -0
  202. package/dist/migrations/manifests/0.7.2-beta.1.json +11 -0
  203. package/dist/migrations/manifests/0.7.2-beta.2.json +11 -0
  204. package/dist/templates/claude/hooks/statusline.py +9 -4
  205. package/dist/templates/codex/hooks/session-start.py +14 -11
  206. package/dist/templates/codex/hooks.json +10 -0
  207. package/dist/templates/common/bundled-skills/trellis-decision-space-construction-and-merging/workflow.md +2 -0
  208. package/dist/templates/common/bundled-skills/trellis-goal-exploration-and-requirements/workflow.md +2 -0
  209. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +1 -1
  210. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/add-project-local-conventions.md +1 -1
  211. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +5 -5
  212. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +3 -2
  213. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +1 -1
  214. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +1 -1
  215. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/multi-agent-teamwork.md +14 -2
  216. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +8 -2
  217. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +2 -1
  218. package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +2 -2
  219. package/dist/templates/common/bundled-skills/trellis-solution-design-and-convergence/workflow.md +8 -0
  220. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/mcp-setup.md +4 -2
  221. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-task-planning.md +2 -2
  222. package/dist/templates/common/bundled-skills/trellis-task-implementation/workflow.md +6 -0
  223. package/dist/templates/common/bundled-skills/trellis-teamwork/SKILL.md +18 -3
  224. package/dist/templates/common/bundled-skills/trellis-teamwork/references/coordination-modes.md +34 -3
  225. package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-configuration-matrix.md +37 -26
  226. package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-processes.md +128 -14
  227. package/dist/templates/common/bundled-skills/trellis-teamwork/references/teamwork-plan-construction.md +152 -20
  228. package/dist/templates/common/commands/start.md +2 -2
  229. package/dist/templates/common/skills/before-dev.md +1 -4
  230. package/dist/templates/common/skills/break-loop.md +7 -18
  231. package/dist/templates/common/skills/check.md +7 -11
  232. package/dist/templates/common/skills/{brainstorm.md → request-intake.md} +5 -3
  233. package/dist/templates/common/skills/update-spec.md +5 -7
  234. package/dist/templates/copilot/hooks/session-start.py +14 -11
  235. package/dist/templates/copilot/index.d.ts +1 -6
  236. package/dist/templates/copilot/index.d.ts.map +1 -1
  237. package/dist/templates/copilot/index.js +1 -14
  238. package/dist/templates/copilot/index.js.map +1 -1
  239. package/dist/templates/extract.js +4 -0
  240. package/dist/templates/extract.js.map +1 -1
  241. package/dist/templates/markdown/spec/backend/index.md.txt +4 -35
  242. package/dist/templates/markdown/spec/frontend/index.md.txt +4 -36
  243. package/dist/templates/omp/extensions/trellis/index.ts.txt +2 -2
  244. package/dist/templates/opencode/lib/session-utils.js +301 -209
  245. package/dist/templates/pi/extensions/trellis/index.ts.txt +17 -1
  246. package/dist/templates/shared-hooks/guard-teamwork-wait.py +58 -0
  247. package/dist/templates/shared-hooks/index.d.ts +1 -1
  248. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  249. package/dist/templates/shared-hooks/index.js +1 -0
  250. package/dist/templates/shared-hooks/index.js.map +1 -1
  251. package/dist/templates/shared-hooks/inject-workflow-state.py +8 -3
  252. package/dist/templates/shared-hooks/session-start.py +16 -12
  253. package/dist/templates/snow/SNOW.md +1 -1
  254. package/dist/templates/trellis/agents/delegated-worktree-primary-agent.md +9 -0
  255. package/dist/templates/trellis/agents/profiles/architecture.md +9 -0
  256. package/dist/templates/trellis/agents/profiles/diagnosis.md +9 -0
  257. package/dist/templates/trellis/agents/profiles/exploration.md +9 -0
  258. package/dist/templates/trellis/agents/profiles/research.md +9 -0
  259. package/dist/templates/trellis/agents/profiles/review.md +9 -0
  260. package/dist/templates/trellis/agents/profiles/verification.md +9 -0
  261. package/dist/templates/trellis/agents/teammate-profiles.json +56 -4
  262. package/dist/templates/trellis/agents/teammate.md +4 -52
  263. package/dist/templates/trellis/config.yaml +2 -5
  264. package/dist/templates/trellis/index.d.ts +4 -0
  265. package/dist/templates/trellis/index.d.ts.map +1 -1
  266. package/dist/templates/trellis/index.js +22 -4
  267. package/dist/templates/trellis/index.js.map +1 -1
  268. package/dist/templates/trellis/scripts/add_session.py +1 -1
  269. package/dist/templates/trellis/scripts/common/active_task.py +3 -47
  270. package/dist/templates/trellis/scripts/common/config.py +5 -0
  271. package/dist/templates/trellis/scripts/common/paths.py +9 -25
  272. package/dist/templates/trellis/scripts/common/safe_commit.py +8 -8
  273. package/dist/templates/trellis/scripts/common/task_context.py +11 -51
  274. package/dist/templates/trellis/scripts/common/task_continuity.py +191 -60
  275. package/dist/templates/trellis/scripts/common/task_layout.py +80 -0
  276. package/dist/templates/trellis/scripts/common/task_move.py +345 -0
  277. package/dist/templates/trellis/scripts/common/task_store.py +51 -57
  278. package/dist/templates/trellis/scripts/common/task_utils.py +23 -19
  279. package/dist/templates/trellis/scripts/common/task_workflow.py +395 -49
  280. package/dist/templates/trellis/scripts/common/tasks.py +6 -5
  281. package/dist/templates/trellis/scripts/hooks/linear_sync.py +13 -3
  282. package/dist/templates/trellis/scripts/task.py +76 -24
  283. package/dist/templates/trellis/teamwork.json +10 -0
  284. package/dist/templates/trellis/workflow.md +11 -2
  285. package/dist/utils/ablation-store.d.ts +1 -1
  286. package/dist/utils/ablation-store.d.ts.map +1 -1
  287. package/dist/utils/ablation-store.js +58 -24
  288. package/dist/utils/ablation-store.js.map +1 -1
  289. package/dist/utils/asset-backup.d.ts +138 -0
  290. package/dist/utils/asset-backup.d.ts.map +1 -0
  291. package/dist/utils/asset-backup.js +525 -0
  292. package/dist/utils/asset-backup.js.map +1 -0
  293. package/dist/utils/atomic-write.d.ts +1 -1
  294. package/dist/utils/atomic-write.d.ts.map +1 -1
  295. package/dist/utils/atomic-write.js +6 -3
  296. package/dist/utils/atomic-write.js.map +1 -1
  297. package/dist/utils/manifest-prune.d.ts +4 -1
  298. package/dist/utils/manifest-prune.d.ts.map +1 -1
  299. package/dist/utils/manifest-prune.js +17 -6
  300. package/dist/utils/manifest-prune.js.map +1 -1
  301. package/dist/utils/template-fetcher.d.ts +4 -19
  302. package/dist/utils/template-fetcher.d.ts.map +1 -1
  303. package/dist/utils/template-fetcher.js +9 -45
  304. package/dist/utils/template-fetcher.js.map +1 -1
  305. package/dist/utils/template-hash.d.ts +5 -4
  306. package/dist/utils/template-hash.d.ts.map +1 -1
  307. package/dist/utils/template-hash.js +24 -17
  308. package/dist/utils/template-hash.js.map +1 -1
  309. package/package.json +3 -2
  310. package/dist/templates/copilot/prompts/before-dev.prompt.md +0 -39
  311. package/dist/templates/copilot/prompts/brainstorm.prompt.md +0 -13
  312. package/dist/templates/copilot/prompts/break-loop.prompt.md +0 -129
  313. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +0 -170
  314. package/dist/templates/copilot/prompts/check.prompt.md +0 -110
  315. package/dist/templates/copilot/prompts/create-command.prompt.md +0 -116
  316. package/dist/templates/copilot/prompts/finish-work.prompt.md +0 -22
  317. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +0 -223
  318. package/dist/templates/copilot/prompts/onboard.prompt.md +0 -362
  319. package/dist/templates/copilot/prompts/record-session.prompt.md +0 -58
  320. package/dist/templates/copilot/prompts/start.prompt.md +0 -65
  321. package/dist/templates/copilot/prompts/update-spec.prompt.md +0 -358
@@ -1,8 +1,12 @@
1
1
  import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
+ import { parseFrozenTeammate, } from "./teammate-launch.js";
5
+ import { assertCoordinationMembers, } from "./coordination.js";
6
+ import { REASONING_EFFORTS } from "./profiles.js";
7
+ import { teammateContentSchema } from "./result.js";
4
8
  const ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
5
- const SECRET = /(-----BEGIN [A-Z ]*PRIVATE KEY-----|\b(?:sk|gh[pousr])_[A-Za-z0-9]{20,}\b|\bBearer\s+\S+)/i;
9
+ const SECRET = /(-----BEGIN [A-Z ]*PRIVATE KEY-----|\b(?:sk|gh[pousr])_[A-Za-z0-9]{20,}\b|\bBearer\s+(?!<(?:redacted|token|placeholder)>(?:\s|[.,;:!?)]|$))\S+)/i;
6
10
  function id(value, field) {
7
11
  if (typeof value !== "string" || !ID.test(value))
8
12
  throw new Error(`${field} must be a safe id`);
@@ -45,7 +49,7 @@ function relativePathList(value, field) {
45
49
  throw new Error(`${field} must not contain duplicates`);
46
50
  return result;
47
51
  }
48
- function safePath(root, candidate) {
52
+ export function safePath(root, candidate) {
49
53
  const absoluteRoot = path.resolve(root);
50
54
  const lexical = path.resolve(root, candidate);
51
55
  const relative = path.relative(absoluteRoot, lexical);
@@ -70,7 +74,7 @@ function attemptArtifactPath(taskRoot, briefPath, attemptId, fileName) {
70
74
  throw new Error("attempt id must be safe");
71
75
  return safePath(taskRoot, path.join(path.dirname(briefPath), "attempts", attemptId, fileName));
72
76
  }
73
- function writeImmutableJson(filePath, value) {
77
+ function writeImmutableJson(filePath, value, idempotent = false) {
74
78
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
75
79
  const temporary = path.join(path.dirname(filePath), `.${path.basename(filePath)}.${process.pid}.${crypto.randomBytes(6).toString("hex")}.tmp`);
76
80
  try {
@@ -88,6 +92,10 @@ function writeImmutableJson(filePath, value) {
88
92
  }
89
93
  catch (error) {
90
94
  if (error.code === "EEXIST") {
95
+ if (idempotent &&
96
+ fs.lstatSync(filePath).isFile() &&
97
+ fs.readFileSync(filePath, "utf8") === JSON.stringify(value) + "\n")
98
+ return;
91
99
  throw new Error(`artifact already exists: ${filePath}`);
92
100
  }
93
101
  throw error;
@@ -100,9 +108,7 @@ function canonicalJson(value) {
100
108
  if (Array.isArray(value))
101
109
  return `[${value.map(canonicalJson).join(",")}]`;
102
110
  if (value && typeof value === "object") {
103
- const entries = Object.entries(value)
104
- .filter(([key]) => key !== "plan_hash")
105
- .sort(([a], [b]) => a.localeCompare(b));
111
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
106
112
  return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
107
113
  }
108
114
  return JSON.stringify(value);
@@ -111,14 +117,20 @@ function withoutFields(value, fields) {
111
117
  return Object.fromEntries(Object.entries(value).filter(([field]) => !fields.includes(field)));
112
118
  }
113
119
  export function computeTeamworkPlanHash(value) {
114
- return crypto.createHash("sha256").update(canonicalJson(value)).digest("hex");
120
+ const contents = value && typeof value === "object" && !Array.isArray(value)
121
+ ? withoutFields(value, ["plan_hash"])
122
+ : value;
123
+ return crypto
124
+ .createHash("sha256")
125
+ .update(canonicalJson(contents))
126
+ .digest("hex");
115
127
  }
116
- export function validateTeamworkPlan(input, taskRoot, expectedContext) {
128
+ export function validateTeamworkPlan(input, taskRoot, expectedContext, options = {}) {
117
129
  if (!input || typeof input !== "object" || Array.isArray(input))
118
130
  throw new Error("Teamwork plan must be an object");
119
131
  const value = input;
120
- if (value.schema_version !== 1)
121
- throw new Error("Teamwork plan schema_version must be 1");
132
+ if (value.schema_version !== 2)
133
+ throw new Error("Teamwork plan schema_version must be 2; construct a new frozen plan");
122
134
  const taskId = id(value.task_id, "task_id");
123
135
  const batchId = id(value.batch_id, "batch_id");
124
136
  const sessionId = id(value.session_id, "session_id");
@@ -126,6 +138,7 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
126
138
  const taskRouteRevision = boundedText(value.task_route_revision, "task_route_revision");
127
139
  const inputRevision = boundedText(value.input_revision, "input_revision");
128
140
  const planSummary = boundedText(value.plan_summary, "plan_summary");
141
+ const coordinationDigest = digest(value.coordination_digest, "coordination_digest");
129
142
  const coordinationMode = value.coordination_mode;
130
143
  if (coordinationMode !== "general" &&
131
144
  coordinationMode !== "advisor" &&
@@ -147,13 +160,13 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
147
160
  const deadlineAt = Date.parse(deadline);
148
161
  if (Number.isNaN(deadlineAt))
149
162
  throw new Error("deadline must be an ISO date");
150
- if (deadlineAt <= Date.now())
163
+ if (!options.allowExpired && deadlineAt <= Date.now())
151
164
  throw new Error("deadline must be in the future");
152
165
  const assignmentValue = value.assignments;
153
166
  if (!Array.isArray(assignmentValue) || assignmentValue.length === 0)
154
167
  throw new Error("Teamwork plan assignments must be non-empty");
155
- if (coordinationMode === "advisor" && assignmentValue.length !== 1)
156
- throw new Error("advisor mode requires exactly one assignment");
168
+ if (coordinationMode === "advisor" && assignmentValue.length > 3)
169
+ throw new Error("advisor mode requires one to three assignments");
157
170
  if (coordinationMode === "committee" &&
158
171
  (assignmentValue.length < 2 || assignmentValue.length > 3))
159
172
  throw new Error("committee mode requires two or three assignments");
@@ -188,8 +201,10 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
188
201
  else if (coordinationMode === "committee") {
189
202
  throw new Error(`assignments[${index}] must declare an evaluation group`);
190
203
  }
191
- if (item.role_id !== "teammate")
192
- throw new Error(`assignments[${index}].role_id must be teammate`);
204
+ if (item.role_id !== undefined)
205
+ throw new Error(`assignments[${index}].role_id is retired; teammate is an internal execution type`);
206
+ const execution = parseFrozenTeammate(item.execution);
207
+ const selectionReason = boundedText(item.selection_reason, `assignments[${index}].selection_reason`);
193
208
  const provider = item.provider;
194
209
  if (provider !== "claude" &&
195
210
  provider !== "codex" &&
@@ -205,7 +220,9 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
205
220
  throw new Error(`assignments[${index}].max_retries must be non-negative`);
206
221
  const briefPath = boundedText(item.brief_path, `assignments[${index}].brief_path`);
207
222
  const scope = boundedText(item.scope, `assignments[${index}].scope`);
208
- const lens = boundedText(item.lens, `assignments[${index}].lens`);
223
+ const lens = item.lens === undefined
224
+ ? undefined
225
+ : boundedText(item.lens, `assignments[${index}].lens`);
209
226
  const summary = boundedText(item.summary, `assignments[${index}].summary`);
210
227
  const briefDigest = digest(item.brief_digest, `assignments[${index}].brief_digest`);
211
228
  const sourceDigest = digest(item.source_digest, `assignments[${index}].source_digest`);
@@ -222,22 +239,31 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
222
239
  if (path.relative(path.resolve(taskRoot), absoluteBrief) !==
223
240
  expectedRelative)
224
241
  throw new Error(`assignments[${index}].brief_path must be ${expectedRelative}`);
225
- const briefBytes = fs.readFileSync(absoluteBrief);
242
+ const prepared = options.briefContents?.get(briefPath);
243
+ if (options.briefContents && prepared === undefined)
244
+ throw new Error(`missing prepared brief: ${briefPath}`);
245
+ const briefBytes = prepared === undefined
246
+ ? fs.readFileSync(absoluteBrief)
247
+ : Buffer.from(prepared);
226
248
  if (briefBytes.byteLength > 64 * 1024)
227
249
  throw new Error(`brief for assignment '${assignmentId}' exceeds 65536 bytes`);
228
250
  const brief = JSON.parse(briefBytes.toString("utf8"));
229
251
  if (!brief || typeof brief !== "object" || Array.isArray(brief))
230
252
  throw new Error(`brief for assignment '${assignmentId}' must be an object`);
253
+ if (typeof brief.input !== "string" ||
254
+ brief.input.trim() === "" ||
255
+ brief.input.length > 32768 ||
256
+ brief.input.includes("\0"))
257
+ throw new Error("brief.input must be nonempty task text of at most 32768 characters");
231
258
  briefs.set(assignmentId, brief);
232
259
  rejectSecrets(brief, `brief for assignment '${assignmentId}'`);
233
260
  if (computeTeamworkPlanHash(brief) !== briefDigest)
234
261
  throw new Error(`brief.${assignmentId} digest does not match the Teamwork plan`);
235
262
  for (const [field, expected] of Object.entries({
236
- schema_version: 1,
263
+ schema_version: 2,
237
264
  task_id: taskId,
238
265
  batch_id: batchId,
239
266
  assignment_id: assignmentId,
240
- role_id: "teammate",
241
267
  provider,
242
268
  summary,
243
269
  scope,
@@ -247,6 +273,16 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
247
273
  if (brief[field] !== expected)
248
274
  throw new Error(`brief.${field} does not match the Teamwork plan`);
249
275
  }
276
+ if (brief.role_id !== undefined)
277
+ throw new Error("brief.role_id is retired");
278
+ if (canonicalJson(brief.execution) !== canonicalJson(item.execution))
279
+ throw new Error("brief.execution does not match the frozen plan");
280
+ if (brief.selection_reason !== selectionReason)
281
+ throw new Error("brief.selection_reason does not match the frozen plan");
282
+ if (execution.profile.provider !== provider ||
283
+ execution.profile.profile !== profile ||
284
+ execution.profile.model !== model)
285
+ throw new Error("assignment provider, profile, or model does not match frozen execution");
250
286
  const briefSourceDigest = digest(brief.source_digest, `brief.${assignmentId}.source_digest`);
251
287
  if (briefSourceDigest !== sourceDigest)
252
288
  throw new Error(`brief.${assignmentId}.source_digest does not match the Teamwork plan`);
@@ -279,6 +315,9 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
279
315
  summary,
280
316
  scope,
281
317
  lens,
318
+ execution,
319
+ selectionReason,
320
+ taskInput: brief.input,
282
321
  briefDigest,
283
322
  sourceDigest,
284
323
  ...(contextFiles ? { contextFiles } : {}),
@@ -289,6 +328,7 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
289
328
  rejectSecrets(assignment, `assignments[${index}]`);
290
329
  return assignment;
291
330
  });
331
+ assertCoordinationMembers(coordinationMode, assignments);
292
332
  if (coordinationMode === "committee") {
293
333
  const groups = new Map();
294
334
  for (const assignment of assignments) {
@@ -315,6 +355,8 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
315
355
  "lens",
316
356
  "brief_path",
317
357
  "brief_digest",
358
+ "execution",
359
+ "selection_reason",
318
360
  ];
319
361
  const briefFields = [
320
362
  "assignment_id",
@@ -322,6 +364,8 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
322
364
  "profile",
323
365
  "model",
324
366
  "lens",
367
+ "execution",
368
+ "selection_reason",
325
369
  ];
326
370
  const first = members[0];
327
371
  if (!first)
@@ -348,12 +392,32 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
348
392
  if (new Set(protectedTargets).size !== protectedTargets.length)
349
393
  throw new Error("protected_targets must not contain duplicates");
350
394
  const requestedCapacityValue = value.requested_capacity;
395
+ let retryOf;
396
+ if (value.retry_of !== undefined) {
397
+ const retry = value.retry_of;
398
+ const assignmentIds = retry?.assignment_ids;
399
+ if (!retry ||
400
+ typeof retry !== "object" ||
401
+ !Array.isArray(assignmentIds) ||
402
+ assignmentIds.length !== assignments.length ||
403
+ new Set(assignmentIds).size !== assignments.length ||
404
+ assignments.some((entry) => !assignmentIds.includes(entry.assignmentId)))
405
+ throw new Error("Retry lineage must contain the exact selected assignment set");
406
+ retryOf = {
407
+ batchId: id(retry.batch_id, "retry_of.batch_id"),
408
+ planHash: digest(retry.plan_hash, "retry_of.plan_hash"),
409
+ assignmentIds: assignmentIds.map((entry) => id(entry, "retry_of.assignment_ids")),
410
+ approvalRef: boundedText(retry.approval_ref, "retry_of.approval_ref"),
411
+ };
412
+ if (retryOf.batchId === batchId)
413
+ throw new Error("Retry must use a new batch identity");
414
+ }
351
415
  if (requestedCapacityValue !== undefined &&
352
416
  (!Number.isInteger(requestedCapacityValue) ||
353
417
  requestedCapacityValue <= 0))
354
418
  throw new Error("requested_capacity must be a positive integer");
355
419
  const plan = {
356
- schemaVersion: 1,
420
+ schemaVersion: 2,
357
421
  taskId,
358
422
  batchId,
359
423
  sessionId,
@@ -362,6 +426,11 @@ export function validateTeamworkPlan(input, taskRoot, expectedContext) {
362
426
  inputRevision,
363
427
  planSummary,
364
428
  coordinationMode,
429
+ coordinationDigest,
430
+ ...(retryOf ? { retryOf } : {}),
431
+ ...(value.coordination_snapshot
432
+ ? { coordinationSnapshot: value.coordination_snapshot }
433
+ : {}),
365
434
  planHash: boundedText(value.plan_hash, "plan_hash"),
366
435
  ...(requestedCapacityValue !== undefined
367
436
  ? { requestedCapacity: requestedCapacityValue }
@@ -380,8 +449,31 @@ export function validateTeammateReport(input, identity, expectedSourceDigest) {
380
449
  if (!input || typeof input !== "object" || Array.isArray(input))
381
450
  throw new Error("teammate report must be an object");
382
451
  const value = input;
383
- if (value.schema_version !== 1)
384
- throw new Error("teammate report schema_version must be 1");
452
+ if (value.schema_version !== 1 && value.schema_version !== 2)
453
+ throw new Error("teammate report schema_version must be 1 or 2");
454
+ if (value.schema_version === 2) {
455
+ const allowed = new Set([
456
+ ...Object.keys(teammateContentSchema.shape),
457
+ "task_id",
458
+ "batch_id",
459
+ "assignment_id",
460
+ "attempt_id",
461
+ "teammate_id",
462
+ "plan_hash",
463
+ "phase_id",
464
+ "task_route_revision",
465
+ "input_revision",
466
+ "source_digest",
467
+ ]);
468
+ if (Object.keys(value).some((key) => !allowed.has(key)))
469
+ throw new Error("teammate report contains unknown fields");
470
+ }
471
+ const content = value.schema_version === 2
472
+ ? teammateContentSchema.parse(Object.fromEntries(Object.keys(teammateContentSchema.shape).map((key) => [
473
+ key,
474
+ value[key],
475
+ ])))
476
+ : undefined;
385
477
  for (const key of [
386
478
  "task_id",
387
479
  "batch_id",
@@ -434,11 +526,11 @@ export function validateTeammateReport(input, identity, expectedSourceDigest) {
434
526
  summary: boundedText(item.summary, `report.evidence[${index}].summary`),
435
527
  };
436
528
  });
437
- if (status !== "complete" || evidence.length === 0) {
438
- throw new Error(`report status '${status}' cannot be accepted as completed work`);
439
- }
529
+ if (evidence.length === 0)
530
+ throw new Error("report.evidence must include at least one item");
440
531
  const report = {
441
- schemaVersion: 1,
532
+ schemaVersion: value.schema_version,
533
+ ...(content ? { content } : {}),
442
534
  taskId: identity.taskId,
443
535
  batchId: identity.batchId,
444
536
  assignmentId: identity.assignmentId,
@@ -504,8 +596,8 @@ export function validateTeammateClaim(input, identity, expectedPlanHash, expecte
504
596
  if (!input || typeof input !== "object" || Array.isArray(input))
505
597
  throw new Error("teammate claim must be an object");
506
598
  const value = input;
507
- if (value.schema_version !== 1)
508
- throw new Error("teammate claim schema_version must be 1");
599
+ if (value.schema_version !== 2)
600
+ throw new Error("teammate claim schema_version must be 2");
509
601
  for (const key of [
510
602
  "task_id",
511
603
  "batch_id",
@@ -541,7 +633,7 @@ export function validateTeammateClaim(input, identity, expectedPlanHash, expecte
541
633
  if (!Number.isInteger(value.slot) || value.slot < 0)
542
634
  throw new Error("claim.slot must be non-negative");
543
635
  const snapshotKeys = [
544
- "role_id",
636
+ "configuration",
545
637
  "provider",
546
638
  "profile",
547
639
  "model",
@@ -555,8 +647,8 @@ export function validateTeammateClaim(input, identity, expectedPlanHash, expecte
555
647
  const hasSnapshot = snapshotKeys.some((key) => value[key] !== undefined);
556
648
  let execution;
557
649
  if (hasSnapshot) {
558
- if (value.role_id !== "teammate")
559
- throw new Error("claim.role_id must be teammate");
650
+ if (value.role_id !== undefined)
651
+ throw new Error("claim.role_id is retired");
560
652
  const provider = value.provider;
561
653
  if (provider !== "claude" &&
562
654
  provider !== "codex" &&
@@ -574,9 +666,7 @@ export function validateTeammateClaim(input, identity, expectedPlanHash, expecte
574
666
  throw new Error("claim.model must be bounded single-line text");
575
667
  const reasoningEffort = value.reasoning_effort;
576
668
  if (reasoningEffort !== undefined &&
577
- reasoningEffort !== "medium" &&
578
- reasoningEffort !== "high" &&
579
- reasoningEffort !== "xhigh") {
669
+ !REASONING_EFFORTS.includes(reasoningEffort)) {
580
670
  throw new Error("claim.reasoning_effort is invalid");
581
671
  }
582
672
  if (!value.options ||
@@ -605,10 +695,13 @@ export function validateTeammateClaim(input, identity, expectedPlanHash, expecte
605
695
  }
606
696
  execution = {
607
697
  roleId: "teammate",
698
+ configuration: id(value.configuration, "claim.configuration"),
608
699
  provider,
609
700
  ...(profile ? { profile } : {}),
610
701
  ...(model ? { model } : {}),
611
- ...(reasoningEffort ? { reasoningEffort } : {}),
702
+ ...(reasoningEffort
703
+ ? { reasoningEffort: reasoningEffort }
704
+ : {}),
612
705
  options,
613
706
  ...(value.profile_digest === undefined
614
707
  ? {}
@@ -621,7 +714,7 @@ export function validateTeammateClaim(input, identity, expectedPlanHash, expecte
621
714
  };
622
715
  }
623
716
  const claim = {
624
- schemaVersion: 1,
717
+ schemaVersion: 2,
625
718
  ...identity,
626
719
  planHash,
627
720
  ...(briefDigest ? { briefDigest } : {}),
@@ -680,7 +773,7 @@ export function validateTeammateDisposition(input, identity, expectedSourceDiges
680
773
  export function writeTeammateClaim(input) {
681
774
  const execution = input.launch
682
775
  ? {
683
- role_id: input.launch.roleId,
776
+ configuration: input.launch.configuration,
684
777
  provider: input.launch.provider,
685
778
  ...(input.launch.profile ? { profile: input.launch.profile } : {}),
686
779
  ...(input.launch.model ? { model: input.launch.model } : {}),
@@ -697,7 +790,7 @@ export function writeTeammateClaim(input) {
697
790
  }
698
791
  : undefined;
699
792
  const claim = validateTeammateClaim({
700
- schema_version: 1,
793
+ schema_version: 2,
701
794
  task_id: input.identity.taskId,
702
795
  batch_id: input.identity.batchId,
703
796
  assignment_id: input.identity.assignmentId,
@@ -724,7 +817,7 @@ export function writeTeammateClaim(input) {
724
817
  status: claim.status,
725
818
  ...(claim.execution
726
819
  ? {
727
- role_id: claim.execution.roleId,
820
+ configuration: claim.execution.configuration,
728
821
  provider: claim.execution.provider,
729
822
  ...(claim.execution.profile
730
823
  ? { profile: claim.execution.profile }
@@ -789,8 +882,13 @@ export function appendTeammateWorklog(input) {
789
882
  }
790
883
  }
791
884
  export function writeTeammateReport(input) {
885
+ if (input.content &&
886
+ (input.content.status !== input.status ||
887
+ JSON.stringify(input.content.evidence) !== JSON.stringify(input.evidence)))
888
+ throw new Error("report content status/evidence must match the submitted report");
792
889
  const report = validateTeammateReport({
793
- schema_version: 1,
890
+ ...input.content,
891
+ schema_version: input.content ? 2 : 1,
794
892
  task_id: input.identity.taskId,
795
893
  batch_id: input.identity.batchId,
796
894
  assignment_id: input.identity.assignmentId,
@@ -805,6 +903,7 @@ export function writeTeammateReport(input) {
805
903
  evidence: input.evidence,
806
904
  }, input.identity, input.sourceDigest);
807
905
  writeImmutableJson(attemptArtifactPath(input.taskRoot, input.briefPath, input.identity.attemptId, "report.json"), {
906
+ ...report.content,
808
907
  schema_version: report.schemaVersion,
809
908
  task_id: report.taskId,
810
909
  batch_id: report.batchId,
@@ -852,57 +951,61 @@ export function writeTeammateDisposition(input) {
852
951
  status: disposition.status,
853
952
  source_digest: disposition.sourceDigest,
854
953
  ...(disposition.reason ? { reason: disposition.reason } : {}),
855
- });
954
+ ...(input.review ? { review: input.review } : {}),
955
+ }, input.review !== undefined);
956
+ }
957
+ export class TeammateReportReadError extends Error {
958
+ kind;
959
+ constructor(kind, message) {
960
+ super(message);
961
+ this.kind = kind;
962
+ this.name = "TeammateReportReadError";
963
+ }
964
+ }
965
+ function isMissingFile(error) {
966
+ return (error !== null &&
967
+ typeof error === "object" &&
968
+ "code" in error &&
969
+ error.code === "ENOENT");
856
970
  }
857
971
  export function readTeammateReport(input) {
858
972
  if (!ID.test(input.attemptId))
859
973
  throw new Error("attempt id must be safe");
860
- const reportPath = safePath(input.taskRoot, path.join(path.dirname(input.briefPath), "attempts", input.attemptId, "report.json"));
861
- const stat = fs.lstatSync(reportPath);
974
+ let reportPath;
975
+ try {
976
+ reportPath = safePath(input.taskRoot, path.join(path.dirname(input.briefPath), "attempts", input.attemptId, "report.json"));
977
+ }
978
+ catch {
979
+ throw new TeammateReportReadError("storage", "teammate report path is unsafe");
980
+ }
981
+ let stat;
982
+ try {
983
+ stat = fs.lstatSync(reportPath);
984
+ }
985
+ catch (error) {
986
+ if (isMissingFile(error))
987
+ throw new TeammateReportReadError("missing", "teammate report is missing");
988
+ throw new TeammateReportReadError("storage", "could not inspect teammate report");
989
+ }
862
990
  if (!stat.isFile() || stat.size > 128 * 1024)
863
- throw new Error("teammate report must be a regular file under 131072 bytes");
864
- const raw = fs.readFileSync(reportPath, "utf8");
865
- const report = JSON.parse(raw);
991
+ throw new TeammateReportReadError("storage", "teammate report must be a regular file under 131072 bytes");
992
+ let raw;
993
+ try {
994
+ raw = fs.readFileSync(reportPath, "utf8");
995
+ }
996
+ catch (error) {
997
+ if (isMissingFile(error))
998
+ throw new TeammateReportReadError("missing", "teammate report is missing");
999
+ throw new TeammateReportReadError("storage", "could not read teammate report");
1000
+ }
1001
+ let report;
1002
+ try {
1003
+ report = JSON.parse(raw);
1004
+ }
1005
+ catch {
1006
+ throw new TeammateReportReadError("incomplete", "teammate report is not complete JSON");
1007
+ }
866
1008
  rejectSecrets(report, "teammate report");
867
1009
  return validateTeammateReport(report, { ...input.identity, attemptId: input.attemptId }, input.sourceDigest);
868
1010
  }
869
- export function cleanupSettledTeamworkArtifacts(input) {
870
- const failures = [];
871
- for (const assignment of input.assignments) {
872
- try {
873
- const assignmentDir = safePath(input.taskRoot, path.dirname(assignment.briefPath));
874
- const queueFile = safePath(input.taskRoot, path.join(assignmentDir, "queue.json"));
875
- if (fs.existsSync(queueFile))
876
- fs.unlinkSync(queueFile);
877
- const attemptsDir = safePath(input.taskRoot, path.join(assignmentDir, "attempts"));
878
- if (!fs.existsSync(attemptsDir))
879
- continue;
880
- for (const attemptId of fs.readdirSync(attemptsDir)) {
881
- if (!ID.test(attemptId))
882
- continue;
883
- const attemptDir = safePath(input.taskRoot, path.join(attemptsDir, attemptId));
884
- const keepReport = input.acceptedAttempts.get(assignment.assignmentId) === attemptId;
885
- const transientFiles = [
886
- "claim.json",
887
- "disposition.json",
888
- "worklog.md",
889
- ...(keepReport ? [] : ["report.json"]),
890
- ];
891
- for (const fileName of transientFiles) {
892
- const filePath = safePath(input.taskRoot, path.join(attemptDir, fileName));
893
- if (fs.existsSync(filePath))
894
- fs.unlinkSync(filePath);
895
- }
896
- if (fs.readdirSync(attemptDir).length === 0)
897
- fs.rmdirSync(attemptDir);
898
- }
899
- if (fs.readdirSync(attemptsDir).length === 0)
900
- fs.rmdirSync(attemptsDir);
901
- }
902
- catch (error) {
903
- failures.push(`${assignment.assignmentId}: ${error instanceof Error ? error.message : String(error)}`);
904
- }
905
- }
906
- return failures;
907
- }
908
1011
  //# sourceMappingURL=artifact.js.map