timsquad 3.5.0 → 3.7.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 (454) hide show
  1. package/README.ko.md +103 -107
  2. package/README.md +100 -104
  3. package/dist/commands/daemon.d.ts.map +1 -1
  4. package/dist/commands/daemon.js +48 -2
  5. package/dist/commands/daemon.js.map +1 -1
  6. package/dist/commands/init.js +46 -14
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/{upgrade.d.ts → update.d.ts} +3 -3
  9. package/dist/commands/update.d.ts.map +1 -0
  10. package/dist/commands/{upgrade.js → update.js} +12 -17
  11. package/dist/commands/update.js.map +1 -0
  12. package/dist/daemon/context-writer.d.ts +14 -0
  13. package/dist/daemon/context-writer.d.ts.map +1 -1
  14. package/dist/daemon/context-writer.js +29 -0
  15. package/dist/daemon/context-writer.js.map +1 -1
  16. package/dist/daemon/event-queue.d.ts +7 -11
  17. package/dist/daemon/event-queue.d.ts.map +1 -1
  18. package/dist/daemon/event-queue.js +78 -118
  19. package/dist/daemon/event-queue.js.map +1 -1
  20. package/dist/daemon/file-watcher.d.ts +14 -8
  21. package/dist/daemon/file-watcher.d.ts.map +1 -1
  22. package/dist/daemon/file-watcher.js +78 -41
  23. package/dist/daemon/file-watcher.js.map +1 -1
  24. package/dist/daemon/index.d.ts +1 -1
  25. package/dist/daemon/index.d.ts.map +1 -1
  26. package/dist/daemon/index.js +54 -47
  27. package/dist/daemon/index.js.map +1 -1
  28. package/dist/index.js +3 -41
  29. package/dist/index.js.map +1 -1
  30. package/dist/lib/agent-generator.d.ts.map +1 -1
  31. package/dist/lib/agent-generator.js +21 -10
  32. package/dist/lib/agent-generator.js.map +1 -1
  33. package/dist/lib/compile-rules.d.ts +2 -0
  34. package/dist/lib/compile-rules.d.ts.map +1 -1
  35. package/dist/lib/compile-rules.js +39 -4
  36. package/dist/lib/compile-rules.js.map +1 -1
  37. package/dist/lib/compiler.d.ts +22 -1
  38. package/dist/lib/compiler.d.ts.map +1 -1
  39. package/dist/lib/compiler.js +178 -12
  40. package/dist/lib/compiler.js.map +1 -1
  41. package/dist/lib/config.d.ts +3 -0
  42. package/dist/lib/config.d.ts.map +1 -1
  43. package/dist/lib/config.js +17 -2
  44. package/dist/lib/config.js.map +1 -1
  45. package/dist/{commands/log.d.ts → lib/log-utils.d.ts} +7 -15
  46. package/dist/lib/log-utils.d.ts.map +1 -0
  47. package/dist/lib/log-utils.js +347 -0
  48. package/dist/lib/log-utils.js.map +1 -0
  49. package/dist/lib/skill-generator.d.ts +1 -1
  50. package/dist/lib/skill-generator.d.ts.map +1 -1
  51. package/dist/lib/skill-generator.js +19 -44
  52. package/dist/lib/skill-generator.js.map +1 -1
  53. package/dist/lib/ssot-map.d.ts +31 -0
  54. package/dist/lib/ssot-map.d.ts.map +1 -0
  55. package/dist/lib/ssot-map.js +79 -0
  56. package/dist/lib/ssot-map.js.map +1 -0
  57. package/dist/lib/template.d.ts +10 -3
  58. package/dist/lib/template.d.ts.map +1 -1
  59. package/dist/lib/template.js +137 -22
  60. package/dist/lib/template.js.map +1 -1
  61. package/dist/lib/upgrade-backup.js +1 -1
  62. package/dist/lib/upgrade-backup.js.map +1 -1
  63. package/dist/lib/workflow-state.d.ts +1 -1
  64. package/dist/lib/workflow-state.d.ts.map +1 -1
  65. package/dist/lib/workflow-state.js +1 -1
  66. package/dist/lib/workflow-state.js.map +1 -1
  67. package/dist/types/config.d.ts +10 -1
  68. package/dist/types/config.d.ts.map +1 -1
  69. package/dist/types/config.js +46 -41
  70. package/dist/types/config.js.map +1 -1
  71. package/dist/types/feedback.d.ts +1 -54
  72. package/dist/types/feedback.d.ts.map +1 -1
  73. package/dist/types/feedback.js +1 -22
  74. package/dist/types/feedback.js.map +1 -1
  75. package/dist/types/index.d.ts +1 -0
  76. package/dist/types/index.d.ts.map +1 -1
  77. package/dist/types/index.js +1 -0
  78. package/dist/types/index.js.map +1 -1
  79. package/dist/types/meta-index.d.ts +8 -0
  80. package/dist/types/meta-index.d.ts.map +1 -1
  81. package/dist/types/project.d.ts +6 -1
  82. package/dist/types/project.d.ts.map +1 -1
  83. package/dist/types/project.js +15 -0
  84. package/dist/types/project.js.map +1 -1
  85. package/dist/types/ssot-map.d.ts +30 -0
  86. package/dist/types/ssot-map.d.ts.map +1 -0
  87. package/dist/types/ssot-map.js +6 -0
  88. package/dist/types/ssot-map.js.map +1 -0
  89. package/package.json +1 -1
  90. package/templates/base/agents/base/tsq-architect.md +1 -1
  91. package/templates/base/agents/base/tsq-dba.md +3 -1
  92. package/templates/base/agents/base/tsq-designer.md +3 -1
  93. package/templates/base/agents/base/tsq-developer.md +3 -1
  94. package/templates/base/agents/base/tsq-librarian.md +45 -0
  95. package/templates/base/agents/base/tsq-qa.md +3 -1
  96. package/templates/base/agents/base/tsq-security.md +3 -1
  97. package/templates/base/agents/overlays/platform/claude-code.md +2 -2
  98. package/templates/base/config.template.yaml +17 -28
  99. package/templates/base/knowledge/templates/task-result.md +5 -10
  100. package/templates/base/skills/_shared/naming-conventions.md +49 -0
  101. package/templates/base/skills/_template/SKILL.md +31 -17
  102. package/templates/base/skills/{architecture → tsq-architecture}/SKILL.md +2 -2
  103. package/templates/base/skills/tsq-audit/SKILL.md +74 -0
  104. package/templates/base/skills/{methodology/bdd → tsq-bdd}/SKILL.md +14 -9
  105. package/templates/base/skills/tsq-coding/SKILL.md +65 -0
  106. package/templates/base/skills/tsq-coding/rules/async-patterns.md +81 -0
  107. package/templates/base/skills/tsq-coding/rules/code-organization.md +80 -0
  108. package/templates/base/skills/tsq-coding/rules/error-handling.md +76 -0
  109. package/templates/base/skills/tsq-coding/rules/type-safety.md +85 -0
  110. package/templates/base/skills/tsq-controller/SKILL.md +81 -0
  111. package/templates/base/skills/tsq-controller/memory/.gitkeep +0 -0
  112. package/templates/base/skills/{mobile/dart → tsq-dart}/SKILL.md +5 -3
  113. package/templates/base/skills/{database → tsq-database}/SKILL.md +13 -27
  114. package/templates/base/skills/tsq-database/rules/query-optimization.md +32 -0
  115. package/templates/base/skills/tsq-database/rules/supabase-patterns.md +94 -0
  116. package/templates/base/skills/{methodology/ddd → tsq-ddd}/SKILL.md +15 -10
  117. package/templates/base/skills/{methodology/debugging → tsq-debugging}/SKILL.md +2 -2
  118. package/templates/base/skills/tsq-decompose/SKILL.md +117 -0
  119. package/templates/base/skills/tsq-delete/SKILL.md +72 -0
  120. package/templates/base/skills/{mobile/flutter → tsq-flutter}/SKILL.md +6 -3
  121. package/templates/base/skills/tsq-grill/SKILL.md +86 -0
  122. package/templates/base/skills/{backend/node → tsq-hono}/SKILL.md +6 -4
  123. package/templates/base/skills/tsq-librarian/SKILL.md +78 -0
  124. package/templates/base/skills/tsq-log/SKILL.md +30 -0
  125. package/templates/base/skills/{frontend/nextjs → tsq-nextjs}/SKILL.md +14 -9
  126. package/templates/base/skills/{planning → tsq-planning}/SKILL.md +2 -2
  127. package/templates/base/skills/{database/prisma → tsq-prisma}/SKILL.md +15 -9
  128. package/templates/base/skills/tsq-product-audit/SKILL.md +113 -0
  129. package/templates/base/skills/tsq-product-audit/checklists/01-security.md +86 -0
  130. package/templates/base/skills/tsq-product-audit/checklists/02-performance.md +67 -0
  131. package/templates/base/skills/tsq-product-audit/checklists/03-seo.md +46 -0
  132. package/templates/base/skills/tsq-product-audit/checklists/04-accessibility.md +66 -0
  133. package/templates/base/skills/tsq-product-audit/checklists/05-ui-ux.md +50 -0
  134. package/templates/base/skills/tsq-product-audit/checklists/06-architecture.md +53 -0
  135. package/templates/base/skills/tsq-product-audit/checklists/07-functional-requirements.md +55 -0
  136. package/templates/base/skills/tsq-product-audit/rules/audit-protocol.md +136 -0
  137. package/templates/base/skills/tsq-product-audit/rules/false-positive-guard.md +81 -0
  138. package/templates/base/skills/tsq-product-audit/rules/scoring-criteria.md +113 -0
  139. package/templates/base/skills/tsq-product-audit/templates/improvement-plan-template.md +60 -0
  140. package/templates/base/skills/tsq-product-audit/templates/report-template.md +88 -0
  141. package/templates/base/skills/tsq-prompt/SKILL.md +86 -0
  142. package/templates/base/skills/tsq-protocol/SKILL.md +101 -33
  143. package/templates/base/skills/{frontend/react → tsq-react}/SKILL.md +6 -3
  144. package/templates/base/skills/tsq-retro/SKILL.md +86 -0
  145. package/templates/base/skills/tsq-retro/references/feedback-guide.md +58 -0
  146. package/templates/base/skills/tsq-retro/references/improve-protocol.md +87 -0
  147. package/templates/base/skills/tsq-retro/references/improvement-template.md +26 -0
  148. package/templates/base/skills/tsq-security/SKILL.md +66 -0
  149. package/templates/base/skills/tsq-security/rules/auth-patterns.md +62 -0
  150. package/templates/base/skills/tsq-security/rules/dependency-security.md +69 -0
  151. package/templates/base/skills/tsq-security/rules/input-validation.md +68 -0
  152. package/templates/base/skills/tsq-security/rules/secrets-management.md +65 -0
  153. package/templates/base/skills/tsq-spec/SKILL.md +58 -0
  154. package/templates/base/skills/{stability-verification → tsq-stability}/SKILL.md +3 -3
  155. package/templates/base/skills/tsq-start/SKILL.md +90 -0
  156. package/templates/base/skills/tsq-start/references/onboarding-questions.md +177 -0
  157. package/templates/base/skills/tsq-status/SKILL.md +32 -0
  158. package/templates/base/skills/{methodology/tdd → tsq-tdd}/SKILL.md +12 -3
  159. package/templates/base/skills/tsq-testing/SKILL.md +69 -0
  160. package/templates/base/skills/tsq-testing/references/e2e-stability.md +33 -0
  161. package/templates/base/skills/{typescript → tsq-typescript}/SKILL.md +5 -11
  162. package/templates/base/skills/{ui-design → tsq-ui}/SKILL.md +2 -2
  163. package/templates/base/skills/tsq-update/SKILL.md +48 -0
  164. package/templates/base/timsquad/constraints/competency-framework.xml +2 -2
  165. package/templates/base/timsquad/constraints/ssot-schema.xml +2 -2
  166. package/templates/base/timsquad/process/phase-checklist.yaml +1 -1
  167. package/templates/base/timsquad/process/state-machine.xml +2 -2
  168. package/templates/base/timsquad/process/validation-rules.xml +8 -8
  169. package/templates/base/timsquad/process/workflow-base.xml +8 -8
  170. package/templates/base/timsquad/retrospective/cycle-report.template.md +2 -2
  171. package/templates/base/timsquad/retrospective/patterns/failure-patterns.md +1 -1
  172. package/templates/base/timsquad/retrospective/patterns/success-patterns.md +2 -2
  173. package/templates/base/timsquad/retrospective/retrospective-state.xml +2 -2
  174. package/templates/base/timsquad/ssot/audit-trail-spec.template.md +155 -0
  175. package/templates/base/timsquad/ssot/compliance-matrix.template.md +105 -0
  176. package/templates/base/timsquad/ssot/component-map.template.md +181 -0
  177. package/templates/base/timsquad/ssot/data-design.template.md +4 -4
  178. package/templates/base/timsquad/ssot/deployment-spec.template.md +29 -22
  179. package/templates/base/timsquad/ssot/env-config.template.md +4 -2
  180. package/templates/base/timsquad/ssot/error-codes.template.md +3 -3
  181. package/templates/base/timsquad/ssot/functional-spec.template.md +40 -3
  182. package/templates/base/timsquad/ssot/glossary.template.md +2 -2
  183. package/templates/base/timsquad/ssot/infra-topology.template.md +191 -0
  184. package/templates/base/timsquad/ssot/integration-spec.template.md +2 -2
  185. package/templates/base/timsquad/ssot/monitoring-spec.template.md +185 -0
  186. package/templates/base/timsquad/ssot/navigation-map.template.md +154 -0
  187. package/templates/base/timsquad/ssot/performance-budget.template.md +132 -0
  188. package/templates/base/timsquad/ssot/planning.template.md +3 -3
  189. package/templates/base/timsquad/ssot/prd/_template.md +73 -0
  190. package/templates/base/timsquad/ssot/prd.template.md +10 -21
  191. package/templates/base/timsquad/ssot/requirements.template.md +3 -3
  192. package/templates/base/timsquad/ssot/sdk-spec.template.md +223 -0
  193. package/templates/base/timsquad/ssot/service-spec.template.md +3 -3
  194. package/templates/base/timsquad/ssot/state-machine.template.md +127 -0
  195. package/templates/base/timsquad/ssot/test-spec.template.md +11 -1
  196. package/templates/base/timsquad/ssot/ui-ux-spec.template.md +43 -3
  197. package/templates/base/timsquad/ssot-map.template.yaml +69 -0
  198. package/templates/base/timsquad/state/workspace.xml +11 -11
  199. package/templates/platforms/claude-code/rules/adr-rules.md +1 -1
  200. package/templates/platforms/claude-code/rules/api-conventions.md +12 -0
  201. package/templates/platforms/claude-code/rules/build-gate.md +1 -1
  202. package/templates/platforms/claude-code/rules/completion-verification.md +0 -2
  203. package/templates/platforms/claude-code/rules/context-monitor.md +1 -1
  204. package/templates/platforms/claude-code/rules/feedback-routing.md +2 -2
  205. package/templates/platforms/claude-code/rules/librarian-constraints.md +11 -0
  206. package/templates/platforms/claude-code/rules/phase-management.md +2 -2
  207. package/templates/platforms/claude-code/rules/plan-review.md +2 -2
  208. package/templates/platforms/claude-code/rules/quality-guards.md +0 -2
  209. package/templates/platforms/claude-code/rules/sequence-management.md +15 -15
  210. package/templates/platforms/claude-code/rules/session-notes.md +1 -1
  211. package/templates/platforms/claude-code/rules/test-conventions.md +13 -0
  212. package/templates/platforms/claude-code/rules/workspace-sync.md +1 -1
  213. package/templates/platforms/claude-code/scripts/build-gate.sh +6 -1
  214. package/templates/platforms/claude-code/scripts/change-scope-guard.sh +110 -0
  215. package/templates/platforms/claude-code/scripts/check-capability.sh +68 -0
  216. package/templates/platforms/claude-code/scripts/completion-guard.sh +134 -14
  217. package/templates/platforms/claude-code/scripts/context-restore.sh +95 -0
  218. package/templates/platforms/claude-code/scripts/e2e-commit-gate.sh +70 -0
  219. package/templates/platforms/claude-code/scripts/e2e-marker.sh +51 -0
  220. package/templates/platforms/claude-code/scripts/phase-guard.sh +3 -6
  221. package/templates/platforms/claude-code/scripts/pre-compact.sh +70 -0
  222. package/templates/platforms/claude-code/scripts/safe-guard.sh +2 -5
  223. package/templates/platforms/claude-code/scripts/subagent-start.sh +11 -0
  224. package/templates/platforms/claude-code/scripts/subagent-stop.sh +11 -0
  225. package/templates/platforms/claude-code/settings.json +28 -56
  226. package/templates/project-types/api-backend/config.yaml +9 -5
  227. package/templates/project-types/api-backend/process/workflow.xml +2 -2
  228. package/templates/project-types/fintech/config.yaml +13 -19
  229. package/templates/project-types/fintech/ssot/audit-trail-spec.template.md +207 -0
  230. package/templates/project-types/fintech/ssot/compliance-matrix.template.md +187 -0
  231. package/templates/project-types/infra/config.yaml +7 -4
  232. package/templates/project-types/infra/process/workflow.xml +3 -3
  233. package/templates/project-types/mobile-app/config.yaml +8 -14
  234. package/templates/project-types/mobile-app/process/workflow.xml +4 -4
  235. package/templates/project-types/platform/config.yaml +8 -5
  236. package/templates/project-types/platform/process/workflow.xml +3 -3
  237. package/templates/project-types/web-app/config.yaml +9 -15
  238. package/templates/project-types/web-app/process/workflow.xml +6 -6
  239. package/templates/project-types/web-service/config.yaml +10 -19
  240. package/templates/project-types/web-service/process/workflow.xml +6 -6
  241. package/dist/commands/compile.d.ts +0 -3
  242. package/dist/commands/compile.d.ts.map +0 -1
  243. package/dist/commands/compile.js +0 -170
  244. package/dist/commands/compile.js.map +0 -1
  245. package/dist/commands/feedback.d.ts +0 -12
  246. package/dist/commands/feedback.d.ts.map +0 -1
  247. package/dist/commands/feedback.js +0 -382
  248. package/dist/commands/feedback.js.map +0 -1
  249. package/dist/commands/full.d.ts +0 -3
  250. package/dist/commands/full.d.ts.map +0 -1
  251. package/dist/commands/full.js +0 -88
  252. package/dist/commands/full.js.map +0 -1
  253. package/dist/commands/git/commit.d.ts +0 -3
  254. package/dist/commands/git/commit.d.ts.map +0 -1
  255. package/dist/commands/git/commit.js +0 -85
  256. package/dist/commands/git/commit.js.map +0 -1
  257. package/dist/commands/git/index.d.ts +0 -5
  258. package/dist/commands/git/index.d.ts.map +0 -1
  259. package/dist/commands/git/index.js +0 -5
  260. package/dist/commands/git/index.js.map +0 -1
  261. package/dist/commands/git/pr.d.ts +0 -3
  262. package/dist/commands/git/pr.d.ts.map +0 -1
  263. package/dist/commands/git/pr.js +0 -139
  264. package/dist/commands/git/pr.js.map +0 -1
  265. package/dist/commands/git/release.d.ts +0 -3
  266. package/dist/commands/git/release.d.ts.map +0 -1
  267. package/dist/commands/git/release.js +0 -153
  268. package/dist/commands/git/release.js.map +0 -1
  269. package/dist/commands/git/sync.d.ts +0 -3
  270. package/dist/commands/git/sync.d.ts.map +0 -1
  271. package/dist/commands/git/sync.js +0 -132
  272. package/dist/commands/git/sync.js.map +0 -1
  273. package/dist/commands/improve.d.ts +0 -3
  274. package/dist/commands/improve.d.ts.map +0 -1
  275. package/dist/commands/improve.js +0 -286
  276. package/dist/commands/improve.js.map +0 -1
  277. package/dist/commands/knowledge.d.ts +0 -3
  278. package/dist/commands/knowledge.d.ts.map +0 -1
  279. package/dist/commands/knowledge.js +0 -316
  280. package/dist/commands/knowledge.js.map +0 -1
  281. package/dist/commands/log.d.ts.map +0 -1
  282. package/dist/commands/log.js +0 -1436
  283. package/dist/commands/log.js.map +0 -1
  284. package/dist/commands/meta-index.d.ts +0 -3
  285. package/dist/commands/meta-index.d.ts.map +0 -1
  286. package/dist/commands/meta-index.js +0 -401
  287. package/dist/commands/meta-index.js.map +0 -1
  288. package/dist/commands/metrics.d.ts +0 -3
  289. package/dist/commands/metrics.d.ts.map +0 -1
  290. package/dist/commands/metrics.js +0 -843
  291. package/dist/commands/metrics.js.map +0 -1
  292. package/dist/commands/quick.d.ts +0 -3
  293. package/dist/commands/quick.d.ts.map +0 -1
  294. package/dist/commands/quick.js +0 -136
  295. package/dist/commands/quick.js.map +0 -1
  296. package/dist/commands/retro.d.ts +0 -3
  297. package/dist/commands/retro.d.ts.map +0 -1
  298. package/dist/commands/retro.js +0 -828
  299. package/dist/commands/retro.js.map +0 -1
  300. package/dist/commands/session.d.ts +0 -3
  301. package/dist/commands/session.d.ts.map +0 -1
  302. package/dist/commands/session.js +0 -346
  303. package/dist/commands/session.js.map +0 -1
  304. package/dist/commands/skills.d.ts +0 -12
  305. package/dist/commands/skills.d.ts.map +0 -1
  306. package/dist/commands/skills.js +0 -228
  307. package/dist/commands/skills.js.map +0 -1
  308. package/dist/commands/status.d.ts +0 -3
  309. package/dist/commands/status.d.ts.map +0 -1
  310. package/dist/commands/status.js +0 -127
  311. package/dist/commands/status.js.map +0 -1
  312. package/dist/commands/upgrade.d.ts.map +0 -1
  313. package/dist/commands/upgrade.js.map +0 -1
  314. package/dist/commands/watch.d.ts +0 -3
  315. package/dist/commands/watch.d.ts.map +0 -1
  316. package/dist/commands/watch.js +0 -213
  317. package/dist/commands/watch.js.map +0 -1
  318. package/dist/commands/workflow.d.ts +0 -3
  319. package/dist/commands/workflow.d.ts.map +0 -1
  320. package/dist/commands/workflow.js +0 -607
  321. package/dist/commands/workflow.js.map +0 -1
  322. package/templates/base/skills/coding/SKILL.md +0 -47
  323. package/templates/base/skills/controller/SKILL.md +0 -111
  324. package/templates/base/skills/prompt-engineering/SKILL.md +0 -103
  325. package/templates/base/skills/retrospective/SKILL.md +0 -102
  326. package/templates/base/skills/security/SKILL.md +0 -55
  327. package/templates/base/skills/testing/SKILL.md +0 -63
  328. package/templates/base/timsquad/feedback/feedback-router.sh +0 -341
  329. package/templates/base/timsquad/feedback/routing-rules.yaml +0 -352
  330. package/templates/platforms/claude-code/CLAUDE.md.template +0 -89
  331. package/templates/platforms/claude-code/rules/skill-suggest.md +0 -27
  332. package/templates/platforms/claude-code/scripts/skill-rules.json +0 -85
  333. package/templates/platforms/claude-code/scripts/skill-suggest.sh +0 -105
  334. /package/templates/base/skills/{architecture → tsq-architecture}/references/adr-template.md +0 -0
  335. /package/templates/base/skills/{architecture → tsq-architecture}/references/api-design.md +0 -0
  336. /package/templates/base/skills/{methodology/bdd → tsq-bdd}/rules/gherkin-patterns.md +0 -0
  337. /package/templates/base/skills/{coding → tsq-coding}/rules/patterns.md +0 -0
  338. /package/templates/base/skills/{controller → tsq-controller}/references/README.md +0 -0
  339. /package/templates/base/skills/{controller → tsq-controller}/rules/README.md +0 -0
  340. /package/templates/base/skills/{mobile/dart → tsq-dart}/rules/async-patterns.md +0 -0
  341. /package/templates/base/skills/{mobile/dart → tsq-dart}/rules/code-style.md +0 -0
  342. /package/templates/base/skills/{mobile/dart → tsq-dart}/rules/null-safety.md +0 -0
  343. /package/templates/base/skills/{mobile/dart → tsq-dart}/rules/type-system.md +0 -0
  344. /package/templates/base/skills/{methodology/ddd → tsq-ddd}/rules/strategic-patterns.md +0 -0
  345. /package/templates/base/skills/{methodology/debugging → tsq-debugging}/references/root-cause-tracing.md +0 -0
  346. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/SKILL.md +0 -0
  347. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/references/ci-cd-pipeline.md +0 -0
  348. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/rules/code-signing.md +0 -0
  349. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/rules/codemagic-setup.md +0 -0
  350. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/rules/fastlane-setup.md +0 -0
  351. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/rules/github-actions.md +0 -0
  352. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/rules/store-deployment.md +0 -0
  353. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/ci-cd/rules/versioning.md +0 -0
  354. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/i18n/SKILL.md +0 -0
  355. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/i18n/references/i18n-architecture.md +0 -0
  356. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/i18n/rules/arb-files.md +0 -0
  357. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/i18n/rules/locale-switching.md +0 -0
  358. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/i18n/rules/localization-setup.md +0 -0
  359. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/i18n/rules/plural-gender.md +0 -0
  360. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/i18n/rules/text-direction.md +0 -0
  361. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/monitoring/SKILL.md +0 -0
  362. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/monitoring/references/monitoring-architecture.md +0 -0
  363. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/monitoring/rules/analytics.md +0 -0
  364. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/monitoring/rules/crashlytics-setup.md +0 -0
  365. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/monitoring/rules/logging.md +0 -0
  366. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/monitoring/rules/performance-monitoring.md +0 -0
  367. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/monitoring/rules/sentry-integration.md +0 -0
  368. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/SKILL.md +0 -0
  369. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/references/api-client-architecture.md +0 -0
  370. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/rules/caching.md +0 -0
  371. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/rules/connectivity.md +0 -0
  372. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/rules/dio-setup.md +0 -0
  373. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/rules/error-handling.md +0 -0
  374. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/rules/interceptors.md +0 -0
  375. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/networking/rules/retrofit-patterns.md +0 -0
  376. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/SKILL.md +0 -0
  377. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/references/notification-architecture.md +0 -0
  378. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/references/platform-setup.md +0 -0
  379. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/rules/background-processing.md +0 -0
  380. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/rules/deep-linking.md +0 -0
  381. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/rules/fcm-setup.md +0 -0
  382. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/rules/local-notifications.md +0 -0
  383. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/rules/notification-handling.md +0 -0
  384. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/rules/notification-permissions.md +0 -0
  385. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/push-notifications/rules/rich-notifications.md +0 -0
  386. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/references/freezed-patterns.md +0 -0
  387. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/references/project-structure.md +0 -0
  388. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/animations.md +0 -0
  389. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/architecture.md +0 -0
  390. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/navigation-routing.md +0 -0
  391. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/performance.md +0 -0
  392. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/platform-adaptive.md +0 -0
  393. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/state-management.md +0 -0
  394. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/testing.md +0 -0
  395. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/rules/widget-conventions.md +0 -0
  396. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/SKILL.md +0 -0
  397. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/references/mobile-security-checklist.md +0 -0
  398. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/rules/api-key-protection.md +0 -0
  399. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/rules/authentication.md +0 -0
  400. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/rules/data-protection.md +0 -0
  401. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/rules/obfuscation.md +0 -0
  402. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/rules/secure-storage.md +0 -0
  403. /package/templates/base/skills/{mobile/flutter → tsq-flutter}/security/rules/ssl-pinning.md +0 -0
  404. /package/templates/base/skills/{backend/node → tsq-hono}/rules/async-patterns.md +0 -0
  405. /package/templates/base/skills/{backend/node → tsq-hono}/rules/deployment.md +0 -0
  406. /package/templates/base/skills/{backend/node → tsq-hono}/rules/env-config.md +0 -0
  407. /package/templates/base/skills/{backend/node → tsq-hono}/rules/error-handling.md +0 -0
  408. /package/templates/base/skills/{backend/node → tsq-hono}/rules/hono-app-setup.md +0 -0
  409. /package/templates/base/skills/{backend/node → tsq-hono}/rules/jwt-auth.md +0 -0
  410. /package/templates/base/skills/{backend/node → tsq-hono}/rules/middleware.md +0 -0
  411. /package/templates/base/skills/{backend/node → tsq-hono}/rules/testing.md +0 -0
  412. /package/templates/base/skills/{frontend/nextjs → tsq-nextjs}/rules/app-router.md +0 -0
  413. /package/templates/base/skills/{planning → tsq-planning}/references/prd-guide.md +0 -0
  414. /package/templates/base/skills/{planning → tsq-planning}/references/requirements-guide.md +0 -0
  415. /package/templates/base/skills/{database/prisma → tsq-prisma}/rules/queries.md +0 -0
  416. /package/templates/base/skills/{database/prisma → tsq-prisma}/rules/schema-design.md +0 -0
  417. /package/templates/base/skills/{frontend/react → tsq-react}/rules/_sections.md +0 -0
  418. /package/templates/base/skills/{frontend/react → tsq-react}/rules/anti-patterns.md +0 -0
  419. /package/templates/base/skills/{frontend/react → tsq-react}/rules/async-api-routes.md +0 -0
  420. /package/templates/base/skills/{frontend/react → tsq-react}/rules/async-defer-await.md +0 -0
  421. /package/templates/base/skills/{frontend/react → tsq-react}/rules/async-dependencies.md +0 -0
  422. /package/templates/base/skills/{frontend/react → tsq-react}/rules/async-parallel.md +0 -0
  423. /package/templates/base/skills/{frontend/react → tsq-react}/rules/async-suspense-boundaries.md +0 -0
  424. /package/templates/base/skills/{frontend/react → tsq-react}/rules/bundle-barrel-imports.md +0 -0
  425. /package/templates/base/skills/{frontend/react → tsq-react}/rules/bundle-defer-third-party.md +0 -0
  426. /package/templates/base/skills/{frontend/react → tsq-react}/rules/bundle-dynamic-imports.md +0 -0
  427. /package/templates/base/skills/{frontend/react → tsq-react}/rules/component-conventions.md +0 -0
  428. /package/templates/base/skills/{frontend/react → tsq-react}/rules/js-combine-iterations.md +0 -0
  429. /package/templates/base/skills/{frontend/react → tsq-react}/rules/js-early-exit.md +0 -0
  430. /package/templates/base/skills/{frontend/react → tsq-react}/rules/js-index-maps.md +0 -0
  431. /package/templates/base/skills/{frontend/react → tsq-react}/rules/js-set-map-lookups.md +0 -0
  432. /package/templates/base/skills/{frontend/react → tsq-react}/rules/rendering-conditional-render.md +0 -0
  433. /package/templates/base/skills/{frontend/react → tsq-react}/rules/rendering-content-visibility.md +0 -0
  434. /package/templates/base/skills/{frontend/react → tsq-react}/rules/rendering-hoist-jsx.md +0 -0
  435. /package/templates/base/skills/{frontend/react → tsq-react}/rules/rerender-defer-reads.md +0 -0
  436. /package/templates/base/skills/{frontend/react → tsq-react}/rules/rerender-derived-state.md +0 -0
  437. /package/templates/base/skills/{frontend/react → tsq-react}/rules/rerender-memo.md +0 -0
  438. /package/templates/base/skills/{frontend/react → tsq-react}/rules/rerender-transitions.md +0 -0
  439. /package/templates/base/skills/{frontend/react → tsq-react}/rules/server-after-nonblocking.md +0 -0
  440. /package/templates/base/skills/{frontend/react → tsq-react}/rules/server-cache-react.md +0 -0
  441. /package/templates/base/skills/{frontend/react → tsq-react}/rules/server-parallel-fetching.md +0 -0
  442. /package/templates/base/skills/{frontend/react → tsq-react}/rules/state-location.md +0 -0
  443. /package/templates/base/skills/{security → tsq-security}/rules/owasp-examples.md +0 -0
  444. /package/templates/base/skills/{security → tsq-security}/scripts/check-secrets.sh +0 -0
  445. /package/templates/base/skills/{stability-verification → tsq-stability}/references/release-checklist.md +0 -0
  446. /package/templates/base/skills/{stability-verification → tsq-stability}/references/security-fix-patterns.md +0 -0
  447. /package/templates/base/skills/{stability-verification → tsq-stability}/rules/verification-layers.md +0 -0
  448. /package/templates/base/skills/{stability-verification → tsq-stability}/rules/verification-workflow.md +0 -0
  449. /package/templates/base/skills/{stability-verification → tsq-stability}/scripts/verify.sh +0 -0
  450. /package/templates/base/skills/{methodology/tdd → tsq-tdd}/rules/real-world-example.md +0 -0
  451. /package/templates/base/skills/{methodology/tdd → tsq-tdd}/rules/techniques.md +0 -0
  452. /package/templates/base/skills/{testing → tsq-testing}/references/testing-patterns.md +0 -0
  453. /package/templates/base/skills/{typescript → tsq-typescript}/rules/type-patterns.md +0 -0
  454. /package/templates/base/skills/{typescript → tsq-typescript}/rules/utility-types.md +0 -0
