dsh-plugin-t-expert 0.1.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 (619) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +215 -0
  3. package/THIRD-PARTY-NOTICES +33 -0
  4. package/cordis.patch.yml +7 -0
  5. package/data/experts/academic/academic-anthropologist.md +125 -0
  6. package/data/experts/academic/academic-geographer.md +127 -0
  7. package/data/experts/academic/academic-historian.md +123 -0
  8. package/data/experts/academic/academic-narratologist.md +118 -0
  9. package/data/experts/academic/academic-psychologist.md +118 -0
  10. package/data/experts/academic/academic-statistician.md +144 -0
  11. package/data/experts/design/design-brand-guardian.md +322 -0
  12. package/data/experts/design/design-image-prompt-engineer.md +236 -0
  13. package/data/experts/design/design-inclusive-visuals-specialist.md +71 -0
  14. package/data/experts/design/design-persona-walkthrough.md +272 -0
  15. package/data/experts/design/design-ui-designer.md +383 -0
  16. package/data/experts/design/design-ui-finish-gate-reviewer.md +217 -0
  17. package/data/experts/design/design-ux-architect.md +469 -0
  18. package/data/experts/design/design-ux-researcher.md +329 -0
  19. package/data/experts/design/design-visual-storyteller.md +149 -0
  20. package/data/experts/design/design-whimsy-injector.md +438 -0
  21. package/data/experts/engineering/engineering-ai-data-remediation-engineer.md +211 -0
  22. package/data/experts/engineering/engineering-ai-engineer.md +146 -0
  23. package/data/experts/engineering/engineering-api-platform-engineer.md +162 -0
  24. package/data/experts/engineering/engineering-ats-validator-architect.md +383 -0
  25. package/data/experts/engineering/engineering-autonomous-optimization-architect.md +107 -0
  26. package/data/experts/engineering/engineering-backend-architect.md +236 -0
  27. package/data/experts/engineering/engineering-china-network-engineer.md +252 -0
  28. package/data/experts/engineering/engineering-cms-developer.md +536 -0
  29. package/data/experts/engineering/engineering-code-reviewer.md +76 -0
  30. package/data/experts/engineering/engineering-codebase-onboarding-engineer.md +173 -0
  31. package/data/experts/engineering/engineering-data-engineer.md +306 -0
  32. package/data/experts/engineering/engineering-data-visualization-engineer.md +151 -0
  33. package/data/experts/engineering/engineering-database-optimizer.md +176 -0
  34. package/data/experts/engineering/engineering-database-reliability-engineer.md +162 -0
  35. package/data/experts/engineering/engineering-desktop-app-engineer.md +204 -0
  36. package/data/experts/engineering/engineering-developer-tooling-engineer.md +153 -0
  37. package/data/experts/engineering/engineering-devops-automator.md +376 -0
  38. package/data/experts/engineering/engineering-drupal-performance.md +347 -0
  39. package/data/experts/engineering/engineering-drupal-shopping-cart.md +360 -0
  40. package/data/experts/engineering/engineering-email-intelligence-engineer.md +353 -0
  41. package/data/experts/engineering/engineering-embedded-firmware-engineer.md +173 -0
  42. package/data/experts/engineering/engineering-feishu-integration-developer.md +598 -0
  43. package/data/experts/engineering/engineering-filament-optimization-specialist.md +283 -0
  44. package/data/experts/engineering/engineering-finops-engineer.md +153 -0
  45. package/data/experts/engineering/engineering-frontend-developer.md +225 -0
  46. package/data/experts/engineering/engineering-gaussdb-expert.md +334 -0
  47. package/data/experts/engineering/engineering-git-workflow-master.md +84 -0
  48. package/data/experts/engineering/engineering-i18n-engineer.md +184 -0
  49. package/data/experts/engineering/engineering-identity-access-engineer.md +196 -0
  50. package/data/experts/engineering/engineering-incident-response-commander.md +444 -0
  51. package/data/experts/engineering/engineering-iot-fleet-engineer.md +148 -0
  52. package/data/experts/engineering/engineering-it-service-manager.md +561 -0
  53. package/data/experts/engineering/engineering-knowledge-graph-engineer.md +368 -0
  54. package/data/experts/engineering/engineering-llm-post-training-engineer.md +166 -0
  55. package/data/experts/engineering/engineering-minimal-change-engineer.md +207 -0
  56. package/data/experts/engineering/engineering-mobile-app-builder.md +493 -0
  57. package/data/experts/engineering/engineering-mobile-release-engineer.md +163 -0
  58. package/data/experts/engineering/engineering-multi-agent-systems-architect.md +600 -0
  59. package/data/experts/engineering/engineering-network-engineer.md +239 -0
  60. package/data/experts/engineering/engineering-orgscript-engineer.md +113 -0
  61. package/data/experts/engineering/engineering-payments-billing-engineer.md +194 -0
  62. package/data/experts/engineering/engineering-pdf-engine-architect.md +666 -0
  63. package/data/experts/engineering/engineering-platform-engineer.md +270 -0
  64. package/data/experts/engineering/engineering-privacy-engineer.md +152 -0
  65. package/data/experts/engineering/engineering-prompt-engineer.md +202 -0
  66. package/data/experts/engineering/engineering-rag-pipeline-engineer.md +437 -0
  67. package/data/experts/engineering/engineering-rapid-prototyper.md +462 -0
  68. package/data/experts/engineering/engineering-realtime-collaboration-engineer.md +187 -0
  69. package/data/experts/engineering/engineering-rust-refactoring-specialist.md +313 -0
  70. package/data/experts/engineering/engineering-search-relevance-engineer.md +237 -0
  71. package/data/experts/engineering/engineering-section-508-specialist.md +339 -0
  72. package/data/experts/engineering/engineering-senior-developer.md +176 -0
  73. package/data/experts/engineering/engineering-software-architect.md +112 -0
  74. package/data/experts/engineering/engineering-solidity-smart-contract-engineer.md +522 -0
  75. package/data/experts/engineering/engineering-sre.md +90 -0
  76. package/data/experts/engineering/engineering-technical-writer.md +393 -0
  77. package/data/experts/engineering/engineering-universal-document-compiler.md +344 -0
  78. package/data/experts/engineering/engineering-uswds-developer.md +340 -0
  79. package/data/experts/engineering/engineering-video-streaming-engineer.md +150 -0
  80. package/data/experts/engineering/engineering-voice-ai-integration-engineer.md +561 -0
  81. package/data/experts/engineering/engineering-webassembly-engineer.md +156 -0
  82. package/data/experts/engineering/engineering-wechat-mini-program-developer.md +350 -0
  83. package/data/experts/engineering/engineering-wordpress-performance.md +346 -0
  84. package/data/experts/engineering/engineering-wordpress-shopping-cart.md +346 -0
  85. package/data/experts/finance/finance-bookkeeper-controller.md +260 -0
  86. package/data/experts/finance/finance-financial-analyst.md +234 -0
  87. package/data/experts/finance/finance-fpa-analyst.md +263 -0
  88. package/data/experts/finance/finance-investment-researcher.md +272 -0
  89. package/data/experts/finance/finance-tax-strategist.md +239 -0
  90. package/data/experts/game-development/blender/blender-addon-engineer.md +234 -0
  91. package/data/experts/game-development/economy-designer.md +156 -0
  92. package/data/experts/game-development/game-audio-engineer.md +264 -0
  93. package/data/experts/game-development/game-designer.md +167 -0
  94. package/data/experts/game-development/godot/godot-gameplay-scripter.md +334 -0
  95. package/data/experts/game-development/godot/godot-multiplayer-engineer.md +297 -0
  96. package/data/experts/game-development/godot/godot-shader-developer.md +266 -0
  97. package/data/experts/game-development/level-designer.md +208 -0
  98. package/data/experts/game-development/narrative-designer.md +243 -0
  99. package/data/experts/game-development/roblox-studio/roblox-avatar-creator.md +297 -0
  100. package/data/experts/game-development/roblox-studio/roblox-experience-designer.md +305 -0
  101. package/data/experts/game-development/roblox-studio/roblox-systems-scripter.md +325 -0
  102. package/data/experts/game-development/technical-artist.md +229 -0
  103. package/data/experts/game-development/unity/unity-architect.md +271 -0
  104. package/data/experts/game-development/unity/unity-editor-tool-developer.md +310 -0
  105. package/data/experts/game-development/unity/unity-multiplayer-engineer.md +321 -0
  106. package/data/experts/game-development/unity/unity-shader-graph-artist.md +269 -0
  107. package/data/experts/game-development/unreal-engine/unreal-multiplayer-architect.md +313 -0
  108. package/data/experts/game-development/unreal-engine/unreal-systems-engineer.md +310 -0
  109. package/data/experts/game-development/unreal-engine/unreal-technical-artist.md +256 -0
  110. package/data/experts/game-development/unreal-engine/unreal-world-builder.md +273 -0
  111. package/data/experts/gis/gis-3d-scene-developer.md +111 -0
  112. package/data/experts/gis/gis-analyst.md +91 -0
  113. package/data/experts/gis/gis-bim-specialist.md +108 -0
  114. package/data/experts/gis/gis-cartography-designer.md +150 -0
  115. package/data/experts/gis/gis-drone-reality-mapping.md +120 -0
  116. package/data/experts/gis/gis-geoai-ml-engineer.md +105 -0
  117. package/data/experts/gis/gis-geoprocessing-specialist.md +97 -0
  118. package/data/experts/gis/gis-qa-engineer.md +133 -0
  119. package/data/experts/gis/gis-solution-engineer.md +101 -0
  120. package/data/experts/gis/gis-spatial-data-engineer.md +97 -0
  121. package/data/experts/gis/gis-spatial-data-scientist.md +111 -0
  122. package/data/experts/gis/gis-technical-consultant.md +86 -0
  123. package/data/experts/gis/gis-web-gis-developer.md +108 -0
  124. package/data/experts/healthcare/healthcare-clinical-evidence-agent.md +231 -0
  125. package/data/experts/healthcare/healthcare-innovation-strategist.md +433 -0
  126. package/data/experts/healthcare/healthcare-sovereign-health-systems-agent.md +312 -0
  127. package/data/experts/marketing/marketing-aeo-foundations.md +264 -0
  128. package/data/experts/marketing/marketing-agentic-search-optimizer.md +313 -0
  129. package/data/experts/marketing/marketing-ai-citation-strategist.md +172 -0
  130. package/data/experts/marketing/marketing-app-store-optimizer.md +321 -0
  131. package/data/experts/marketing/marketing-baidu-seo-specialist.md +226 -0
  132. package/data/experts/marketing/marketing-bilibili-content-strategist.md +199 -0
  133. package/data/experts/marketing/marketing-book-co-author.md +110 -0
  134. package/data/experts/marketing/marketing-carousel-growth-engine.md +199 -0
  135. package/data/experts/marketing/marketing-china-ecommerce-operator.md +283 -0
  136. package/data/experts/marketing/marketing-china-market-localization-strategist.md +283 -0
  137. package/data/experts/marketing/marketing-content-creator.md +54 -0
  138. package/data/experts/marketing/marketing-cross-border-ecommerce.md +259 -0
  139. package/data/experts/marketing/marketing-douyin-strategist.md +149 -0
  140. package/data/experts/marketing/marketing-email-strategist.md +249 -0
  141. package/data/experts/marketing/marketing-global-podcast-strategist.md +206 -0
  142. package/data/experts/marketing/marketing-growth-hacker.md +54 -0
  143. package/data/experts/marketing/marketing-instagram-curator.md +113 -0
  144. package/data/experts/marketing/marketing-kuaishou-strategist.md +223 -0
  145. package/data/experts/marketing/marketing-linkedin-content-creator.md +214 -0
  146. package/data/experts/marketing/marketing-livestream-commerce-coach.md +305 -0
  147. package/data/experts/marketing/marketing-multi-platform-publisher.md +217 -0
  148. package/data/experts/marketing/marketing-podcast-strategist.md +277 -0
  149. package/data/experts/marketing/marketing-pr-communications-manager.md +473 -0
  150. package/data/experts/marketing/marketing-private-domain-operator.md +308 -0
  151. package/data/experts/marketing/marketing-reddit-community-builder.md +123 -0
  152. package/data/experts/marketing/marketing-seo-specialist.md +370 -0
  153. package/data/experts/marketing/marketing-short-video-editing-coach.md +412 -0
  154. package/data/experts/marketing/marketing-social-media-strategist.md +125 -0
  155. package/data/experts/marketing/marketing-tiktok-strategist.md +125 -0
  156. package/data/experts/marketing/marketing-twitter-engager.md +126 -0
  157. package/data/experts/marketing/marketing-video-optimization-specialist.md +119 -0
  158. package/data/experts/marketing/marketing-wechat-official-account.md +145 -0
  159. package/data/experts/marketing/marketing-weibo-strategist.md +240 -0
  160. package/data/experts/marketing/marketing-x-twitter-intelligence-analyst.md +161 -0
  161. package/data/experts/marketing/marketing-xiaohongshu-specialist.md +138 -0
  162. package/data/experts/marketing/marketing-zhihu-strategist.md +162 -0
  163. package/data/experts/paid-media/paid-media-auditor.md +71 -0
  164. package/data/experts/paid-media/paid-media-creative-strategist.md +71 -0
  165. package/data/experts/paid-media/paid-media-paid-social-strategist.md +71 -0
  166. package/data/experts/paid-media/paid-media-ppc-strategist.md +71 -0
  167. package/data/experts/paid-media/paid-media-programmatic-buyer.md +71 -0
  168. package/data/experts/paid-media/paid-media-search-query-analyst.md +71 -0
  169. package/data/experts/paid-media/paid-media-tracking-specialist.md +71 -0
  170. package/data/experts/product/product-behavioral-nudge-engine.md +80 -0
  171. package/data/experts/product/product-feedback-synthesizer.md +119 -0
  172. package/data/experts/product/product-manager.md +469 -0
  173. package/data/experts/product/product-sprint-prioritizer.md +154 -0
  174. package/data/experts/product/product-trend-researcher.md +159 -0
  175. package/data/experts/project-management/project-management-experiment-tracker.md +198 -0
  176. package/data/experts/project-management/project-management-jira-workflow-steward.md +230 -0
  177. package/data/experts/project-management/project-management-meeting-notes-specialist.md +95 -0
  178. package/data/experts/project-management/project-management-project-shepherd.md +194 -0
  179. package/data/experts/project-management/project-management-studio-operations.md +200 -0
  180. package/data/experts/project-management/project-management-studio-producer.md +203 -0
  181. package/data/experts/project-management/project-manager-senior.md +135 -0
  182. package/data/experts/research/research-synthesist.md +136 -0
  183. package/data/experts/sales/sales-account-strategist.md +227 -0
  184. package/data/experts/sales/sales-coach.md +271 -0
  185. package/data/experts/sales/sales-deal-strategist.md +180 -0
  186. package/data/experts/sales/sales-discovery-coach.md +225 -0
  187. package/data/experts/sales/sales-engineer.md +182 -0
  188. package/data/experts/sales/sales-offer-lead-gen-strategist.md +257 -0
  189. package/data/experts/sales/sales-outbound-strategist.md +201 -0
  190. package/data/experts/sales/sales-pipeline-analyst.md +267 -0
  191. package/data/experts/sales/sales-proposal-strategist.md +217 -0
  192. package/data/experts/security/security-ai-generated-code-auditor.md +207 -0
  193. package/data/experts/security/security-appsec-engineer.md +491 -0
  194. package/data/experts/security/security-architect.md +304 -0
  195. package/data/experts/security/security-blockchain-security-auditor.md +463 -0
  196. package/data/experts/security/security-cloud-security-architect.md +523 -0
  197. package/data/experts/security/security-compliance-auditor.md +158 -0
  198. package/data/experts/security/security-incident-responder.md +437 -0
  199. package/data/experts/security/security-penetration-tester.md +399 -0
  200. package/data/experts/security/security-secrets-credential-engineer.md +176 -0
  201. package/data/experts/security/security-senior-secops.md +750 -0
  202. package/data/experts/security/security-threat-detection-engineer.md +534 -0
  203. package/data/experts/security/security-threat-intelligence-analyst.md +644 -0
  204. package/data/experts/spatial-computing/macos-spatial-metal-engineer.md +337 -0
  205. package/data/experts/spatial-computing/terminal-integration-specialist.md +70 -0
  206. package/data/experts/spatial-computing/visionos-spatial-engineer.md +54 -0
  207. package/data/experts/spatial-computing/xr-cockpit-interaction-specialist.md +32 -0
  208. package/data/experts/spatial-computing/xr-immersive-developer.md +32 -0
  209. package/data/experts/spatial-computing/xr-interface-architect.md +32 -0
  210. package/data/experts/specialized/accounts-payable-agent.md +185 -0
  211. package/data/experts/specialized/agentic-identity-trust.md +387 -0
  212. package/data/experts/specialized/agents-orchestrator.md +367 -0
  213. package/data/experts/specialized/automation-governance-architect.md +216 -0
  214. package/data/experts/specialized/business-strategist.md +488 -0
  215. package/data/experts/specialized/change-management-consultant.md +497 -0
  216. package/data/experts/specialized/chief-financial-officer.md +388 -0
  217. package/data/experts/specialized/corporate-training-designer.md +192 -0
  218. package/data/experts/specialized/customer-service.md +398 -0
  219. package/data/experts/specialized/customer-success-manager.md +460 -0
  220. package/data/experts/specialized/data-consolidation-agent.md +60 -0
  221. package/data/experts/specialized/data-privacy-officer.md +412 -0
  222. package/data/experts/specialized/esg-sustainability-officer.md +396 -0
  223. package/data/experts/specialized/government-digital-presales-consultant.md +363 -0
  224. package/data/experts/specialized/grant-writer.md +511 -0
  225. package/data/experts/specialized/healthcare-aging-parent-care-companion.md +414 -0
  226. package/data/experts/specialized/healthcare-customer-service.md +389 -0
  227. package/data/experts/specialized/healthcare-marketing-compliance.md +395 -0
  228. package/data/experts/specialized/hospitality-guest-services.md +603 -0
  229. package/data/experts/specialized/hr-onboarding.md +451 -0
  230. package/data/experts/specialized/identity-graph-operator.md +260 -0
  231. package/data/experts/specialized/language-translator.md +264 -0
  232. package/data/experts/specialized/legal-billing-time-tracking.md +569 -0
  233. package/data/experts/specialized/legal-client-intake.md +492 -0
  234. package/data/experts/specialized/legal-document-review.md +454 -0
  235. package/data/experts/specialized/loan-officer-assistant.md +555 -0
  236. package/data/experts/specialized/lsp-index-engineer.md +314 -0
  237. package/data/experts/specialized/ma-integration-manager.md +427 -0
  238. package/data/experts/specialized/medical-billing-coding-specialist.md +491 -0
  239. package/data/experts/specialized/operations-manager.md +399 -0
  240. package/data/experts/specialized/organizational-psychologist.md +391 -0
  241. package/data/experts/specialized/personal-growth-mentor.md +159 -0
  242. package/data/experts/specialized/real-estate-buyer-seller.md +596 -0
  243. package/data/experts/specialized/recruitment-specialist.md +509 -0
  244. package/data/experts/specialized/report-distribution-agent.md +65 -0
  245. package/data/experts/specialized/resume-tailor.md +230 -0
  246. package/data/experts/specialized/retail-customer-returns.md +566 -0
  247. package/data/experts/specialized/sales-data-extraction-agent.md +67 -0
  248. package/data/experts/specialized/sales-outreach.md +425 -0
  249. package/data/experts/specialized/specialized-chief-of-staff.md +279 -0
  250. package/data/experts/specialized/specialized-civil-engineer.md +356 -0
  251. package/data/experts/specialized/specialized-codebase-archaeologist.md +341 -0
  252. package/data/experts/specialized/specialized-cultural-intelligence-strategist.md +88 -0
  253. package/data/experts/specialized/specialized-developer-advocate.md +317 -0
  254. package/data/experts/specialized/specialized-document-generator.md +55 -0
  255. package/data/experts/specialized/specialized-fedramp-rmf-compliance.md +378 -0
  256. package/data/experts/specialized/specialized-focus-music-architect.md +172 -0
  257. package/data/experts/specialized/specialized-french-consulting-market.md +194 -0
  258. package/data/experts/specialized/specialized-korean-business-navigator.md +216 -0
  259. package/data/experts/specialized/specialized-master-plan-architect.md +157 -0
  260. package/data/experts/specialized/specialized-mcp-builder.md +248 -0
  261. package/data/experts/specialized/specialized-model-qa.md +488 -0
  262. package/data/experts/specialized/specialized-pricing-analyst.md +243 -0
  263. package/data/experts/specialized/specialized-salesforce-architect.md +182 -0
  264. package/data/experts/specialized/specialized-strategy-duel-agent.md +130 -0
  265. package/data/experts/specialized/specialized-workflow-architect.md +597 -0
  266. package/data/experts/specialized/study-abroad-advisor.md +282 -0
  267. package/data/experts/specialized/supply-chain-strategist.md +582 -0
  268. package/data/experts/specialized/zk-steward.md +211 -0
  269. package/data/experts/support/support-analytics-reporter.md +365 -0
  270. package/data/experts/support/support-executive-summary-generator.md +212 -0
  271. package/data/experts/support/support-finance-tracker.md +442 -0
  272. package/data/experts/support/support-infrastructure-maintainer.md +618 -0
  273. package/data/experts/support/support-legal-compliance-checker.md +588 -0
  274. package/data/experts/support/support-support-responder.md +585 -0
  275. package/data/experts/testing/testing-accessibility-auditor.md +316 -0
  276. package/data/experts/testing/testing-api-tester.md +306 -0
  277. package/data/experts/testing/testing-evidence-collector.md +210 -0
  278. package/data/experts/testing/testing-performance-benchmarker.md +268 -0
  279. package/data/experts/testing/testing-reality-checker.md +249 -0
  280. package/data/experts/testing/testing-test-automation-engineer.md +179 -0
  281. package/data/experts/testing/testing-test-results-analyzer.md +305 -0
  282. package/data/experts/testing/testing-tool-evaluator.md +394 -0
  283. package/data/experts/testing/testing-workflow-optimizer.md +450 -0
  284. package/data/source.json +27 -0
  285. package/data/t-team.config.json +998 -0
  286. package/data/team-profiles.py +365 -0
  287. package/data/teams.json +581 -0
  288. package/data/teams.resolved.json +1121 -0
  289. package/data/zh/COVERAGE.json +20 -0
  290. package/data/zh/academic/academic-anthropologist.md +124 -0
  291. package/data/zh/academic/academic-geographer.md +126 -0
  292. package/data/zh/academic/academic-historian.md +122 -0
  293. package/data/zh/academic/academic-narratologist.md +117 -0
  294. package/data/zh/academic/academic-psychologist.md +117 -0
  295. package/data/zh/academic/academic-statistician.md +40 -0
  296. package/data/zh/descriptions.json +281 -0
  297. package/data/zh/design/design-brand-guardian.md +321 -0
  298. package/data/zh/design/design-image-prompt-engineer.md +255 -0
  299. package/data/zh/design/design-inclusive-visuals-specialist.md +177 -0
  300. package/data/zh/design/design-persona-walkthrough.md +271 -0
  301. package/data/zh/design/design-ui-designer.md +382 -0
  302. package/data/zh/design/design-ui-finish-gate-reviewer.md +40 -0
  303. package/data/zh/design/design-ux-architect.md +482 -0
  304. package/data/zh/design/design-ux-researcher.md +328 -0
  305. package/data/zh/design/design-visual-storyteller.md +159 -0
  306. package/data/zh/design/design-whimsy-injector.md +453 -0
  307. package/data/zh/divisions.json +74 -0
  308. package/data/zh/engineering/engineering-ai-data-remediation-engineer.md +209 -0
  309. package/data/zh/engineering/engineering-ai-engineer.md +161 -0
  310. package/data/zh/engineering/engineering-api-platform-engineer.md +40 -0
  311. package/data/zh/engineering/engineering-ats-validator-architect.md +383 -0
  312. package/data/zh/engineering/engineering-autonomous-optimization-architect.md +115 -0
  313. package/data/zh/engineering/engineering-backend-architect.md +234 -0
  314. package/data/zh/engineering/engineering-china-network-engineer.md +252 -0
  315. package/data/zh/engineering/engineering-cms-developer.md +534 -0
  316. package/data/zh/engineering/engineering-code-reviewer.md +172 -0
  317. package/data/zh/engineering/engineering-codebase-onboarding-engineer.md +172 -0
  318. package/data/zh/engineering/engineering-data-engineer.md +324 -0
  319. package/data/zh/engineering/engineering-data-visualization-engineer.md +40 -0
  320. package/data/zh/engineering/engineering-database-optimizer.md +175 -0
  321. package/data/zh/engineering/engineering-database-reliability-engineer.md +40 -0
  322. package/data/zh/engineering/engineering-desktop-app-engineer.md +40 -0
  323. package/data/zh/engineering/engineering-developer-tooling-engineer.md +40 -0
  324. package/data/zh/engineering/engineering-devops-automator.md +375 -0
  325. package/data/zh/engineering/engineering-drupal-performance.md +40 -0
  326. package/data/zh/engineering/engineering-drupal-shopping-cart.md +359 -0
  327. package/data/zh/engineering/engineering-email-intelligence-engineer.md +349 -0
  328. package/data/zh/engineering/engineering-embedded-firmware-engineer.md +168 -0
  329. package/data/zh/engineering/engineering-feishu-integration-developer.md +597 -0
  330. package/data/zh/engineering/engineering-filament-optimization-specialist.md +283 -0
  331. package/data/zh/engineering/engineering-finops-engineer.md +40 -0
  332. package/data/zh/engineering/engineering-frontend-developer.md +224 -0
  333. package/data/zh/engineering/engineering-gaussdb-expert.md +40 -0
  334. package/data/zh/engineering/engineering-git-workflow-master.md +220 -0
  335. package/data/zh/engineering/engineering-i18n-engineer.md +40 -0
  336. package/data/zh/engineering/engineering-identity-access-engineer.md +40 -0
  337. package/data/zh/engineering/engineering-incident-response-commander.md +465 -0
  338. package/data/zh/engineering/engineering-iot-fleet-engineer.md +40 -0
  339. package/data/zh/engineering/engineering-it-service-manager.md +560 -0
  340. package/data/zh/engineering/engineering-knowledge-graph-engineer.md +40 -0
  341. package/data/zh/engineering/engineering-llm-post-training-engineer.md +40 -0
  342. package/data/zh/engineering/engineering-minimal-change-engineer.md +206 -0
  343. package/data/zh/engineering/engineering-mobile-app-builder.md +434 -0
  344. package/data/zh/engineering/engineering-mobile-release-engineer.md +40 -0
  345. package/data/zh/engineering/engineering-multi-agent-systems-architect.md +599 -0
  346. package/data/zh/engineering/engineering-network-engineer.md +40 -0
  347. package/data/zh/engineering/engineering-orgscript-engineer.md +112 -0
  348. package/data/zh/engineering/engineering-payments-billing-engineer.md +40 -0
  349. package/data/zh/engineering/engineering-pdf-engine-architect.md +666 -0
  350. package/data/zh/engineering/engineering-platform-engineer.md +271 -0
  351. package/data/zh/engineering/engineering-privacy-engineer.md +40 -0
  352. package/data/zh/engineering/engineering-prompt-engineer.md +203 -0
  353. package/data/zh/engineering/engineering-rag-pipeline-engineer.md +40 -0
  354. package/data/zh/engineering/engineering-rapid-prototyper.md +461 -0
  355. package/data/zh/engineering/engineering-realtime-collaboration-engineer.md +40 -0
  356. package/data/zh/engineering/engineering-rust-refactoring-specialist.md +40 -0
  357. package/data/zh/engineering/engineering-search-relevance-engineer.md +40 -0
  358. package/data/zh/engineering/engineering-section-508-specialist.md +40 -0
  359. package/data/zh/engineering/engineering-senior-developer.md +177 -0
  360. package/data/zh/engineering/engineering-software-architect.md +200 -0
  361. package/data/zh/engineering/engineering-solidity-smart-contract-engineer.md +541 -0
  362. package/data/zh/engineering/engineering-sre.md +233 -0
  363. package/data/zh/engineering/engineering-technical-writer.md +409 -0
  364. package/data/zh/engineering/engineering-universal-document-compiler.md +344 -0
  365. package/data/zh/engineering/engineering-uswds-developer.md +40 -0
  366. package/data/zh/engineering/engineering-video-streaming-engineer.md +40 -0
  367. package/data/zh/engineering/engineering-voice-ai-integration-engineer.md +560 -0
  368. package/data/zh/engineering/engineering-webassembly-engineer.md +40 -0
  369. package/data/zh/engineering/engineering-wechat-mini-program-developer.md +288 -0
  370. package/data/zh/engineering/engineering-wordpress-performance.md +40 -0
  371. package/data/zh/engineering/engineering-wordpress-shopping-cart.md +345 -0
  372. package/data/zh/finance/finance-bookkeeper-controller.md +271 -0
  373. package/data/zh/finance/finance-financial-analyst.md +244 -0
  374. package/data/zh/finance/finance-fpa-analyst.md +272 -0
  375. package/data/zh/finance/finance-investment-researcher.md +283 -0
  376. package/data/zh/finance/finance-tax-strategist.md +250 -0
  377. package/data/zh/game-development/blender/blender-addon-engineer.md +233 -0
  378. package/data/zh/game-development/economy-designer.md +40 -0
  379. package/data/zh/game-development/game-audio-engineer.md +265 -0
  380. package/data/zh/game-development/game-designer.md +168 -0
  381. package/data/zh/game-development/godot/godot-gameplay-scripter.md +335 -0
  382. package/data/zh/game-development/godot/godot-multiplayer-engineer.md +296 -0
  383. package/data/zh/game-development/godot/godot-shader-developer.md +267 -0
  384. package/data/zh/game-development/level-designer.md +209 -0
  385. package/data/zh/game-development/narrative-designer.md +244 -0
  386. package/data/zh/game-development/roblox-studio/roblox-avatar-creator.md +298 -0
  387. package/data/zh/game-development/roblox-studio/roblox-experience-designer.md +306 -0
  388. package/data/zh/game-development/roblox-studio/roblox-systems-scripter.md +325 -0
  389. package/data/zh/game-development/technical-artist.md +230 -0
  390. package/data/zh/game-development/unity/unity-architect.md +272 -0
  391. package/data/zh/game-development/unity/unity-editor-tool-developer.md +300 -0
  392. package/data/zh/game-development/unity/unity-multiplayer-engineer.md +238 -0
  393. package/data/zh/game-development/unity/unity-shader-graph-artist.md +270 -0
  394. package/data/zh/game-development/unreal-engine/unreal-multiplayer-architect.md +314 -0
  395. package/data/zh/game-development/unreal-engine/unreal-systems-engineer.md +311 -0
  396. package/data/zh/game-development/unreal-engine/unreal-technical-artist.md +256 -0
  397. package/data/zh/game-development/unreal-engine/unreal-world-builder.md +274 -0
  398. package/data/zh/gis/gis-3d-scene-developer.md +110 -0
  399. package/data/zh/gis/gis-analyst.md +90 -0
  400. package/data/zh/gis/gis-bim-specialist.md +107 -0
  401. package/data/zh/gis/gis-cartography-designer.md +149 -0
  402. package/data/zh/gis/gis-drone-reality-mapping.md +119 -0
  403. package/data/zh/gis/gis-geoai-ml-engineer.md +104 -0
  404. package/data/zh/gis/gis-geoprocessing-specialist.md +96 -0
  405. package/data/zh/gis/gis-qa-engineer.md +132 -0
  406. package/data/zh/gis/gis-solution-engineer.md +100 -0
  407. package/data/zh/gis/gis-spatial-data-engineer.md +96 -0
  408. package/data/zh/gis/gis-spatial-data-scientist.md +110 -0
  409. package/data/zh/gis/gis-technical-consultant.md +85 -0
  410. package/data/zh/gis/gis-web-gis-developer.md +107 -0
  411. package/data/zh/healthcare/healthcare-clinical-evidence-agent.md +40 -0
  412. package/data/zh/healthcare/healthcare-innovation-strategist.md +40 -0
  413. package/data/zh/healthcare/healthcare-sovereign-health-systems-agent.md +40 -0
  414. package/data/zh/manual-bodies/engineering/engineering-ats-validator-architect.md +383 -0
  415. package/data/zh/manual-bodies/engineering/engineering-china-network-engineer.md +252 -0
  416. package/data/zh/manual-bodies/engineering/engineering-pdf-engine-architect.md +666 -0
  417. package/data/zh/manual-bodies/engineering/engineering-platform-engineer.md +271 -0
  418. package/data/zh/manual-bodies/engineering/engineering-universal-document-compiler.md +344 -0
  419. package/data/zh/manual-bodies/specialized/specialized-focus-music-architect.md +172 -0
  420. package/data/zh/manual.json +22 -0
  421. package/data/zh/marketing/marketing-aeo-foundations.md +263 -0
  422. package/data/zh/marketing/marketing-agentic-search-optimizer.md +312 -0
  423. package/data/zh/marketing/marketing-ai-citation-strategist.md +169 -0
  424. package/data/zh/marketing/marketing-app-store-optimizer.md +319 -0
  425. package/data/zh/marketing/marketing-baidu-seo-specialist.md +220 -0
  426. package/data/zh/marketing/marketing-bilibili-content-strategist.md +40 -0
  427. package/data/zh/marketing/marketing-book-co-author.md +109 -0
  428. package/data/zh/marketing/marketing-carousel-growth-engine.md +215 -0
  429. package/data/zh/marketing/marketing-china-ecommerce-operator.md +277 -0
  430. package/data/zh/marketing/marketing-china-market-localization-strategist.md +282 -0
  431. package/data/zh/marketing/marketing-content-creator.md +145 -0
  432. package/data/zh/marketing/marketing-cross-border-ecommerce.md +260 -0
  433. package/data/zh/marketing/marketing-douyin-strategist.md +150 -0
  434. package/data/zh/marketing/marketing-email-strategist.md +248 -0
  435. package/data/zh/marketing/marketing-global-podcast-strategist.md +204 -0
  436. package/data/zh/marketing/marketing-growth-hacker.md +121 -0
  437. package/data/zh/marketing/marketing-instagram-curator.md +179 -0
  438. package/data/zh/marketing/marketing-kuaishou-strategist.md +182 -0
  439. package/data/zh/marketing/marketing-linkedin-content-creator.md +232 -0
  440. package/data/zh/marketing/marketing-livestream-commerce-coach.md +303 -0
  441. package/data/zh/marketing/marketing-multi-platform-publisher.md +216 -0
  442. package/data/zh/marketing/marketing-podcast-strategist.md +278 -0
  443. package/data/zh/marketing/marketing-pr-communications-manager.md +472 -0
  444. package/data/zh/marketing/marketing-private-domain-operator.md +309 -0
  445. package/data/zh/marketing/marketing-reddit-community-builder.md +127 -0
  446. package/data/zh/marketing/marketing-seo-specialist.md +298 -0
  447. package/data/zh/marketing/marketing-short-video-editing-coach.md +413 -0
  448. package/data/zh/marketing/marketing-social-media-strategist.md +118 -0
  449. package/data/zh/marketing/marketing-tiktok-strategist.md +124 -0
  450. package/data/zh/marketing/marketing-twitter-engager.md +132 -0
  451. package/data/zh/marketing/marketing-video-optimization-specialist.md +128 -0
  452. package/data/zh/marketing/marketing-wechat-official-account.md +158 -0
  453. package/data/zh/marketing/marketing-weibo-strategist.md +241 -0
  454. package/data/zh/marketing/marketing-x-twitter-intelligence-analyst.md +160 -0
  455. package/data/zh/marketing/marketing-xiaohongshu-specialist.md +151 -0
  456. package/data/zh/marketing/marketing-zhihu-strategist.md +175 -0
  457. package/data/zh/names.json +281 -0
  458. package/data/zh/paid-media/paid-media-auditor.md +170 -0
  459. package/data/zh/paid-media/paid-media-creative-strategist.md +173 -0
  460. package/data/zh/paid-media/paid-media-paid-social-strategist.md +180 -0
  461. package/data/zh/paid-media/paid-media-ppc-strategist.md +180 -0
  462. package/data/zh/paid-media/paid-media-programmatic-buyer.md +177 -0
  463. package/data/zh/paid-media/paid-media-search-query-analyst.md +182 -0
  464. package/data/zh/paid-media/paid-media-tracking-specialist.md +199 -0
  465. package/data/zh/product/product-behavioral-nudge-engine.md +246 -0
  466. package/data/zh/product/product-feedback-synthesizer.md +175 -0
  467. package/data/zh/product/product-manager.md +474 -0
  468. package/data/zh/product/product-sprint-prioritizer.md +133 -0
  469. package/data/zh/product/product-trend-researcher.md +143 -0
  470. package/data/zh/project-management/project-management-experiment-tracker.md +206 -0
  471. package/data/zh/project-management/project-management-jira-workflow-steward.md +249 -0
  472. package/data/zh/project-management/project-management-meeting-notes-specialist.md +94 -0
  473. package/data/zh/project-management/project-management-project-shepherd.md +202 -0
  474. package/data/zh/project-management/project-management-studio-operations.md +208 -0
  475. package/data/zh/project-management/project-management-studio-producer.md +211 -0
  476. package/data/zh/project-management/project-manager-senior.md +135 -0
  477. package/data/zh/research/research-synthesist.md +40 -0
  478. package/data/zh/sales/sales-account-strategist.md +243 -0
  479. package/data/zh/sales/sales-coach.md +291 -0
  480. package/data/zh/sales/sales-deal-strategist.md +204 -0
  481. package/data/zh/sales/sales-discovery-coach.md +230 -0
  482. package/data/zh/sales/sales-engineer.md +200 -0
  483. package/data/zh/sales/sales-offer-lead-gen-strategist.md +256 -0
  484. package/data/zh/sales/sales-outbound-strategist.md +208 -0
  485. package/data/zh/sales/sales-pipeline-analyst.md +284 -0
  486. package/data/zh/sales/sales-proposal-strategist.md +233 -0
  487. package/data/zh/security/security-ai-generated-code-auditor.md +40 -0
  488. package/data/zh/security/security-appsec-engineer.md +490 -0
  489. package/data/zh/security/security-architect.md +303 -0
  490. package/data/zh/security/security-blockchain-security-auditor.md +462 -0
  491. package/data/zh/security/security-cloud-security-architect.md +522 -0
  492. package/data/zh/security/security-compliance-auditor.md +157 -0
  493. package/data/zh/security/security-incident-responder.md +436 -0
  494. package/data/zh/security/security-penetration-tester.md +398 -0
  495. package/data/zh/security/security-secrets-credential-engineer.md +40 -0
  496. package/data/zh/security/security-senior-secops.md +751 -0
  497. package/data/zh/security/security-threat-detection-engineer.md +533 -0
  498. package/data/zh/security/security-threat-intelligence-analyst.md +643 -0
  499. package/data/zh/spatial-computing/macos-spatial-metal-engineer.md +337 -0
  500. package/data/zh/spatial-computing/terminal-integration-specialist.md +236 -0
  501. package/data/zh/spatial-computing/visionos-spatial-engineer.md +282 -0
  502. package/data/zh/spatial-computing/xr-cockpit-interaction-specialist.md +220 -0
  503. package/data/zh/spatial-computing/xr-immersive-developer.md +229 -0
  504. package/data/zh/spatial-computing/xr-interface-architect.md +253 -0
  505. package/data/zh/specialized/accounts-payable-agent.md +212 -0
  506. package/data/zh/specialized/agentic-identity-trust.md +388 -0
  507. package/data/zh/specialized/agents-orchestrator.md +366 -0
  508. package/data/zh/specialized/automation-governance-architect.md +215 -0
  509. package/data/zh/specialized/business-strategist.md +487 -0
  510. package/data/zh/specialized/change-management-consultant.md +495 -0
  511. package/data/zh/specialized/chief-financial-officer.md +390 -0
  512. package/data/zh/specialized/corporate-training-designer.md +191 -0
  513. package/data/zh/specialized/customer-service.md +40 -0
  514. package/data/zh/specialized/customer-success-manager.md +458 -0
  515. package/data/zh/specialized/data-consolidation-agent.md +327 -0
  516. package/data/zh/specialized/data-privacy-officer.md +411 -0
  517. package/data/zh/specialized/esg-sustainability-officer.md +395 -0
  518. package/data/zh/specialized/government-digital-presales-consultant.md +362 -0
  519. package/data/zh/specialized/grant-writer.md +510 -0
  520. package/data/zh/specialized/healthcare-aging-parent-care-companion.md +40 -0
  521. package/data/zh/specialized/healthcare-customer-service.md +388 -0
  522. package/data/zh/specialized/healthcare-marketing-compliance.md +394 -0
  523. package/data/zh/specialized/hospitality-guest-services.md +597 -0
  524. package/data/zh/specialized/hr-onboarding.md +450 -0
  525. package/data/zh/specialized/identity-graph-operator.md +270 -0
  526. package/data/zh/specialized/language-translator.md +275 -0
  527. package/data/zh/specialized/legal-billing-time-tracking.md +566 -0
  528. package/data/zh/specialized/legal-client-intake.md +487 -0
  529. package/data/zh/specialized/legal-document-review.md +452 -0
  530. package/data/zh/specialized/loan-officer-assistant.md +549 -0
  531. package/data/zh/specialized/lsp-index-engineer.md +334 -0
  532. package/data/zh/specialized/ma-integration-manager.md +426 -0
  533. package/data/zh/specialized/medical-billing-coding-specialist.md +489 -0
  534. package/data/zh/specialized/operations-manager.md +398 -0
  535. package/data/zh/specialized/organizational-psychologist.md +390 -0
  536. package/data/zh/specialized/personal-growth-mentor.md +158 -0
  537. package/data/zh/specialized/real-estate-buyer-seller.md +594 -0
  538. package/data/zh/specialized/recruitment-specialist.md +49 -0
  539. package/data/zh/specialized/report-distribution-agent.md +354 -0
  540. package/data/zh/specialized/resume-tailor.md +40 -0
  541. package/data/zh/specialized/retail-customer-returns.md +564 -0
  542. package/data/zh/specialized/sales-data-extraction-agent.md +159 -0
  543. package/data/zh/specialized/sales-outreach.md +40 -0
  544. package/data/zh/specialized/specialized-chief-of-staff.md +40 -0
  545. package/data/zh/specialized/specialized-civil-engineer.md +355 -0
  546. package/data/zh/specialized/specialized-codebase-archaeologist.md +40 -0
  547. package/data/zh/specialized/specialized-cultural-intelligence-strategist.md +168 -0
  548. package/data/zh/specialized/specialized-developer-advocate.md +334 -0
  549. package/data/zh/specialized/specialized-document-generator.md +346 -0
  550. package/data/zh/specialized/specialized-fedramp-rmf-compliance.md +40 -0
  551. package/data/zh/specialized/specialized-focus-music-architect.md +172 -0
  552. package/data/zh/specialized/specialized-french-consulting-market.md +46 -0
  553. package/data/zh/specialized/specialized-korean-business-navigator.md +46 -0
  554. package/data/zh/specialized/specialized-master-plan-architect.md +40 -0
  555. package/data/zh/specialized/specialized-mcp-builder.md +351 -0
  556. package/data/zh/specialized/specialized-model-qa.md +507 -0
  557. package/data/zh/specialized/specialized-pricing-analyst.md +242 -0
  558. package/data/zh/specialized/specialized-salesforce-architect.md +179 -0
  559. package/data/zh/specialized/specialized-strategy-duel-agent.md +129 -0
  560. package/data/zh/specialized/specialized-workflow-architect.md +596 -0
  561. package/data/zh/specialized/study-abroad-advisor.md +281 -0
  562. package/data/zh/specialized/supply-chain-strategist.md +581 -0
  563. package/data/zh/specialized/zk-steward.md +228 -0
  564. package/data/zh/support/support-analytics-reporter.md +364 -0
  565. package/data/zh/support/support-executive-summary-generator.md +217 -0
  566. package/data/zh/support/support-finance-tracker.md +447 -0
  567. package/data/zh/support/support-infrastructure-maintainer.md +623 -0
  568. package/data/zh/support/support-legal-compliance-checker.md +587 -0
  569. package/data/zh/support/support-support-responder.md +584 -0
  570. package/data/zh/testing/testing-accessibility-auditor.md +329 -0
  571. package/data/zh/testing/testing-api-tester.md +305 -0
  572. package/data/zh/testing/testing-evidence-collector.md +153 -0
  573. package/data/zh/testing/testing-performance-benchmarker.md +196 -0
  574. package/data/zh/testing/testing-reality-checker.md +235 -0
  575. package/data/zh/testing/testing-test-automation-engineer.md +40 -0
  576. package/data/zh/testing/testing-test-results-analyzer.md +313 -0
  577. package/data/zh/testing/testing-tool-evaluator.md +402 -0
  578. package/data/zh/testing/testing-workflow-optimizer.md +458 -0
  579. package/lib/assets/t-team/action-celebrating-v2.png +0 -0
  580. package/lib/assets/t-team/action-reporting-v2.png +0 -0
  581. package/lib/assets/t-team/action-sending-v2.png +0 -0
  582. package/lib/assets/t-team/action-sleeping-v2.png +0 -0
  583. package/lib/assets/t-team/action-thinking-v2.png +0 -0
  584. package/lib/assets/t-team/action-working-v2.png +0 -0
  585. package/lib/assets/t-team/member-data-v2.png +0 -0
  586. package/lib/assets/t-team/member-designer-v2.png +0 -0
  587. package/lib/assets/t-team/member-docs-v2.png +0 -0
  588. package/lib/assets/t-team/member-engineer-v2.png +0 -0
  589. package/lib/assets/t-team/member-operator-v2.png +0 -0
  590. package/lib/assets/t-team/member-qa-v2.png +0 -0
  591. package/lib/assets/t-team/member-researcher-v2.png +0 -0
  592. package/lib/assets/t-team/member-security-v2.png +0 -0
  593. package/lib/assets/t-team/team-lead-v2.png +0 -0
  594. package/lib/bootstrap.js +85 -0
  595. package/lib/catalog.js +376 -0
  596. package/lib/client.js +21034 -0
  597. package/lib/command.js +228 -0
  598. package/lib/i18n.js +136 -0
  599. package/lib/index.js +686 -0
  600. package/lib/plan-check.js +171 -0
  601. package/lib/remote.js +353 -0
  602. package/lib/squads.js +231 -0
  603. package/lib/teams/capabilities.js +106 -0
  604. package/lib/teams/command.js +143 -0
  605. package/lib/teams/event-types.js +12 -0
  606. package/lib/teams/events.js +60 -0
  607. package/lib/teams/harness-compat.js +179 -0
  608. package/lib/teams/index.js +441 -0
  609. package/lib/teams/members.js +602 -0
  610. package/lib/teams/profiles.js +572 -0
  611. package/lib/teams/quality-gates.js +822 -0
  612. package/lib/teams/scheduler.js +434 -0
  613. package/lib/teams/snapshot.js +181 -0
  614. package/lib/teams/state.js +925 -0
  615. package/lib/teams/tool-names.js +11 -0
  616. package/lib/teams/tools.js +2279 -0
  617. package/lib/teams/types.js +22 -0
  618. package/lib/teams/web-routes.js +86 -0
  619. package/package.json +191 -0
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Event-driven shared task scheduler.
3
+ *
4
+ * Claude Code teammates keep polling the shared task list after a turn. DSH
5
+ * continuable agents instead expose explicit idle/running edges, so this
6
+ * scheduler closes the same loop without keeping a polling turn alive: every
7
+ * idle edge and every task-graph mutation attempts one atomic claim and wakes
8
+ * the selected durable member. A resident member that becomes idle while it
9
+ * still owns an open attempt is parked: only an explicit captain reassignment
10
+ * may rotate that capability. Automatic retry is reserved for cold recovery,
11
+ * when this process has not observed the durable owner settle its open attempt.
12
+ * @module t-team/scheduler
13
+ */
14
+ import { join } from 'node:path';
15
+ import { deliverToMember } from "./members.js";
16
+ import { acknowledgeMailbox, beginTaskAttempt, CAPTAIN_KEY, claimMailboxDelivery, findTeamByParticipant, invalidateTaskAttempt, readTeam, readUnreadMailbox, releaseMailboxDelivery, unsatisfiedDependencies, withTeamLock, writeTeam, } from "./state.js";
17
+ /** Per-dependency output cap in the assignment prompt. */
18
+ export const DEPENDENCY_OUTPUT_MAX_CHARS = 2_000;
19
+ /** Combined dependency-output budget in the assignment prompt. */
20
+ export const DEPENDENCY_OUTPUTS_TOTAL_MAX_CHARS = 12_000;
21
+ function taskProfileSeedId(task) {
22
+ const seed = task.profileSeedId?.trim();
23
+ return seed === undefined || seed === '' ? undefined : seed;
24
+ }
25
+ function teamProfileProtocol(team) {
26
+ return team.profile?.protocol;
27
+ }
28
+ /**
29
+ * Recursively collect `status=completed` ancestors of `taskId` in topological
30
+ * order (dependencies before dependents). Cycles stop that branch only.
31
+ */
32
+ export function collectCompletedDependencyOutputs(tasks, taskId, warn) {
33
+ const byId = new Map(tasks.map(task => [task.id, task]));
34
+ const visiting = new Set();
35
+ const visited = new Set();
36
+ const ordered = [];
37
+ const walk = (id) => {
38
+ if (visiting.has(id)) {
39
+ warn?.(`t-team: dependency cycle involving "${id}" while collecting outputs; stopping this branch`);
40
+ return;
41
+ }
42
+ if (visited.has(id))
43
+ return;
44
+ visiting.add(id);
45
+ const task = byId.get(id);
46
+ if (task !== undefined) {
47
+ for (const dependency of task.dependencies)
48
+ walk(dependency);
49
+ if (id !== taskId)
50
+ ordered.push(task);
51
+ }
52
+ visiting.delete(id);
53
+ visited.add(id);
54
+ };
55
+ walk(taskId);
56
+ return ordered
57
+ .filter(task => task.status === 'completed')
58
+ .map((task) => {
59
+ const profileSeedId = taskProfileSeedId(task);
60
+ return {
61
+ id: task.id,
62
+ subject: task.subject,
63
+ ...profileSeedId === undefined ? {} : { profileSeedId },
64
+ ...task.output === undefined ? {} : { output: task.output },
65
+ };
66
+ });
67
+ }
68
+ /** Format completed-dependency outputs with per-item and total truncation. */
69
+ export function formatDependencyOutputs(items) {
70
+ if (items.length === 0)
71
+ return '(none)';
72
+ const formatted = items.map((item) => {
73
+ const seed = item.profileSeedId === undefined ? '' : ` [${item.profileSeedId}]`;
74
+ const raw = item.output === undefined || item.output === ''
75
+ ? '(no output recorded)'
76
+ : item.output;
77
+ const truncated = raw.length > DEPENDENCY_OUTPUT_MAX_CHARS;
78
+ const body = truncated ? `${raw.slice(0, DEPENDENCY_OUTPUT_MAX_CHARS)} [truncated]` : raw;
79
+ return `- ${item.id}${seed} ${item.subject}:\n ${body}`;
80
+ });
81
+ let selected = formatted;
82
+ while (selected.length > 1 && selected.join('\n').length > DEPENDENCY_OUTPUTS_TOTAL_MAX_CHARS) {
83
+ selected = selected.slice(1);
84
+ }
85
+ const last = selected[0];
86
+ if (selected.length === 1 && last !== undefined && last.length > DEPENDENCY_OUTPUTS_TOTAL_MAX_CHARS) {
87
+ selected = [`${last.slice(0, DEPENDENCY_OUTPUTS_TOTAL_MAX_CHARS)} [truncated]`];
88
+ }
89
+ return selected.join('\n');
90
+ }
91
+ function stateRootOf(workspace, config) {
92
+ return join(workspace, config.stateDir);
93
+ }
94
+ function teamLockKey(stateRoot, teamId) {
95
+ return `team:${stateRoot}:${teamId}`;
96
+ }
97
+ function liveCaptain(ctx, captainSessionId, supplied) {
98
+ if (supplied !== undefined && supplied.id === captainSessionId)
99
+ return supplied;
100
+ return ctx.agents.get(captainSessionId);
101
+ }
102
+ function liveMember(ctx, member) {
103
+ return ctx.agents.get(member.id);
104
+ }
105
+ function isMemberAvailable(ctx, member) {
106
+ const live = liveMember(ctx, member);
107
+ return live === undefined || live.status === 'idle';
108
+ }
109
+ function ownedOpenTask(tasks, memberName) {
110
+ return tasks.find(task => task.assignee === memberName
111
+ && (task.status === 'claimed' || task.status === 'in_progress'));
112
+ }
113
+ function nextReadyTask(tasks, memberName) {
114
+ const ready = tasks.filter(task => task.status === 'pending'
115
+ && task.reassigning !== true
116
+ && unsatisfiedDependencies([...tasks], task.dependencies).length === 0);
117
+ return ready.find(task => task.assignee === memberName)
118
+ ?? ready.find(task => task.assignee === undefined);
119
+ }
120
+ export function assignmentPrompt(ticket, stateDir, teamId) {
121
+ const description = ticket.description === undefined ? '' : `\n\n${ticket.description}`;
122
+ const seed = ticket.profileSeedId === undefined ? '' : ` [${ticket.profileSeedId}]`;
123
+ const goal = ticket.teamDescription?.trim() || '(not provided)';
124
+ const protocol = ticket.profileProtocol?.trim() || '(none)';
125
+ const executionPrompt = ticket.executionPrompt?.trim();
126
+ const kind = ticket.kind?.trim() || 'work';
127
+ const contract = [
128
+ `Kind: ${kind}${ticket.round === undefined ? '' : ` (round ${ticket.round})`}`,
129
+ ticket.objective === undefined || ticket.objective === '' ? '' : `Objective: ${ticket.objective}`,
130
+ ticket.inScope === undefined || ticket.inScope.length === 0 ? '' : `In scope: ${ticket.inScope.join(', ')}`,
131
+ ticket.outOfScope === undefined || ticket.outOfScope.length === 0 ? '' : `Out of scope: ${ticket.outOfScope.join(', ')}`,
132
+ ticket.acceptance === undefined || ticket.acceptance.length === 0 ? '' : `Acceptance: ${ticket.acceptance.join('; ')}`,
133
+ ticket.verify === undefined || ticket.verify.length === 0 ? '' : `Verify: ${ticket.verify.join('; ')}`,
134
+ ticket.reviewedTaskId === undefined ? '' : `Reviewed task: ${ticket.reviewedTaskId}`,
135
+ ].filter((line) => line !== '').join('\n');
136
+ const structuredCompletion = ['implementation', 'repair', 'verification', 'integration'].includes(kind)
137
+ ? `
138
+ Structured completion payload (keep these arrays in contract order):
139
+ acceptanceResults: ${JSON.stringify((ticket.acceptance ?? []).map((criterion) => ({ criterion, status: 'passed', evidence: '<what proved it>' })))}
140
+ commandsRun: ${JSON.stringify((ticket.verify ?? []).map((command) => ({ command, status: 'passed', exitCode: 0, evidence: '<observed result>' })))}
141
+ ${kind === 'implementation' || kind === 'repair' ? 'changedPaths: list the actual workspace-relative POSIX paths you changed.\n' : ''}`
142
+ : '';
143
+ return `T Team automatic task assignment from the shared task list.
144
+
145
+ You are executing as configured member "${ticket.memberName}".
146
+ Do not start a teammate's assigned task.
147
+
148
+ Team goal:
149
+ ${goal}
150
+
151
+ Profile protocol:
152
+ ${protocol}
153
+ ${executionPrompt === undefined || executionPrompt === '' ? '' : `
154
+ Execution guidance:
155
+ ${executionPrompt}
156
+ `}
157
+ Completed dependency results:
158
+ ${formatDependencyOutputs(ticket.dependencyOutputs)}
159
+
160
+ Task: ${ticket.taskId}${seed} — ${ticket.subject}${description}
161
+ ${contract === '' ? '' : `\nContract:\n${contract}\n`}
162
+ ${structuredCompletion}
163
+ Attempt: ${ticket.attempt}
164
+ Attempt id: ${ticket.attemptId}
165
+
166
+ Call t_team_claim_task for ${ticket.taskId}; it will return this same attempt_id. Include attempt_id=${ticket.attemptId} in every t_team_update_task call. If it is rejected as stale, stop work because the task was reassigned. claimed cannot jump to completed. Mark in_progress first, then completed or failed. Include attempt_id on every update. Then send_message to captain and become idle.
167
+ When finishing: use status=completed only when the task's success criteria are satisfied; use status=failed when blocking findings or validation failures mean downstream work must not proceed; include a concise output in either case. Quality kinds must submit structured fields: review/requirements need verdict=pass to complete (needs_revision/reject must fail with findings); implementation/repair/verification/integration need acceptanceResults and commandsRun, while implementation/repair also need in-scope changedPaths. Use status values "passed" or "failed" inside those arrays. After the work and verification finish, call t_team_update_task immediately; do not wait for captain confirmation and do not continue exploring. Do not approve your own implementation. Mail is not a formal next review. Treat the dependency results above as source material. Do not ignore them. Work only this task and only its in-scope paths in this turn.
168
+
169
+ State policy: ${stateDir}/${teamId}/ is read-only diagnostics; mutate team state only through t_team_* tools.`;
170
+ }
171
+ function fallbackMailboxPrompt(messages) {
172
+ return [
173
+ 'T Team delivered messages that were persisted while live delivery was unavailable:',
174
+ ...messages.map(message => `\nFrom ${message.from}:\n${message.content}`),
175
+ '\nHandle these messages in this turn. Task assignments still require t_team_claim_task and the current attempt_id.',
176
+ ].join('\n');
177
+ }
178
+ /** Install one scheduler and its member activity observer. */
179
+ export function installTeamScheduler(ctx, config) {
180
+ const memberQueues = new Map();
181
+ // An idle edge in this process proves that the resident member ended its
182
+ // turn while the current attempt was still open. Remember that capability
183
+ // even after Harness disposes the continuable AgentHandle: later status or
184
+ // graph kicks must keep it parked. A cold process starts with an empty map,
185
+ // so durable open attempts are still recovered after restart.
186
+ const parkedAttempts = new Map();
187
+ const memberQueueKey = (stateRoot, teamId, memberName) => (`${stateRoot}\u0000${teamId}\u0000${memberName}`);
188
+ const serializeMember = async (key, operation) => {
189
+ const previous = memberQueues.get(key) ?? Promise.resolve();
190
+ let release;
191
+ const gate = new Promise((resolve) => { release = resolve; });
192
+ const tail = previous.then(() => gate);
193
+ memberQueues.set(key, tail);
194
+ await previous;
195
+ try {
196
+ return await operation();
197
+ }
198
+ finally {
199
+ release();
200
+ if (memberQueues.get(key) === tail)
201
+ memberQueues.delete(key);
202
+ }
203
+ };
204
+ const runtime = {
205
+ async kickTeam(workspace, teamId, suppliedCaptain) {
206
+ const stateRoot = stateRootOf(workspace, config);
207
+ const team = await readTeam(stateRoot, teamId);
208
+ if (team === undefined || team.halted === true || team.phase === 'staged')
209
+ return;
210
+ const captain = liveCaptain(ctx, team.captainSessionId, suppliedCaptain);
211
+ if (captain === undefined)
212
+ return;
213
+ for (const member of team.members) {
214
+ if (member.status === 'removed')
215
+ continue;
216
+ await runtime.kickMember(workspace, teamId, member.name, captain);
217
+ }
218
+ },
219
+ async kickMember(workspace, teamId, memberName, suppliedCaptain) {
220
+ const stateRoot = stateRootOf(workspace, config);
221
+ const queueKey = memberQueueKey(stateRoot, teamId, memberName);
222
+ await serializeMember(queueKey, async () => {
223
+ let team = await readTeam(stateRoot, teamId);
224
+ if (team === undefined || team.halted === true || team.phase === 'staged')
225
+ return;
226
+ const captain = liveCaptain(ctx, team.captainSessionId, suppliedCaptain);
227
+ if (captain === undefined)
228
+ return;
229
+ let member = team.members.find(candidate => candidate.name === memberName && candidate.status !== 'removed');
230
+ if (member === undefined || member.id === '' || !isMemberAvailable(ctx, member))
231
+ return;
232
+ // A mailbox-only fallback is real pending work. Deliver it before a
233
+ // fresh task and acknowledge only after Harness accepts the follow-up.
234
+ const unread = await readUnreadMailbox(stateRoot, team.id, member.name);
235
+ if (unread.length > 0) {
236
+ await withTeamLock(teamLockKey(stateRoot, team.id), () => (claimMailboxDelivery(stateRoot, team.id, member.name, unread.map(message => message.id))));
237
+ const accepted = await deliverToMember(ctx, captain, member.id, fallbackMailboxPrompt(unread), new AbortController().signal);
238
+ if (accepted) {
239
+ await withTeamLock(teamLockKey(stateRoot, team.id), () => (acknowledgeMailbox(stateRoot, team.id, member.name, unread.map(message => message.id))));
240
+ }
241
+ else {
242
+ await withTeamLock(teamLockKey(stateRoot, team.id), () => (releaseMailboxDelivery(stateRoot, team.id, member.name, unread.map(message => message.id))));
243
+ }
244
+ return;
245
+ }
246
+ const ticket = await withTeamLock(teamLockKey(stateRoot, team.id), async () => {
247
+ const fresh = await readTeam(stateRoot, team.id);
248
+ if (fresh === undefined || fresh.halted === true || fresh.phase === 'staged')
249
+ return undefined;
250
+ const currentMember = fresh.members.find(candidate => candidate.name === memberName && candidate.status !== 'removed');
251
+ if (currentMember === undefined || currentMember.id === '' || !isMemberAvailable(ctx, currentMember))
252
+ return undefined;
253
+ const owned = ownedOpenTask(fresh.tasks, currentMember.name);
254
+ // An idle edge observed by this scheduler parks the exact open
255
+ // capability. Harness may dispose its AgentHandle after settlement,
256
+ // so registry absence is not evidence that the owner was lost. Keep
257
+ // the marker sticky across later kicks; only a durable attempt that
258
+ // this process has not observed is eligible for one cold recovery.
259
+ const parkedAttemptId = parkedAttempts.get(currentMember.id);
260
+ const recoverOwned = owned !== undefined
261
+ && (owned.attemptId === undefined || owned.attemptId !== parkedAttemptId);
262
+ const task = recoverOwned ? owned : owned === undefined
263
+ ? nextReadyTask(fresh.tasks, currentMember.name)
264
+ : undefined;
265
+ if (task === undefined) {
266
+ if (currentMember.status !== 'idle') {
267
+ currentMember.status = 'idle';
268
+ await writeTeam(stateRoot, fresh);
269
+ }
270
+ return undefined;
271
+ }
272
+ const previousAssignee = task.assignee;
273
+ const previousStatus = recoverOwned ? task.status : undefined;
274
+ const previousAttempt = recoverOwned ? task.attempt : undefined;
275
+ const previousAttemptId = recoverOwned ? task.attemptId : undefined;
276
+ const attemptId = beginTaskAttempt(task, currentMember.name);
277
+ // A recovered generation is parked before delivery. This makes each
278
+ // (member, attempt) recovery idempotent even if every status poll
279
+ // sees a disposed handle. Fresh pending work remains unparked so a
280
+ // genuinely lost first delivery can be recovered once.
281
+ if (recoverOwned)
282
+ parkedAttempts.set(currentMember.id, attemptId);
283
+ else
284
+ parkedAttempts.delete(currentMember.id);
285
+ currentMember.status = 'working';
286
+ await writeTeam(stateRoot, fresh);
287
+ const profileSeedId = taskProfileSeedId(task);
288
+ const protocol = teamProfileProtocol(fresh);
289
+ return {
290
+ taskId: task.id,
291
+ memberName: currentMember.name,
292
+ memberId: currentMember.id,
293
+ attempt: task.attempt ?? 1,
294
+ attemptId,
295
+ previousAssignee,
296
+ recoveredOwned: recoverOwned,
297
+ ...previousStatus === undefined ? {} : { previousStatus },
298
+ ...previousAttempt === undefined ? {} : { previousAttempt },
299
+ ...previousAttemptId === undefined ? {} : { previousAttemptId },
300
+ subject: task.subject,
301
+ description: task.description,
302
+ teamDescription: fresh.description,
303
+ ...protocol === undefined ? {} : { profileProtocol: protocol },
304
+ ...profileSeedId === undefined ? {} : { profileSeedId },
305
+ ...fresh.profile?.executionPrompt === undefined && config.executionPrompt === undefined
306
+ ? {}
307
+ : { executionPrompt: fresh.profile?.executionPrompt ?? config.executionPrompt },
308
+ kind: task.kind ?? 'work',
309
+ ...task.round === undefined ? {} : { round: task.round },
310
+ ...task.objective === undefined ? {} : { objective: task.objective },
311
+ ...task.inScope === undefined ? {} : { inScope: task.inScope },
312
+ ...task.outOfScope === undefined ? {} : { outOfScope: task.outOfScope },
313
+ ...task.acceptance === undefined ? {} : { acceptance: task.acceptance },
314
+ ...task.verify === undefined ? {} : { verify: task.verify },
315
+ ...task.reviewedTaskId === undefined ? {} : { reviewedTaskId: task.reviewedTaskId },
316
+ dependencyOutputs: collectCompletedDependencyOutputs(fresh.tasks, task.id, (message) => ctx.logger.warn(message)),
317
+ };
318
+ });
319
+ if (ticket === undefined)
320
+ return;
321
+ const accepted = await deliverToMember(ctx, captain, ticket.memberId, assignmentPrompt(ticket, config.stateDir, team.id), new AbortController().signal);
322
+ if (accepted)
323
+ return;
324
+ // Roll back only our exact failed dispatch. A concurrent captain
325
+ // handoff has already changed the capability and wins.
326
+ await withTeamLock(teamLockKey(stateRoot, team.id), async () => {
327
+ const fresh = await readTeam(stateRoot, team.id);
328
+ if (fresh === undefined)
329
+ return;
330
+ const task = fresh.tasks.find(candidate => candidate.id === ticket.taskId);
331
+ if (task?.attemptId !== ticket.attemptId)
332
+ return;
333
+ if (ticket.recoveredOwned && ticket.previousStatus !== undefined && ticket.previousAttemptId !== undefined) {
334
+ // Recovery delivery failed. Restore the durable generation instead
335
+ // of returning it to pending, then keep it parked so later status
336
+ // kicks cannot spend an unbounded sequence of fresh attempts.
337
+ task.status = ticket.previousStatus;
338
+ task.assignee = ticket.previousAssignee;
339
+ task.attempt = ticket.previousAttempt;
340
+ task.attemptId = ticket.previousAttemptId;
341
+ parkedAttempts.set(ticket.memberId, ticket.previousAttemptId);
342
+ }
343
+ else {
344
+ task.status = 'pending';
345
+ task.assignee = ticket.previousAssignee;
346
+ task.attemptId = undefined;
347
+ parkedAttempts.delete(ticket.memberId);
348
+ }
349
+ task.handoffId = undefined;
350
+ task.reassigning = false;
351
+ task.updatedAt = Date.now();
352
+ const currentMember = fresh.members.find(candidate => candidate.name === ticket.memberName);
353
+ if (currentMember !== undefined && currentMember.status !== 'removed')
354
+ currentMember.status = 'idle';
355
+ await writeTeam(stateRoot, fresh);
356
+ });
357
+ });
358
+ },
359
+ };
360
+ const syncMemberStatus = async (agent, status) => {
361
+ const workspace = agent.session.header.cwd ?? process.cwd();
362
+ const stateRoot = stateRootOf(workspace, config);
363
+ const located = await findTeamByParticipant(stateRoot, agent.id);
364
+ if (located === undefined) {
365
+ parkedAttempts.delete(agent.id);
366
+ return;
367
+ }
368
+ if (located.captainSessionId === agent.id) {
369
+ // Captain takeover is scoped to the captain's current turn. Unlike a
370
+ // durable member, the captain has no scheduler lane that can resume an
371
+ // abandoned attempt later. Returning unfinished captain-owned work to
372
+ // the shared pool on the idle edge prevents it from becoming a
373
+ // permanently parked `claimed` task after the captain answers, is
374
+ // interrupted, or the user switches conversations.
375
+ if (status === 'running')
376
+ return;
377
+ let requeued = false;
378
+ await withTeamLock(teamLockKey(stateRoot, located.id), async () => {
379
+ const fresh = await readTeam(stateRoot, located.id);
380
+ if (fresh === undefined || fresh.captainSessionId !== agent.id)
381
+ return;
382
+ for (const task of fresh.tasks) {
383
+ if (task.assignee !== CAPTAIN_KEY
384
+ || task.status === 'completed'
385
+ || task.status === 'failed'
386
+ || task.status === 'cancelled')
387
+ continue;
388
+ invalidateTaskAttempt(task);
389
+ task.reassigning = false;
390
+ requeued = true;
391
+ }
392
+ if (requeued)
393
+ await writeTeam(stateRoot, fresh);
394
+ });
395
+ if (requeued)
396
+ await runtime.kickTeam(workspace, located.id, agent);
397
+ return;
398
+ }
399
+ const member = located.members.find(candidate => candidate.id === agent.id && candidate.status !== 'removed');
400
+ if (member === undefined) {
401
+ parkedAttempts.delete(agent.id);
402
+ return;
403
+ }
404
+ await withTeamLock(teamLockKey(stateRoot, located.id), async () => {
405
+ const fresh = await readTeam(stateRoot, located.id);
406
+ const current = fresh?.members.find(candidate => candidate.id === agent.id && candidate.status !== 'removed');
407
+ if (fresh === undefined || current === undefined)
408
+ return;
409
+ const next = status === 'running' ? 'working' : 'idle';
410
+ if (next === 'idle') {
411
+ const owned = ownedOpenTask(fresh.tasks, current.name);
412
+ if (owned?.attemptId === undefined)
413
+ parkedAttempts.delete(agent.id);
414
+ else
415
+ parkedAttempts.set(agent.id, owned.attemptId);
416
+ }
417
+ else {
418
+ parkedAttempts.delete(agent.id);
419
+ }
420
+ if (current.status === next)
421
+ return;
422
+ current.status = next;
423
+ await writeTeam(stateRoot, fresh);
424
+ });
425
+ if (status === 'idle')
426
+ await runtime.kickMember(workspace, located.id, member.name);
427
+ };
428
+ ctx.on('agent/status', ({ agent, status }) => {
429
+ void syncMemberStatus(agent, status).catch((error) => {
430
+ ctx.logger.warn(`t-team: member status scheduling failed for ${agent.id}: ${String(error)}`);
431
+ });
432
+ });
433
+ return runtime;
434
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Team activity snapshot assembly for the activity panel.
3
+ *
4
+ * Server-side assembly mirrors the Claude Code desktop teamWatcher: read the
5
+ * durable team files (the truth source) and enrich with live subagent
6
+ * activity, so the panel always reflects the on-disk state even when a model
7
+ * skipped a tool "ritual" (e.g. not calling update_task on completion).
8
+ * @module t-team/snapshot
9
+ */
10
+ import { readdir } from 'node:fs/promises';
11
+ import { join } from 'node:path';
12
+ import { memberActivity } from "./members.js";
13
+ import { CAPTAIN_KEY, listArchivedTeamIds, readArchivedTeam, readUnreadMailbox, readTeam, taskDepthsById, taskVisualState, } from "./state.js";
14
+ /** The current task of a member: its first unfinished owned task. */
15
+ function currentTaskOf(memberName, tasks) {
16
+ for (const task of tasks) {
17
+ if (task.status === 'in_progress' && task.assignee === memberName)
18
+ return task.id;
19
+ }
20
+ return '';
21
+ }
22
+ /** Compact `provider/model` route for the activity panel, or just the model. */
23
+ export function memberModelRoute(member) {
24
+ if (member === undefined)
25
+ return '';
26
+ const provider = member.provider?.trim() ?? '';
27
+ const model = member.model?.trim() ?? '';
28
+ if (provider !== '' && model !== '')
29
+ return `${provider}/${model}`;
30
+ return model;
31
+ }
32
+ /**
33
+ * Assemble one team snapshot from its durable files plus live activity.
34
+ * @param ctx - the plugin context (injects `subagents`, used for activity).
35
+ * @param stateRoot - resolved absolute state root of the owning workspace.
36
+ * @param workspace - display name of the owning workspace.
37
+ * @param state - the durable team record.
38
+ * @returns the panel snapshot.
39
+ */
40
+ export async function assembleTeamSnapshot(ctx, stateRoot, workspace, state, options = {}) {
41
+ const tasks = state.tasks;
42
+ const depths = taskDepthsById(tasks);
43
+ const roster = options.includeRemoved === true
44
+ ? state.members
45
+ : state.members.filter((member) => member.status !== 'removed');
46
+ const activity = options.historic === true
47
+ ? new Map()
48
+ : memberActivity(ctx, roster.map((member) => member.id));
49
+ const unreadByMember = new Map();
50
+ for (const member of roster) {
51
+ try {
52
+ unreadByMember.set(member.name, (await readUnreadMailbox(stateRoot, state.id, member.name)).length);
53
+ }
54
+ catch (error) {
55
+ ctx.logger.warn(`t-team: mailbox read failed for ${member.name}: ${String(error)}`);
56
+ unreadByMember.set(member.name, 0);
57
+ }
58
+ }
59
+ const members = roster.map((member) => {
60
+ const owned = tasks.filter((task) => task.assignee === member.name);
61
+ const done = owned.filter((task) => task.status === 'completed').length;
62
+ return {
63
+ id: member.id,
64
+ name: member.name,
65
+ role: member.role ?? '',
66
+ provider: member.provider?.trim() ?? '',
67
+ model: member.model?.trim() ?? '',
68
+ reasoningEffort: member.reasoningEffort?.trim() ?? '',
69
+ executionPrompt: member.executionPrompt ?? '',
70
+ status: member.status,
71
+ activity: options.historic === true
72
+ ? 'idle'
73
+ : member.id !== ''
74
+ ? (activity.get(member.id) === 'running'
75
+ ? 'working'
76
+ : activity.get(member.id) === 'idle' || activity.get(member.id) === 'ready'
77
+ ? 'idle'
78
+ : 'unknown')
79
+ : state.phase === 'staged' ? 'idle' : 'unknown',
80
+ progress: owned.length === 0 ? 0 : Math.round((done / owned.length) * 100),
81
+ done,
82
+ total: owned.length,
83
+ currentTask: currentTaskOf(member.name, tasks),
84
+ unread: unreadByMember.get(member.name) ?? 0,
85
+ };
86
+ });
87
+ const captainInbox = await readUnreadMailbox(stateRoot, state.id, CAPTAIN_KEY);
88
+ return {
89
+ workspace,
90
+ teamId: state.id,
91
+ name: state.name,
92
+ ...state.description !== undefined ? { description: state.description } : {},
93
+ captainSessionId: state.captainSessionId,
94
+ phase: state.phase ?? 'running',
95
+ ...state.phase === 'staged'
96
+ ? { planReviewState: state.planReviewState ?? 'awaiting_review' }
97
+ : {},
98
+ ...state.halted === true ? { halted: true } : {},
99
+ members,
100
+ tasks: tasks.map((task) => ({
101
+ id: task.id,
102
+ subject: task.subject,
103
+ description: task.description ?? '',
104
+ status: task.status,
105
+ state: taskVisualState(task.status, task.dependencies, tasks),
106
+ assignee: task.assignee ?? '',
107
+ model: memberModelRoute(roster.find((member) => member.name === task.assignee)),
108
+ dependencies: task.dependencies,
109
+ depth: depths.get(task.id) ?? 0,
110
+ ...task.kind === undefined ? {} : { kind: task.kind },
111
+ ...task.round === undefined ? {} : { round: task.round },
112
+ ...task.verdict === undefined ? {} : { verdict: task.verdict },
113
+ })),
114
+ messageCount: captainInbox.length
115
+ + members.reduce((count, member) => count + member.unread, 0),
116
+ captainInbox: captainInbox.slice(-5).map((message) => ({
117
+ from: message.from,
118
+ content: message.content,
119
+ })),
120
+ };
121
+ }
122
+ /**
123
+ * Collect every team under the given workspace state roots.
124
+ * @param ctx - the plugin context.
125
+ * @param roots - `{ workspace, stateRoot }` pairs (resolved absolute roots).
126
+ * @returns the snapshots in stable order (workspace, then team id).
127
+ */
128
+ export async function collectTeamsActivity(ctx, roots) {
129
+ const snapshots = [];
130
+ for (const root of roots) {
131
+ let entries;
132
+ try {
133
+ entries = await readdir(root.stateRoot, { withFileTypes: true });
134
+ }
135
+ catch (error) {
136
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
137
+ continue;
138
+ }
139
+ throw error;
140
+ }
141
+ for (const entry of entries) {
142
+ if (!entry.isDirectory())
143
+ continue;
144
+ try {
145
+ const state = await readTeam(root.stateRoot, entry.name);
146
+ if (state === undefined)
147
+ continue;
148
+ snapshots.push(await assembleTeamSnapshot(ctx, root.stateRoot, root.workspace, state));
149
+ }
150
+ catch {
151
+ ctx.logger.warn(`t-team: skipped unreadable team state "${entry.name}" in workspace "${root.workspace}"`);
152
+ }
153
+ }
154
+ }
155
+ return snapshots;
156
+ }
157
+ /**
158
+ * Collect every archived team under the given workspace state roots (the
159
+ * `archive/` subdirectory of each state root). Used by the historic panel
160
+ * path to restore full team detail after deletion.
161
+ * @param ctx - the plugin context.
162
+ * @param roots - `{ workspace, stateRoot }` pairs.
163
+ * @returns the archived snapshots in stable order.
164
+ */
165
+ export async function collectArchivedTeamsActivity(ctx, roots) {
166
+ const snapshots = [];
167
+ for (const root of roots) {
168
+ for (const teamId of await listArchivedTeamIds(root.stateRoot)) {
169
+ try {
170
+ const state = await readArchivedTeam(root.stateRoot, teamId);
171
+ if (state === undefined)
172
+ continue;
173
+ snapshots.push(await assembleTeamSnapshot(ctx, join(root.stateRoot, 'archive'), root.workspace, state, { includeRemoved: true, historic: true }));
174
+ }
175
+ catch {
176
+ ctx.logger.warn(`t-team: skipped unreadable archived team "${teamId}" in workspace "${root.workspace}"`);
177
+ }
178
+ }
179
+ }
180
+ return snapshots;
181
+ }