@@ -1,828 +0,0 @@
1
- import path from 'path';
2
- import fs from 'fs-extra';
3
- import { execSync, execFileSync } from 'child_process';
4
- import { colors, printHeader, printError, printSuccess, printKeyValue } from '../utils/colors.js';
5
- import { findProjectRoot, getProjectInfo } from '../lib/project.js';
6
- import { exists, writeFile, listFiles } from '../utils/fs.js';
7
- import { getTimestamp, getDateString } from '../utils/date.js';
8
- import { promptText, promptConfirm } from '../utils/prompts.js';
9
- export function registerRetroCommand(program) {
10
- const retroCmd = program
11
- .command('retro')
12
- .description('Retrospective learning system');
13
- // tsq retro phase <phase-name>
14
- retroCmd
15
- .command('phase <phase>')
16
- .description('Run phase-level retrospective (saves locally)')
17
- .action(async (phase) => {
18
- try {
19
- await runPhaseRetro(phase);
20
- }
21
- catch (error) {
22
- printError(error.message);
23
- process.exit(1);
24
- }
25
- });
26
- // tsq retro start
27
- retroCmd
28
- .command('start')
29
- .description('Start a new retrospective cycle')
30
- .action(async () => {
31
- try {
32
- await startRetro();
33
- }
34
- catch (error) {
35
- printError(error.message);
36
- process.exit(1);
37
- }
38
- });
39
- // tsq retro collect
40
- retroCmd
41
- .command('collect')
42
- .description('Collect logs and metrics')
43
- .action(async () => {
44
- try {
45
- await collectRetro();
46
- }
47
- catch (error) {
48
- printError(error.message);
49
- process.exit(1);
50
- }
51
- });
52
- // tsq retro analyze
53
- retroCmd
54
- .command('analyze')
55
- .description('Analyze patterns (requires Claude)')
56
- .action(async () => {
57
- try {
58
- await analyzeRetro();
59
- }
60
- catch (error) {
61
- printError(error.message);
62
- process.exit(1);
63
- }
64
- });
65
- // tsq retro report
66
- retroCmd
67
- .command('report')
68
- .description('Generate aggregated report + create GitHub Issue')
69
- .option('--local', 'Skip GitHub Issue creation')
70
- .action(async (options) => {
71
- try {
72
- await generateReport(options.local);
73
- }
74
- catch (error) {
75
- printError(error.message);
76
- process.exit(1);
77
- }
78
- });
79
- // tsq retro apply
80
- retroCmd
81
- .command('apply')
82
- .description('Apply improvements')
83
- .action(async () => {
84
- try {
85
- await applyImprovements();
86
- }
87
- catch (error) {
88
- printError(error.message);
89
- process.exit(1);
90
- }
91
- });
92
- // tsq retro auto
93
- retroCmd
94
- .command('auto')
95
- .description('Run full retrospective cycle automatically (start → collect → report → apply)')
96
- .option('--local', 'Skip GitHub Issue creation')
97
- .action(async (options) => {
98
- try {
99
- await runAutoRetro(options.local);
100
- }
101
- catch (error) {
102
- printError(error.message);
103
- process.exit(1);
104
- }
105
- });
106
- // tsq retro status
107
- retroCmd
108
- .command('status')
109
- .description('Show retrospective status')
110
- .action(async () => {
111
- try {
112
- await showRetroStatus();
113
- }
114
- catch (error) {
115
- printError(error.message);
116
- process.exit(1);
117
- }
118
- });
119
- }
120
- // ============================================================
121
- // Phase-level retro
122
- // ============================================================
123
- const VALID_PHASES = ['planning', 'design', 'implementation', 'review', 'security', 'deployment'];
124
- async function runPhaseRetro(phase) {
125
- if (!VALID_PHASES.includes(phase)) {
126
- throw new Error(`Invalid phase: ${phase}. Valid: ${VALID_PHASES.join(', ')}`);
127
- }
128
- const projectRoot = await findProjectRoot();
129
- if (!projectRoot) {
130
- throw new Error('Not a TimSquad project');
131
- }
132
- const project = await getProjectInfo(projectRoot);
133
- printHeader(`Phase Retrospective: ${phase}`);
134
- console.log(colors.dim('KPT 프레임워크로 Phase 회고를 진행합니다.\n'));
135
- // Interactive KPT input
136
- console.log(colors.header('Keep (잘 된 것)'));
137
- const keepInput = await promptText('쉼표로 구분하여 입력:', '');
138
- const keep = keepInput.split(',').map(s => s.trim()).filter(Boolean);
139
- console.log('');
140
- console.log(colors.header('Problem (문제점)'));
141
- const problemInput = await promptText('쉼표로 구분하여 입력:', '');
142
- const problem = problemInput.split(',').map(s => s.trim()).filter(Boolean);
143
- console.log('');
144
- console.log(colors.header('Try (다음에 시도할 것)'));
145
- const tryInput = await promptText('쉼표로 구분하여 입력:', '');
146
- const tryNext = tryInput.split(',').map(s => s.trim()).filter(Boolean);
147
- // Create phase retro entry
148
- const entry = {
149
- id: `PR-${phase}-${Date.now()}`,
150
- timestamp: getTimestamp(),
151
- project: project.name,
152
- phase,
153
- keep,
154
- problem,
155
- try_next: tryNext,
156
- tags: [phase, project.type],
157
- };
158
- // Save locally
159
- const feedbackDir = path.join(projectRoot, '.timsquad', 'feedback');
160
- await fs.ensureDir(feedbackDir);
161
- const fileName = `phase-${phase}-${getDateString()}.json`;
162
- await fs.writeJson(path.join(feedbackDir, fileName), entry, { spaces: 2 });
163
- console.log('');
164
- printSuccess(`Phase 회고 저장: .timsquad/feedback/${fileName}`);
165
- // Show summary
166
- console.log('');
167
- printKeyValue('Keep', keep.length > 0 ? keep.join(', ') : '(없음)');
168
- printKeyValue('Problem', problem.length > 0 ? problem.join(', ') : '(없음)');
169
- printKeyValue('Try', tryNext.length > 0 ? tryNext.join(', ') : '(없음)');
170
- console.log(colors.dim('\n전체 리포트 생성: tsq retro report'));
171
- }
172
- // ============================================================
173
- // Existing retro flow
174
- // ============================================================
175
- async function getRetroState(projectRoot) {
176
- const statePath = path.join(projectRoot, '.timsquad', 'retrospective', 'state.json');
177
- if (!await exists(statePath)) {
178
- return { currentCycle: 0, status: 'idle' };
179
- }
180
- return fs.readJson(statePath);
181
- }
182
- async function saveRetroState(projectRoot, state) {
183
- const statePath = path.join(projectRoot, '.timsquad', 'retrospective', 'state.json');
184
- await fs.ensureDir(path.dirname(statePath));
185
- await fs.writeJson(statePath, state, { spaces: 2 });
186
- }
187
- async function startRetro() {
188
- const projectRoot = await findProjectRoot();
189
- if (!projectRoot) {
190
- throw new Error('Not a TimSquad project');
191
- }
192
- const state = await getRetroState(projectRoot);
193
- if (state.status !== 'idle') {
194
- throw new Error(`Retrospective cycle ${state.currentCycle} is already in progress (${state.status})`);
195
- }
196
- state.currentCycle += 1;
197
- state.status = 'collecting';
198
- state.startedAt = getTimestamp();
199
- await saveRetroState(projectRoot, state);
200
- printSuccess(`Started retrospective cycle ${state.currentCycle}`);
201
- console.log(colors.dim('\nNext: Run "tsq retro collect" to collect metrics'));
202
- }
203
- async function collectRetro() {
204
- const projectRoot = await findProjectRoot();
205
- if (!projectRoot) {
206
- throw new Error('Not a TimSquad project');
207
- }
208
- const state = await getRetroState(projectRoot);
209
- if (state.status !== 'collecting') {
210
- throw new Error('No active retrospective. Run "tsq retro start" first');
211
- }
212
- printHeader(`Collecting Metrics - Cycle ${state.currentCycle}`);
213
- // Collect log stats
214
- const logsDir = path.join(projectRoot, '.timsquad', 'logs');
215
- const logFiles = await listFiles('*.md', logsDir);
216
- const recentLogs = logFiles.filter(f => !f.startsWith('_'));
217
- // Count by agent
218
- const agentStats = {};
219
- for (const file of recentLogs) {
220
- const match = file.match(/-([a-z]+)\.md$/);
221
- if (match) {
222
- const agent = match[1];
223
- agentStats[agent] = (agentStats[agent] || 0) + 1;
224
- }
225
- }
226
- // Create metrics JSON
227
- const metrics = {
228
- cycle: state.currentCycle,
229
- collectedAt: getTimestamp(),
230
- raw_data: {
231
- log_files: recentLogs.length,
232
- agents: agentStats,
233
- },
234
- summary: {
235
- total_logs: recentLogs.length,
236
- agents_active: Object.keys(agentStats).length,
237
- },
238
- };
239
- const metricsPath = path.join(projectRoot, '.timsquad', 'retrospective', 'metrics', `cycle-${state.currentCycle}.json`);
240
- await fs.ensureDir(path.dirname(metricsPath));
241
- await fs.writeJson(metricsPath, metrics, { spaces: 2 });
242
- state.status = 'analyzing';
243
- state.collectedAt = getTimestamp();
244
- await saveRetroState(projectRoot, state);
245
- printSuccess('Metrics collected');
246
- printKeyValue('Log files', String(recentLogs.length));
247
- printKeyValue('Active agents', String(Object.keys(agentStats).length));
248
- console.log(colors.dim('\nNext: Run "tsq retro analyze" to analyze patterns'));
249
- }
250
- async function analyzeRetro() {
251
- const projectRoot = await findProjectRoot();
252
- if (!projectRoot) {
253
- throw new Error('Not a TimSquad project');
254
- }
255
- const state = await getRetroState(projectRoot);
256
- if (state.status !== 'analyzing') {
257
- throw new Error('Collect metrics first. Run "tsq retro collect"');
258
- }
259
- printHeader(`Analyzing Patterns - Cycle ${state.currentCycle}`);
260
- const analysis = await runPatternAnalysis(projectRoot, state.currentCycle);
261
- // 결과 저장
262
- const analysisDir = path.join(projectRoot, '.timsquad', 'retrospective', 'analysis');
263
- await fs.ensureDir(analysisDir);
264
- await fs.writeJson(path.join(analysisDir, `cycle-${state.currentCycle}-analysis.json`), analysis, { spaces: 2 });
265
- state.status = 'reporting';
266
- state.analyzedAt = getTimestamp();
267
- await saveRetroState(projectRoot, state);
268
- // 결과 출력
269
- printSuccess('Pattern analysis completed');
270
- printKeyValue('Sessions analyzed', String(analysis.sessions));
271
- printKeyValue('Agents', String(Object.keys(analysis.agents).length));
272
- printKeyValue('Flags', String(analysis.flags.length));
273
- if (analysis.flags.length > 0) {
274
- console.log(colors.warning('\n⚠ Detected issues:'));
275
- for (const flag of analysis.flags) {
276
- console.log(colors.dim(` - [${flag.severity}] ${flag.message}`));
277
- }
278
- }
279
- console.log(colors.dim('\nNext: Run "tsq retro report" to generate report'));
280
- }
281
- async function runPatternAnalysis(projectRoot, cycle) {
282
- const sessionsDir = path.join(projectRoot, '.timsquad', 'logs', 'sessions');
283
- const agentStats = {};
284
- const toolStats = {};
285
- const fileModCounts = {};
286
- let sessionCount = 0;
287
- // 세션 로그 파싱
288
- if (await exists(sessionsDir)) {
289
- const logFiles = await listFiles('*.jsonl', sessionsDir);
290
- sessionCount = logFiles.length;
291
- for (const file of logFiles) {
292
- try {
293
- const content = await fs.readFile(path.join(sessionsDir, file), 'utf-8');
294
- for (const line of content.split('\n')) {
295
- const trimmed = line.trim();
296
- if (!trimmed)
297
- continue;
298
- try {
299
- const ev = JSON.parse(trimmed);
300
- // 에이전트 통계
301
- if (ev.event === 'SubagentStart' && ev.detail?.subagent_type) {
302
- const agent = ev.detail.subagent_type;
303
- if (!agentStats[agent])
304
- agentStats[agent] = { calls: 0, failures: 0 };
305
- agentStats[agent].calls++;
306
- }
307
- // 도구 통계
308
- if (ev.event === 'PostToolUse' && ev.tool) {
309
- if (!toolStats[ev.tool])
310
- toolStats[ev.tool] = { uses: 0, failures: 0 };
311
- toolStats[ev.tool].uses++;
312
- }
313
- if (ev.event === 'PostToolUseFailure' && ev.tool) {
314
- if (!toolStats[ev.tool])
315
- toolStats[ev.tool] = { uses: 0, failures: 0 };
316
- toolStats[ev.tool].failures++;
317
- }
318
- }
319
- catch { /* skip malformed line */ }
320
- }
321
- }
322
- catch { /* skip unreadable file */ }
323
- }
324
- }
325
- // L1 태스크 로그에서 rework 파일 탐지
326
- const tasksDir = path.join(projectRoot, '.timsquad', 'logs', 'tasks');
327
- if (await exists(tasksDir)) {
328
- const taskFiles = await listFiles('*.json', tasksDir);
329
- for (const file of taskFiles) {
330
- try {
331
- const task = await fs.readJson(path.join(tasksDir, file));
332
- if (task.mechanical?.files) {
333
- for (const f of task.mechanical.files) {
334
- fileModCounts[f.path] = (fileModCounts[f.path] || 0) + 1;
335
- }
336
- }
337
- // 에이전트 실패 추적 (status !== 'completed')
338
- if (task.agent && task.status !== 'completed') {
339
- if (!agentStats[task.agent])
340
- agentStats[task.agent] = { calls: 0, failures: 0 };
341
- agentStats[task.agent].failures++;
342
- }
343
- }
344
- catch { /* skip */ }
345
- }
346
- }
347
- // rework 파일 (3회+ 수정)
348
- const reworkFiles = Object.entries(fileModCounts)
349
- .filter(([, count]) => count >= 3)
350
- .sort(([, a], [, b]) => b - a)
351
- .map(([filePath, modifications]) => ({ path: filePath, modifications }));
352
- // 에이전트별 실패율 계산
353
- const agents = {};
354
- for (const [name, stat] of Object.entries(agentStats)) {
355
- const total = stat.calls + stat.failures;
356
- agents[name] = {
357
- calls: stat.calls,
358
- failures: stat.failures,
359
- failureRate: total > 0 ? Math.round((stat.failures / total) * 100) : 0,
360
- };
361
- }
362
- // 도구별 실패율 계산
363
- const tools = {};
364
- for (const [name, stat] of Object.entries(toolStats)) {
365
- const total = stat.uses + stat.failures;
366
- tools[name] = {
367
- uses: stat.uses,
368
- failures: stat.failures,
369
- failureRate: total > 0 ? Math.round((stat.failures / total) * 100) : 0,
370
- };
371
- }
372
- // 이상 탐지 플래그
373
- const flags = [];
374
- // 에이전트 실패율 > 20%
375
- for (const [name, stat] of Object.entries(agents)) {
376
- if (stat.failureRate > 20 && (stat.calls + stat.failures) >= 3) {
377
- flags.push({
378
- severity: 'warn',
379
- category: 'agent-failure',
380
- message: `Agent "${name}" failure rate ${stat.failureRate}% (${stat.failures}/${stat.calls + stat.failures})`,
381
- });
382
- }
383
- }
384
- // 도구 실패율 > 30% (3회 이상 사용)
385
- for (const [name, stat] of Object.entries(tools)) {
386
- if (stat.failureRate > 30 && (stat.uses + stat.failures) >= 3) {
387
- flags.push({
388
- severity: 'warn',
389
- category: 'tool-failure',
390
- message: `Tool "${name}" failure rate ${stat.failureRate}% (${stat.failures}/${stat.uses + stat.failures})`,
391
- });
392
- }
393
- }
394
- // rework 파일
395
- for (const rw of reworkFiles.slice(0, 5)) {
396
- flags.push({
397
- severity: 'info',
398
- category: 'rework',
399
- message: `File "${rw.path}" modified ${rw.modifications} times (possible rework)`,
400
- });
401
- }
402
- return {
403
- cycle,
404
- analyzedAt: getTimestamp(),
405
- sessions: sessionCount,
406
- agents,
407
- tools,
408
- reworkFiles,
409
- flags,
410
- };
411
- }
412
- // ============================================================
413
- // Aggregated report + GitHub Issue
414
- // ============================================================
415
- async function loadFeedbackEntries(projectRoot) {
416
- const feedbackDir = path.join(projectRoot, '.timsquad', 'feedback');
417
- if (!await exists(feedbackDir))
418
- return [];
419
- const files = await listFiles('FB-*.json', feedbackDir);
420
- const entries = [];
421
- for (const file of files) {
422
- try {
423
- const data = await fs.readJson(path.join(feedbackDir, file));
424
- entries.push(data);
425
- }
426
- catch {
427
- // skip invalid files
428
- }
429
- }
430
- return entries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
431
- }
432
- async function loadPhaseRetros(projectRoot) {
433
- const feedbackDir = path.join(projectRoot, '.timsquad', 'feedback');
434
- if (!await exists(feedbackDir))
435
- return [];
436
- const files = await listFiles('phase-*.json', feedbackDir);
437
- const entries = [];
438
- for (const file of files) {
439
- try {
440
- const data = await fs.readJson(path.join(feedbackDir, file));
441
- entries.push(data);
442
- }
443
- catch {
444
- // skip invalid files
445
- }
446
- }
447
- return entries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
448
- }
449
- function buildAggregatedReport(project, phases, feedbacks) {
450
- const byLevel = {};
451
- const byPhase = {};
452
- const issueCount = {};
453
- for (const fb of feedbacks) {
454
- const levelKey = `Level ${fb.level ?? '?'}`;
455
- byLevel[levelKey] = (byLevel[levelKey] || 0) + 1;
456
- if (fb.phase) {
457
- byPhase[fb.phase] = (byPhase[fb.phase] || 0) + 1;
458
- }
459
- if (fb.trigger) {
460
- issueCount[fb.trigger] = (issueCount[fb.trigger] || 0) + 1;
461
- }
462
- }
463
- for (const pr of phases) {
464
- byPhase[pr.phase] = (byPhase[pr.phase] || 0) + pr.problem.length;
465
- for (const p of pr.problem) {
466
- issueCount[p] = (issueCount[p] || 0) + 1;
467
- }
468
- }
469
- const topIssues = Object.entries(issueCount)
470
- .sort(([, a], [, b]) => b - a)
471
- .slice(0, 5)
472
- .map(([issue]) => issue);
473
- const timestamps = [
474
- ...phases.map(p => p.timestamp),
475
- ...feedbacks.map(f => f.timestamp),
476
- ].sort();
477
- return {
478
- project: project.name,
479
- generated_at: getTimestamp(),
480
- period: {
481
- start: timestamps[0] || getTimestamp(),
482
- end: timestamps[timestamps.length - 1] || getTimestamp(),
483
- },
484
- phases,
485
- feedbacks,
486
- summary: {
487
- total_feedbacks: feedbacks.length,
488
- by_level: byLevel,
489
- by_phase: byPhase,
490
- top_issues: topIssues,
491
- },
492
- };
493
- }
494
- function renderReportMarkdown(report) {
495
- const lines = [];
496
- lines.push(`# [retro] ${report.project} - Retrospective Report`);
497
- lines.push('');
498
- lines.push(`> Generated: ${report.generated_at}`);
499
- lines.push(`> Period: ${report.period.start?.split('T')[0] ?? 'N/A'} ~ ${report.period.end?.split('T')[0] ?? 'N/A'}`);
500
- lines.push('');
501
- // Summary
502
- lines.push('## Summary');
503
- lines.push('');
504
- lines.push('| Metric | Value |');
505
- lines.push('|--------|-------|');
506
- lines.push(`| Phase retros | ${report.phases.length} |`);
507
- lines.push(`| Feedbacks | ${report.summary.total_feedbacks} |`);
508
- for (const [level, count] of Object.entries(report.summary.by_level)) {
509
- lines.push(`| ${level} | ${count} |`);
510
- }
511
- lines.push('');
512
- // Top issues
513
- if (report.summary.top_issues.length > 0) {
514
- lines.push('## Top Issues');
515
- lines.push('');
516
- for (const issue of report.summary.top_issues) {
517
- lines.push(`- ${issue}`);
518
- }
519
- lines.push('');
520
- }
521
- // Phase retros
522
- if (report.phases.length > 0) {
523
- lines.push('## Phase Retrospectives');
524
- lines.push('');
525
- for (const phase of report.phases) {
526
- lines.push(`### ${phase.phase} (${phase.timestamp?.split('T')[0] ?? 'N/A'})`);
527
- lines.push('');
528
- if (phase.keep.length > 0) {
529
- lines.push('**Keep:**');
530
- for (const k of phase.keep)
531
- lines.push(`- ${k}`);
532
- lines.push('');
533
- }
534
- if (phase.problem.length > 0) {
535
- lines.push('**Problem:**');
536
- for (const p of phase.problem)
537
- lines.push(`- ${p}`);
538
- lines.push('');
539
- }
540
- if (phase.try_next.length > 0) {
541
- lines.push('**Try:**');
542
- for (const t of phase.try_next)
543
- lines.push(`- ${t}`);
544
- lines.push('');
545
- }
546
- }
547
- }
548
- // Feedbacks
549
- if (report.feedbacks.length > 0) {
550
- lines.push('## Feedbacks');
551
- lines.push('');
552
- lines.push('| Date | Level | Trigger | Message |');
553
- lines.push('|------|:-----:|---------|---------|');
554
- for (const fb of report.feedbacks) {
555
- const date = fb.timestamp?.split('T')[0] ?? 'N/A';
556
- lines.push(`| ${date} | ${fb.level ?? '-'} | ${fb.trigger ?? '-'} | ${fb.message.substring(0, 60)} |`);
557
- }
558
- lines.push('');
559
- }
560
- lines.push('## Improvement Suggestions');
561
- lines.push('');
562
- for (const issue of report.summary.top_issues) {
563
- lines.push(`- [ ] Address: ${issue}`);
564
- }
565
- lines.push('');
566
- lines.push('---');
567
- lines.push('Generated by TimSquad v2.0.0');
568
- return lines.join('\n');
569
- }
570
- function createGitHubIssue(title, body) {
571
- try {
572
- execSync('gh --version', { stdio: 'ignore' });
573
- // Write body to temp file to avoid shell escaping issues
574
- const tmpFile = path.join('/tmp', `tsq-retro-${Date.now()}.md`);
575
- fs.writeFileSync(tmpFile, body, 'utf-8');
576
- const result = execFileSync('gh', ['issue', 'create', '--repo', 'ericson/timsquad', '--title', title, '--label', 'retro-feedback', '--body-file', tmpFile], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
577
- fs.removeSync(tmpFile);
578
- return result.trim();
579
- }
580
- catch {
581
- return null;
582
- }
583
- }
584
- async function generateReport(localOnly) {
585
- const projectRoot = await findProjectRoot();
586
- if (!projectRoot) {
587
- throw new Error('Not a TimSquad project');
588
- }
589
- const project = await getProjectInfo(projectRoot);
590
- printHeader('Generating Aggregated Report');
591
- // Load all local feedback
592
- const phases = await loadPhaseRetros(projectRoot);
593
- const feedbacks = await loadFeedbackEntries(projectRoot);
594
- if (phases.length === 0 && feedbacks.length === 0) {
595
- console.log(colors.warning('\n⚠ No feedback data found.'));
596
- console.log(colors.dim(' Run "tsq retro phase <name>" or "tsq feedback <message>" first.\n'));
597
- return;
598
- }
599
- printKeyValue('Phase retros', String(phases.length));
600
- printKeyValue('Feedbacks', String(feedbacks.length));
601
- // Build aggregated report
602
- const report = buildAggregatedReport(project, phases, feedbacks);
603
- const markdown = renderReportMarkdown(report);
604
- // Save report locally
605
- const state = await getRetroState(projectRoot);
606
- const cycleNum = state.currentCycle > 0 ? state.currentCycle : 1;
607
- const reportDir = path.join(projectRoot, '.timsquad', 'retrospective', 'cycles');
608
- await fs.ensureDir(reportDir);
609
- const reportPath = path.join(reportDir, `cycle-${cycleNum}.md`);
610
- await writeFile(reportPath, markdown);
611
- const jsonPath = path.join(reportDir, `cycle-${cycleNum}.json`);
612
- await fs.writeJson(jsonPath, report, { spaces: 2 });
613
- console.log('');
614
- printSuccess(`Report saved: cycle-${cycleNum}.md`);
615
- console.log(colors.path(` ${reportPath}`));
616
- // Create GitHub Issue (unless --local)
617
- if (!localOnly) {
618
- console.log('');
619
- const shouldCreate = await promptConfirm('GitHub Issue를 생성하시겠습니까?', true);
620
- if (shouldCreate) {
621
- const issueTitle = `[retro] ${project.name} - Cycle ${cycleNum}`;
622
- const issueUrl = createGitHubIssue(issueTitle, markdown);
623
- if (issueUrl) {
624
- console.log('');
625
- printSuccess(`GitHub Issue created: ${issueUrl}`);
626
- }
627
- else {
628
- console.log(colors.warning('\n⚠ GitHub Issue 생성 실패 (gh CLI 확인 필요)'));
629
- console.log(colors.dim(' 수동 생성: gh issue create --repo ericson/timsquad'));
630
- }
631
- }
632
- }
633
- // Update retro state
634
- state.status = 'applying';
635
- await saveRetroState(projectRoot, state);
636
- console.log(colors.dim('\nNext: Review report and run "tsq retro apply" to complete'));
637
- }
638
- async function applyImprovements() {
639
- const projectRoot = await findProjectRoot();
640
- if (!projectRoot) {
641
- throw new Error('Not a TimSquad project');
642
- }
643
- const state = await getRetroState(projectRoot);
644
- if (state.status !== 'applying') {
645
- throw new Error('Generate report first. Run "tsq retro report"');
646
- }
647
- console.log(colors.warning('\n⚠ Improvement application requires manual review'));
648
- console.log(colors.dim(' 1. Review the generated report'));
649
- console.log(colors.dim(' 2. Update templates/prompts as needed'));
650
- console.log(colors.dim(' 3. This cycle will be marked as complete\n'));
651
- // Archive processed feedback
652
- const feedbackDir = path.join(projectRoot, '.timsquad', 'feedback');
653
- const archiveDir = path.join(feedbackDir, `archive-cycle-${state.currentCycle}`);
654
- if (await exists(feedbackDir)) {
655
- const files = await listFiles('*.json', feedbackDir);
656
- if (files.length > 0) {
657
- await fs.ensureDir(archiveDir);
658
- for (const file of files) {
659
- await fs.move(path.join(feedbackDir, file), path.join(archiveDir, file), { overwrite: true });
660
- }
661
- console.log(colors.dim(` Feedback archived: ${archiveDir}`));
662
- }
663
- }
664
- state.status = 'idle';
665
- await saveRetroState(projectRoot, state);
666
- printSuccess(`Retrospective cycle ${state.currentCycle} completed!`);
667
- }
668
- // ============================================================
669
- // Auto retro (전체 사이클 자동 실행)
670
- // start → collect → (analyze skip) → report → apply
671
- // ============================================================
672
- async function runAutoRetro(localOnly) {
673
- const projectRoot = await findProjectRoot();
674
- if (!projectRoot) {
675
- throw new Error('Not a TimSquad project');
676
- }
677
- printHeader('Auto Retrospective');
678
- console.log(colors.dim('전체 회고 사이클을 자동으로 실행합니다.\n'));
679
- // Step 1: Start
680
- let state = await getRetroState(projectRoot);
681
- if (state.status !== 'idle') {
682
- console.log(colors.warning(`⚠ 기존 cycle ${state.currentCycle} (${state.status}) 가 진행 중입니다.`));
683
- console.log(colors.dim(' 기존 사이클을 이어서 진행합니다.\n'));
684
- }
685
- else {
686
- state.currentCycle += 1;
687
- state.status = 'collecting';
688
- state.startedAt = getTimestamp();
689
- await saveRetroState(projectRoot, state);
690
- printSuccess(`[1/4] Cycle ${state.currentCycle} started`);
691
- }
692
- // Step 2: Collect
693
- if (state.status === 'collecting') {
694
- const logsDir = path.join(projectRoot, '.timsquad', 'logs');
695
- const logFiles = await listFiles('*.md', logsDir);
696
- const recentLogs = logFiles.filter(f => !f.startsWith('_'));
697
- const agentStats = {};
698
- for (const file of recentLogs) {
699
- const match = file.match(/-([a-z]+)\.md$/);
700
- if (match) {
701
- agentStats[match[1]] = (agentStats[match[1]] || 0) + 1;
702
- }
703
- }
704
- const metricsPath = path.join(projectRoot, '.timsquad', 'retrospective', 'metrics', `cycle-${state.currentCycle}.json`);
705
- await fs.ensureDir(path.dirname(metricsPath));
706
- await fs.writeJson(metricsPath, {
707
- cycle: state.currentCycle,
708
- collectedAt: getTimestamp(),
709
- raw_data: { log_files: recentLogs.length, agents: agentStats },
710
- summary: { total_logs: recentLogs.length, agents_active: Object.keys(agentStats).length },
711
- }, { spaces: 2 });
712
- state.status = 'analyzing';
713
- state.collectedAt = getTimestamp();
714
- await saveRetroState(projectRoot, state);
715
- printSuccess(`[2/4] Metrics collected (${recentLogs.length} logs, ${Object.keys(agentStats).length} agents)`);
716
- }
717
- // Step 3: Pattern analysis
718
- if (state.status === 'analyzing') {
719
- const analysis = await runPatternAnalysis(projectRoot, state.currentCycle);
720
- const analysisDir = path.join(projectRoot, '.timsquad', 'retrospective', 'analysis');
721
- await fs.ensureDir(analysisDir);
722
- await fs.writeJson(path.join(analysisDir, `cycle-${state.currentCycle}-analysis.json`), analysis, { spaces: 2 });
723
- state.status = 'reporting';
724
- state.analyzedAt = getTimestamp();
725
- await saveRetroState(projectRoot, state);
726
- printSuccess(`[3/4] Analysis completed (${analysis.flags.length} flags)`);
727
- }
728
- // Step 4: Report + Apply
729
- if (state.status === 'reporting') {
730
- const project = await getProjectInfo(projectRoot);
731
- const phases = await loadPhaseRetros(projectRoot);
732
- const feedbacks = await loadFeedbackEntries(projectRoot);
733
- if (phases.length === 0 && feedbacks.length === 0) {
734
- console.log(colors.dim('\n 피드백 데이터 없음 - 빈 리포트 생성을 건너뜁니다.'));
735
- }
736
- else {
737
- const report = buildAggregatedReport(project, phases, feedbacks);
738
- const markdown = renderReportMarkdown(report);
739
- const reportDir = path.join(projectRoot, '.timsquad', 'retrospective', 'cycles');
740
- await fs.ensureDir(reportDir);
741
- await writeFile(path.join(reportDir, `cycle-${state.currentCycle}.md`), markdown);
742
- await fs.writeJson(path.join(reportDir, `cycle-${state.currentCycle}.json`), report, { spaces: 2 });
743
- printKeyValue(' Phase retros', String(phases.length));
744
- printKeyValue(' Feedbacks', String(feedbacks.length));
745
- // GitHub Issue (auto mode에서는 --local이 아니면 자동 생성 시도)
746
- if (!localOnly) {
747
- const issueTitle = `[retro] ${project.name} - Cycle ${state.currentCycle}`;
748
- const issueUrl = createGitHubIssue(issueTitle, markdown);
749
- if (issueUrl) {
750
- printSuccess(` GitHub Issue: ${issueUrl}`);
751
- }
752
- }
753
- }
754
- // Apply: archive feedback
755
- const feedbackDir = path.join(projectRoot, '.timsquad', 'feedback');
756
- const archiveDir = path.join(feedbackDir, `archive-cycle-${state.currentCycle}`);
757
- if (await exists(feedbackDir)) {
758
- const files = await listFiles('*.json', feedbackDir);
759
- if (files.length > 0) {
760
- await fs.ensureDir(archiveDir);
761
- for (const file of files) {
762
- await fs.move(path.join(feedbackDir, file), path.join(archiveDir, file), { overwrite: true });
763
- }
764
- }
765
- }
766
- state.status = 'idle';
767
- await saveRetroState(projectRoot, state);
768
- printSuccess(`[4/4] Cycle ${state.currentCycle} completed`);
769
- }
770
- // Bonus: retro → improve 자동 연결
771
- // GitHub Issue가 생성되었으면 improve fetch+analyze 자동 실행
772
- try {
773
- execSync('gh --version', { stdio: 'ignore' });
774
- console.log(colors.dim('\n Improvement analysis 자동 실행 중...'));
775
- try {
776
- execFileSync('npx', ['tsq', 'improve', 'fetch', '--limit', '20'], {
777
- cwd: projectRoot,
778
- stdio: 'ignore',
779
- timeout: 15000,
780
- });
781
- execFileSync('npx', ['tsq', 'improve', 'analyze'], {
782
- cwd: projectRoot,
783
- stdio: 'ignore',
784
- timeout: 15000,
785
- });
786
- printSuccess(' Improvement analysis completed');
787
- console.log(colors.dim(' 결과 확인: tsq improve summary'));
788
- }
789
- catch {
790
- console.log(colors.dim(' Improvement analysis skipped (no issues or error)'));
791
- }
792
- }
793
- catch {
794
- // gh not available, skip
795
- }
796
- console.log(colors.dim('\nTip: tsq retro status 로 결과 확인'));
797
- }
798
- async function showRetroStatus() {
799
- const projectRoot = await findProjectRoot();
800
- if (!projectRoot) {
801
- throw new Error('Not a TimSquad project');
802
- }
803
- const state = await getRetroState(projectRoot);
804
- printHeader('Retrospective Status');
805
- printKeyValue('Current Cycle', String(state.currentCycle));
806
- printKeyValue('Status', state.status);
807
- if (state.startedAt) {
808
- printKeyValue('Started', state.startedAt?.split('T')[0] ?? 'N/A');
809
- }
810
- // Count pending feedback
811
- const feedbackDir = path.join(projectRoot, '.timsquad', 'feedback');
812
- if (await exists(feedbackDir)) {
813
- const phaseFiles = await listFiles('phase-*.json', feedbackDir);
814
- const fbFiles = await listFiles('FB-*.json', feedbackDir);
815
- console.log('');
816
- printKeyValue('Pending phase retros', String(phaseFiles.length));
817
- printKeyValue('Pending feedbacks', String(fbFiles.length));
818
- }
819
- // List completed cycles
820
- const cyclesDir = path.join(projectRoot, '.timsquad', 'retrospective', 'cycles');
821
- if (await exists(cyclesDir)) {
822
- const cycles = await listFiles('cycle-*.md', cyclesDir);
823
- if (cycles.length > 0) {
824
- console.log(colors.dim(`\nCompleted cycles: ${cycles.length}`));
825
- }
826
- }
827
- }
828
- //# sourceMappingURL=retro.js.map