@phuc1403/musketeer 0.8.0 → 0.10.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 (236) hide show
  1. package/INSTALLATION.md +52 -52
  2. package/README.md +49 -49
  3. package/bin/musketeer.js +168 -168
  4. package/manifest.json +333 -301
  5. package/package.json +48 -48
  6. package/src/dotnet-scaffold-copier.js +79 -79
  7. package/src/provisioner/detect.js +93 -93
  8. package/src/self-update.js +77 -77
  9. package/template/.claude/agents/code-reviewer.md +182 -166
  10. package/template/.claude/agents/git-manager.md +18 -18
  11. package/template/.claude/agents/hallmark-auditor.md +78 -78
  12. package/template/.claude/agents/researcher.md +33 -33
  13. package/template/.claude/hooks/block-unsafe-adr-title.cjs +85 -85
  14. package/template/.claude/hooks/git-skill-reminder.cjs +53 -0
  15. package/template/.claude/hooks/init-adr-dir.cjs +173 -173
  16. package/template/.claude/hooks/inject-adr-flags.cjs +94 -94
  17. package/template/.claude/hooks/lib/adr/command-scan.cjs +115 -115
  18. package/template/.claude/hooks/lib/characteristics/checker.cjs +357 -357
  19. package/template/.claude/hooks/lib/colors.cjs +180 -122
  20. package/template/.claude/hooks/lib/git-info-cache.cjs +191 -191
  21. package/template/.claude/hooks/lib/transcript-parser.cjs +300 -277
  22. package/template/.claude/hooks/sync-adr-toc.cjs +146 -146
  23. package/template/.claude/hooks/{usage-context-awareness.cjs → usage-quota-cache-refresh.cjs} +166 -166
  24. package/template/.claude/hooks/validate-characteristics-hook.cjs +66 -66
  25. package/template/.claude/hooks/validate-cml-hook.js +145 -145
  26. package/template/.claude/skills/adr-writer/SKILL.md +48 -48
  27. package/template/.claude/skills/adr-writer/references/adr-example.md +35 -35
  28. package/template/.claude/skills/architecture-characteristic-writer/SKILL.md +215 -215
  29. package/template/.claude/skills/architecture-characteristic-writer/assets/worksheet-template.md +29 -29
  30. package/template/.claude/skills/architecture-characteristic-writer/references/characteristics-catalog.md +40 -40
  31. package/template/.claude/skills/architecture-characteristic-writer/scripts/ranking-table.cjs +171 -171
  32. package/template/.claude/skills/code-review/SKILL.md +201 -54
  33. package/template/.claude/skills/code-review/references/checklist-workflow.md +96 -0
  34. package/template/.claude/skills/code-review/references/checklists/api.md +52 -52
  35. package/template/.claude/skills/code-review/references/checklists/base.md +100 -100
  36. package/template/.claude/skills/code-review/references/checklists/web-app.md +54 -54
  37. package/template/.claude/skills/code-review/references/code-review-reception.md +113 -0
  38. package/template/.claude/skills/code-review/references/codebase-scan-workflow.md +30 -0
  39. package/template/.claude/skills/code-review/references/edge-case-scouting.md +119 -0
  40. package/template/.claude/skills/code-review/references/input-mode-resolution.md +135 -0
  41. package/template/.claude/skills/code-review/references/parallel-review-workflow.md +76 -0
  42. package/template/.claude/skills/code-review/references/requesting-code-review.md +116 -0
  43. package/template/.claude/skills/code-review/references/spec-compliance-review.md +43 -0
  44. package/template/.claude/skills/code-review/references/task-management-reviews.md +140 -0
  45. package/template/.claude/skills/code-review/references/verification-before-completion.md +139 -0
  46. package/template/.claude/skills/context-map/SKILL.md +80 -80
  47. package/template/.claude/skills/context-map/example.cml +106 -106
  48. package/template/.claude/skills/context-map/reference/Bounded Context/Bounded Context.md +40 -40
  49. package/template/.claude/skills/context-map/reference/Bounded Context/businessModel.md +5 -5
  50. package/template/.claude/skills/context-map/reference/Bounded Context/domainVisionStatement.md +2 -2
  51. package/template/.claude/skills/context-map/reference/Bounded Context/evolution.md +5 -5
  52. package/template/.claude/skills/context-map/reference/Bounded Context/implementationTechnology.md +1 -1
  53. package/template/.claude/skills/context-map/reference/Bounded Context/implements.md +1 -1
  54. package/template/.claude/skills/context-map/reference/Bounded Context/knowledgeLevel.md +4 -4
  55. package/template/.claude/skills/context-map/reference/Bounded Context/realizes.md +9 -9
  56. package/template/.claude/skills/context-map/reference/Bounded Context/refines.md +10 -10
  57. package/template/.claude/skills/context-map/reference/Bounded Context/responsibilities.md +26 -26
  58. package/template/.claude/skills/context-map/reference/Bounded Context/type.md +23 -23
  59. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Anticorruption Layer.md +5 -5
  60. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Bounded Context Relationship.md +12 -12
  61. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Conformist.md +5 -5
  62. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Customer-Supplier (C-S).md +22 -22
  63. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Open Host Service.md +4 -4
  64. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Partnership (P).md +13 -13
  65. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Published Language.md +4 -4
  66. package/template/.claude/skills/context-map/reference/Bounded Context Relationship/Shared Kernel (SK).md +12 -12
  67. package/template/.claude/skills/context-map/reference/Context Map.md +62 -62
  68. package/template/.claude/skills/context-map/reference/Domain/Domain.md +30 -30
  69. package/template/.claude/skills/context-map/reference/Domain/supports.md +33 -33
  70. package/template/.claude/skills/context-map/reference/Domain/type.md +3 -3
  71. package/template/.claude/skills/context-map/reference/Semantic Rules.md +32 -32
  72. package/template/.claude/skills/git/SKILL.md +131 -115
  73. package/template/.claude/skills/git/references/branch-management.md +88 -88
  74. package/template/.claude/skills/git/references/commit-standards.md +46 -46
  75. package/template/.claude/skills/git/references/context-efficiency.md +54 -0
  76. package/template/.claude/skills/git/references/gh-cli-guide.md +109 -109
  77. package/template/.claude/skills/git/references/safety-protocols.md +69 -69
  78. package/template/.claude/skills/git/references/workflow-commit.md +58 -58
  79. package/template/.claude/skills/git/references/workflow-merge-pr.md +136 -0
  80. package/template/.claude/skills/git/references/workflow-merge.md +48 -48
  81. package/template/.claude/skills/git/references/workflow-pr.md +58 -58
  82. package/template/.claude/skills/git/references/workflow-push.md +52 -52
  83. package/template/.claude/skills/hallmark/SKILL.md +552 -552
  84. package/template/.claude/skills/hallmark/references/anti-patterns.md +412 -412
  85. package/template/.claude/skills/hallmark/references/assets.md +406 -406
  86. package/template/.claude/skills/hallmark/references/color.md +95 -95
  87. package/template/.claude/skills/hallmark/references/component-cookbook.md +256 -256
  88. package/template/.claude/skills/hallmark/references/components/c1-outlined-chip.md +12 -12
  89. package/template/.claude/skills/hallmark/references/components/c2-inline-form-as-cta.md +16 -16
  90. package/template/.claude/skills/hallmark/references/components/c3-typographic-link.md +8 -8
  91. package/template/.claude/skills/hallmark/references/components/c4-sticky-bottom-bar.md +16 -16
  92. package/template/.claude/skills/hallmark/references/components/f1-bento-grid.md +20 -20
  93. package/template/.claude/skills/hallmark/references/components/f2-sticky-scroll-stack.md +20 -20
  94. package/template/.claude/skills/hallmark/references/components/f3-tabular-spec-sheet.md +11 -11
  95. package/template/.claude/skills/hallmark/references/components/f4-step-sequence.md +11 -11
  96. package/template/.claude/skills/hallmark/references/components/f5-annotated-screenshot.md +11 -11
  97. package/template/.claude/skills/hallmark/references/components/f6-product-card-grid.md +41 -41
  98. package/template/.claude/skills/hallmark/references/components/ft1-mast-headed.md +13 -13
  99. package/template/.claude/skills/hallmark/references/components/ft2-inline-rule-single-line.md +10 -10
  100. package/template/.claude/skills/hallmark/references/components/ft3-index-style-category-list.md +12 -12
  101. package/template/.claude/skills/hallmark/references/components/ft4-dense-typographic.md +10 -10
  102. package/template/.claude/skills/hallmark/references/components/ft5-statement.md +21 -21
  103. package/template/.claude/skills/hallmark/references/components/ft6-letter-close.md +19 -19
  104. package/template/.claude/skills/hallmark/references/components/ft7-newsletter-first.md +27 -27
  105. package/template/.claude/skills/hallmark/references/components/ft8-marquee-scroll.md +25 -25
  106. package/template/.claude/skills/hallmark/references/components/h1-marquee.md +15 -15
  107. package/template/.claude/skills/hallmark/references/components/h2-split-diptych.md +15 -15
  108. package/template/.claude/skills/hallmark/references/components/h3-quote-led.md +11 -11
  109. package/template/.claude/skills/hallmark/references/components/h4-stat-led.md +14 -14
  110. package/template/.claude/skills/hallmark/references/components/h5-letter-hero.md +11 -11
  111. package/template/.claude/skills/hallmark/references/components/h6-photographic-fold.md +16 -16
  112. package/template/.claude/skills/hallmark/references/components/h7-demo-video-clipped-by-viewport-edge.md +27 -27
  113. package/template/.claude/skills/hallmark/references/components/h8-mockup-split-browser-framed.md +23 -23
  114. package/template/.claude/skills/hallmark/references/components/h9-custom-illustration-centerpiece.md +27 -27
  115. package/template/.claude/skills/hallmark/references/components/n1-wordmark-2-links.md +12 -12
  116. package/template/.claude/skills/hallmark/references/components/n10-floating-on-scroll-morph.md +19 -19
  117. package/template/.claude/skills/hallmark/references/components/n2-floating-chip.md +14 -14
  118. package/template/.claude/skills/hallmark/references/components/n3-side-rail.md +14 -14
  119. package/template/.claude/skills/hallmark/references/components/n4-hidden-behind-k.md +9 -9
  120. package/template/.claude/skills/hallmark/references/components/n5-floating-pill.md +28 -28
  121. package/template/.claude/skills/hallmark/references/components/n6-newspaper-masthead.md +24 -24
  122. package/template/.claude/skills/hallmark/references/components/n7-brutal-slab.md +22 -22
  123. package/template/.claude/skills/hallmark/references/components/n8-terminal-command.md +21 -21
  124. package/template/.claude/skills/hallmark/references/components/n9-edge-aligned-minimal.md +17 -17
  125. package/template/.claude/skills/hallmark/references/components/s1-left-margin-numbered.md +15 -15
  126. package/template/.claude/skills/hallmark/references/components/s2-hanging.md +13 -13
  127. package/template/.claude/skills/hallmark/references/components/s3-sticky-pinned.md +19 -19
  128. package/template/.claude/skills/hallmark/references/components/s4-inline-no-break.md +11 -11
  129. package/template/.claude/skills/hallmark/references/components/s5-bottom-anchored.md +13 -13
  130. package/template/.claude/skills/hallmark/references/components/t1-pull-quote-with-marginalia.md +12 -12
  131. package/template/.claude/skills/hallmark/references/components/t2-logo-wall-hairline.md +19 -19
  132. package/template/.claude/skills/hallmark/references/components/t3-single-huge-quote.md +11 -11
  133. package/template/.claude/skills/hallmark/references/components/t4-numbered-stat-strip.md +14 -14
  134. package/template/.claude/skills/hallmark/references/contract.md +24 -24
  135. package/template/.claude/skills/hallmark/references/copy.md +182 -182
  136. package/template/.claude/skills/hallmark/references/custom-craft.md +626 -626
  137. package/template/.claude/skills/hallmark/references/custom-theme.md +329 -329
  138. package/template/.claude/skills/hallmark/references/design-md.md +116 -116
  139. package/template/.claude/skills/hallmark/references/export-formats.md +328 -328
  140. package/template/.claude/skills/hallmark/references/floating-nav.md +89 -89
  141. package/template/.claude/skills/hallmark/references/genres/atmospheric.md +65 -65
  142. package/template/.claude/skills/hallmark/references/genres/editorial.md +70 -70
  143. package/template/.claude/skills/hallmark/references/genres/modern-minimal.md +67 -67
  144. package/template/.claude/skills/hallmark/references/genres/playful.md +65 -65
  145. package/template/.claude/skills/hallmark/references/hero-enrichment.md +474 -474
  146. package/template/.claude/skills/hallmark/references/imagery-kit.md +170 -170
  147. package/template/.claude/skills/hallmark/references/interaction-and-states.md +207 -207
  148. package/template/.claude/skills/hallmark/references/layout-and-space.md +111 -111
  149. package/template/.claude/skills/hallmark/references/macrostructures/01-bento-grid.md +35 -35
  150. package/template/.claude/skills/hallmark/references/macrostructures/02-long-document.md +34 -34
  151. package/template/.claude/skills/hallmark/references/macrostructures/03-marquee-hero.md +31 -31
  152. package/template/.claude/skills/hallmark/references/macrostructures/04-stat-led.md +32 -32
  153. package/template/.claude/skills/hallmark/references/macrostructures/05-workbench.md +32 -32
  154. package/template/.claude/skills/hallmark/references/macrostructures/06-conversational-faq.md +33 -33
  155. package/template/.claude/skills/hallmark/references/macrostructures/07-manifesto.md +32 -32
  156. package/template/.claude/skills/hallmark/references/macrostructures/08-photographic.md +34 -34
  157. package/template/.claude/skills/hallmark/references/macrostructures/09-quote-led.md +32 -32
  158. package/template/.claude/skills/hallmark/references/macrostructures/10-specimen.md +32 -32
  159. package/template/.claude/skills/hallmark/references/macrostructures/11-catalogue.md +23 -23
  160. package/template/.claude/skills/hallmark/references/macrostructures/12-letter.md +23 -23
  161. package/template/.claude/skills/hallmark/references/macrostructures/13-index-first.md +23 -23
  162. package/template/.claude/skills/hallmark/references/macrostructures/14-narrative-workflow.md +23 -23
  163. package/template/.claude/skills/hallmark/references/macrostructures/15-split-studio.md +23 -23
  164. package/template/.claude/skills/hallmark/references/macrostructures/16-feature-stack.md +23 -23
  165. package/template/.claude/skills/hallmark/references/macrostructures/17-type-specimen.md +23 -23
  166. package/template/.claude/skills/hallmark/references/macrostructures/18-portfolio-grid.md +23 -23
  167. package/template/.claude/skills/hallmark/references/macrostructures/19-map-diagram.md +23 -23
  168. package/template/.claude/skills/hallmark/references/macrostructures/20-ecosystem-index.md +23 -23
  169. package/template/.claude/skills/hallmark/references/macrostructures/21-component-playground.md +23 -23
  170. package/template/.claude/skills/hallmark/references/macrostructures.md +89 -89
  171. package/template/.claude/skills/hallmark/references/microinteractions.md +260 -260
  172. package/template/.claude/skills/hallmark/references/motion.md +109 -109
  173. package/template/.claude/skills/hallmark/references/preview-examples.md +49 -49
  174. package/template/.claude/skills/hallmark/references/responsive.md +138 -138
  175. package/template/.claude/skills/hallmark/references/slop-test.md +205 -205
  176. package/template/.claude/skills/hallmark/references/structure.md +164 -164
  177. package/template/.claude/skills/hallmark/references/study.md +511 -511
  178. package/template/.claude/skills/hallmark/references/typography.md +243 -243
  179. package/template/.claude/skills/hallmark/references/verbs/audit.md +25 -25
  180. package/template/.claude/skills/hallmark/references/verbs/redesign.md +269 -269
  181. package/template/.claude/skills/hallmark-loop/SKILL.md +105 -105
  182. package/template/.claude/skills/hallmark-loop/references/auditor-call.md +60 -60
  183. package/template/.claude/skills/hallmark-loop/references/capture.md +78 -78
  184. package/template/.claude/skills/hallmark-loop/references/loop-control.md +79 -79
  185. package/template/.claude/skills/handoff/SKILL.md +15 -15
  186. package/template/.claude/skills/knowledge-crunching/SKILL.md +94 -94
  187. package/template/.claude/skills/research/SKILL.md +69 -69
  188. package/template/.claude/skills/skill-creator/LICENSE.txt +201 -201
  189. package/template/.claude/skills/skill-creator/SKILL.md +154 -149
  190. package/template/.claude/skills/skill-creator/agents/analyzer.md +274 -274
  191. package/template/.claude/skills/skill-creator/agents/comparator.md +202 -202
  192. package/template/.claude/skills/skill-creator/agents/grader.md +223 -223
  193. package/template/.claude/skills/skill-creator/assets/eval_review.html +146 -146
  194. package/template/.claude/skills/skill-creator/eval-viewer/generate_review.py +471 -471
  195. package/template/.claude/skills/skill-creator/eval-viewer/viewer.html +1325 -1325
  196. package/template/.claude/skills/skill-creator/references/benchmark-optimization-guide.md +86 -86
  197. package/template/.claude/skills/skill-creator/references/distribution-guide.md +79 -79
  198. package/template/.claude/skills/skill-creator/references/eval-infrastructure-guide.md +129 -129
  199. package/template/.claude/skills/skill-creator/references/eval-schemas.md +121 -121
  200. package/template/.claude/skills/skill-creator/references/mcp-skills-integration.md +71 -71
  201. package/template/.claude/skills/skill-creator/references/metadata-quality-criteria.md +94 -94
  202. package/template/.claude/skills/skill-creator/references/plugin-marketplace-hosting.md +104 -104
  203. package/template/.claude/skills/skill-creator/references/plugin-marketplace-overview.md +89 -89
  204. package/template/.claude/skills/skill-creator/references/plugin-marketplace-schema.md +93 -93
  205. package/template/.claude/skills/skill-creator/references/plugin-marketplace-sources.md +103 -103
  206. package/template/.claude/skills/skill-creator/references/plugin-marketplace-troubleshooting.md +76 -76
  207. package/template/.claude/skills/skill-creator/references/script-quality-criteria.md +106 -106
  208. package/template/.claude/skills/skill-creator/references/skill-anatomy-and-requirements.md +77 -77
  209. package/template/.claude/skills/skill-creator/references/skill-creation-workflow.md +152 -151
  210. package/template/.claude/skills/skill-creator/references/skill-design-patterns.md +75 -75
  211. package/template/.claude/skills/skill-creator/references/skillmark-benchmark-criteria.md +102 -102
  212. package/template/.claude/skills/skill-creator/references/structure-organization-criteria.md +114 -114
  213. package/template/.claude/skills/skill-creator/references/testing-and-iteration.md +78 -78
  214. package/template/.claude/skills/skill-creator/references/token-efficiency-criteria.md +74 -74
  215. package/template/.claude/skills/skill-creator/references/troubleshooting-guide.md +81 -81
  216. package/template/.claude/skills/skill-creator/references/validation-checklist.md +83 -83
  217. package/template/.claude/skills/skill-creator/references/writing-effective-instructions.md +88 -88
  218. package/template/.claude/skills/skill-creator/references/yaml-frontmatter-reference.md +92 -92
  219. package/template/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +401 -401
  220. package/template/.claude/skills/skill-creator/scripts/encoding_utils.py +36 -36
  221. package/template/.claude/skills/skill-creator/scripts/generate_report.py +326 -326
  222. package/template/.claude/skills/skill-creator/scripts/improve_description.py +248 -248
  223. package/template/.claude/skills/skill-creator/scripts/init_skill.py +360 -360
  224. package/template/.claude/skills/skill-creator/scripts/package_skill.py +143 -143
  225. package/template/.claude/skills/skill-creator/scripts/quick_validate.py +110 -110
  226. package/template/.claude/skills/skill-creator/scripts/run_eval.py +310 -310
  227. package/template/.claude/skills/skill-creator/scripts/run_loop.py +332 -332
  228. package/template/.claude/skills/skill-creator/scripts/utils.py +47 -47
  229. package/template/.claude/skills/tdd/SKILL.md +142 -142
  230. package/template/.claude/skills/tdd/deep-modules.md +15 -15
  231. package/template/.claude/skills/tdd/interface-design.md +31 -31
  232. package/template/.claude/skills/tdd/mocking.md +59 -59
  233. package/template/.claude/skills/tdd/refactoring.md +10 -10
  234. package/template/.claude/skills/tdd/tests.md +61 -61
  235. package/template/.claude/statusline.cjs +0 -0
  236. package/template/.claude/skills/code-review/references/adversarial-review.md +0 -223
@@ -1,277 +1,300 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * Transcript Parser - Extract tool/agent/todo state from session JSONL
6
- * @module transcript-parser
7
- */
8
-
9
- const fs = require('fs');
10
- const readline = require('readline');
11
-
12
- function isNativeTaskTodo(todo) {
13
- return Boolean(todo && todo._source === 'native_task');
14
- }
15
-
16
- function normalizeTodo(todo) {
17
- if (!todo || typeof todo !== 'object') return null;
18
- const normalized = {
19
- content: todo.content ?? '',
20
- status: todo.status ?? 'pending',
21
- activeForm: todo.activeForm ?? null
22
- };
23
- if (todo.id != null) normalized.id = todo.id;
24
- return normalized;
25
- }
26
-
27
- function extractTaskIdFromString(text) {
28
- if (!text || typeof text !== 'string') return null;
29
- const trimmed = text.trim();
30
- if (!trimmed) return null;
31
-
32
- try {
33
- const parsed = JSON.parse(trimmed);
34
- return extractTaskIdFromValue(parsed);
35
- } catch {
36
- // Not JSON, continue with regex extraction.
37
- }
38
-
39
- const match = trimmed.match(/["']?task[_-]?id["']?\s*[:=]\s*["']([^"']+)["']/i);
40
- if (match && match[1]) return match[1];
41
- return null;
42
- }
43
-
44
- function extractTaskIdFromValue(value) {
45
- if (value == null) return null;
46
-
47
- if (typeof value === 'string') {
48
- return extractTaskIdFromString(value);
49
- }
50
-
51
- if (typeof value !== 'object') return null;
52
-
53
- if (typeof value.taskId === 'string' || typeof value.taskId === 'number') {
54
- return String(value.taskId);
55
- }
56
- if (typeof value.task_id === 'string' || typeof value.task_id === 'number') {
57
- return String(value.task_id);
58
- }
59
-
60
- if (Array.isArray(value)) {
61
- for (const item of value) {
62
- const taskId = extractTaskIdFromValue(item);
63
- if (taskId) return taskId;
64
- }
65
- return null;
66
- }
67
-
68
- for (const fieldValue of Object.values(value)) {
69
- const taskId = extractTaskIdFromValue(fieldValue);
70
- if (taskId) return taskId;
71
- }
72
- return null;
73
- }
74
-
75
- /**
76
- * Parse transcript JSONL file
77
- * @param {string} transcriptPath - Path to transcript file
78
- * @returns {Promise<TranscriptData>}
79
- */
80
- async function parseTranscript(transcriptPath) {
81
- const result = {
82
- tools: [],
83
- agents: [],
84
- todos: [],
85
- sessionStart: null
86
- };
87
-
88
- if (!transcriptPath || !fs.existsSync(transcriptPath)) {
89
- return result;
90
- }
91
-
92
- const toolMap = new Map();
93
- const agentMap = new Map();
94
- let latestTodos = [];
95
-
96
- try {
97
- const fileStream = fs.createReadStream(transcriptPath);
98
- const rl = readline.createInterface({
99
- input: fileStream,
100
- crlfDelay: Infinity
101
- });
102
-
103
- for await (const line of rl) {
104
- if (!line.trim()) continue;
105
-
106
- try {
107
- const entry = JSON.parse(line);
108
- processEntry(entry, toolMap, agentMap, latestTodos, result);
109
- } catch {
110
- // Skip malformed lines
111
- }
112
- }
113
- } catch {
114
- // Return partial results on error
115
- }
116
-
117
- result.tools = Array.from(toolMap.values()).slice(-20);
118
- result.agents = Array.from(agentMap.values()).slice(-10);
119
- result.todos = latestTodos
120
- .map(normalizeTodo)
121
- .filter(Boolean);
122
-
123
- return result;
124
- }
125
-
126
- /**
127
- * Process single JSONL entry
128
- * @param {Object} entry - Parsed JSON line
129
- * @param {Map} toolMap - Tool tracking map
130
- * @param {Map} agentMap - Agent tracking map
131
- * @param {Array} latestTodos - Latest todo array reference
132
- * @param {Object} result - Result object
133
- */
134
- function processEntry(entry, toolMap, agentMap, latestTodos, result) {
135
- const timestamp = entry.timestamp ? new Date(entry.timestamp) : new Date();
136
-
137
- // Track session start
138
- if (!result.sessionStart && entry.timestamp) {
139
- result.sessionStart = timestamp;
140
- }
141
-
142
- const content = entry.message?.content;
143
- if (!content || !Array.isArray(content)) return;
144
-
145
- for (const block of content) {
146
- // Handle tool_use blocks
147
- if (block.type === 'tool_use' && block.id && block.name) {
148
- if (block.name === 'Task') {
149
- // Agent spawn
150
- agentMap.set(block.id, {
151
- id: block.id,
152
- type: block.input?.subagent_type ?? 'unknown',
153
- model: block.input?.model ?? null,
154
- description: block.input?.description ?? null,
155
- status: 'running',
156
- startTime: timestamp,
157
- endTime: null
158
- });
159
- } else if (block.name === 'TodoWrite') {
160
- // Legacy: Replace todo array (deprecated, kept for backwards compatibility)
161
- if (block.input?.todos && Array.isArray(block.input.todos)) {
162
- latestTodos.length = 0;
163
- latestTodos.push(
164
- ...block.input.todos.map(todo => ({
165
- ...todo,
166
- _source: 'legacy_todowrite'
167
- }))
168
- );
169
- }
170
- } else if (block.name === 'TaskCreate') {
171
- // Native Task API: add new task.
172
- // Track by tool_use id first; hydrate real task id from matching tool_result when present.
173
- if (block.input?.subject) {
174
- latestTodos.push({
175
- id: block.id,
176
- content: block.input.subject,
177
- status: 'pending',
178
- activeForm: block.input.activeForm || null,
179
- _source: 'native_task',
180
- _toolUseId: block.id
181
- });
182
- }
183
- } else if (block.name === 'TaskUpdate') {
184
- // Native Task API: Update existing task status
185
- // Match by taskId against native-task ids first.
186
- // Numeric fallback maps to native-task creation order only (not legacy TodoWrite items).
187
- if (block.input?.taskId && block.input?.status) {
188
- const taskId = String(block.input.taskId);
189
- const nativeTodos = latestTodos.filter(isNativeTaskTodo);
190
- let task = nativeTodos.find(t => String(t.id) === taskId);
191
- if (!task && /^\d+$/.test(taskId)) {
192
- const idx = Number(taskId) - 1;
193
- if (idx >= 0 && idx < nativeTodos.length) task = nativeTodos[idx];
194
- }
195
-
196
- if (task) {
197
- task.status = block.input.status;
198
- if (Object.prototype.hasOwnProperty.call(block.input, 'activeForm')) {
199
- task.activeForm = block.input.activeForm || null;
200
- }
201
- }
202
- }
203
- } else {
204
- // Regular tool
205
- toolMap.set(block.id, {
206
- id: block.id,
207
- name: block.name,
208
- target: extractTarget(block.name, block.input),
209
- status: 'running',
210
- startTime: timestamp,
211
- endTime: null
212
- });
213
- }
214
- }
215
-
216
- // Handle tool_result blocks
217
- if (block.type === 'tool_result' && block.tool_use_id) {
218
- const tool = toolMap.get(block.tool_use_id);
219
- if (tool) {
220
- tool.status = block.is_error ? 'error' : 'completed';
221
- tool.endTime = timestamp;
222
- }
223
-
224
- const agent = agentMap.get(block.tool_use_id);
225
- if (agent) {
226
- agent.status = 'completed';
227
- agent.endTime = timestamp;
228
- }
229
-
230
- const createdTask = latestTodos.find(
231
- todo => isNativeTaskTodo(todo) && todo._toolUseId === block.tool_use_id
232
- );
233
- if (createdTask) {
234
- const hydratedId = extractTaskIdFromValue(block.content);
235
- if (hydratedId) {
236
- createdTask.id = hydratedId;
237
- }
238
- }
239
- }
240
- }
241
- }
242
-
243
- /**
244
- * Extract target from tool input
245
- * @param {string} toolName - Tool name
246
- * @param {Object} input - Tool input object
247
- * @returns {string|null} - Extracted target
248
- */
249
- function extractTarget(toolName, input) {
250
- if (!input) return null;
251
-
252
- switch (toolName) {
253
- case 'Read':
254
- case 'Write':
255
- case 'Edit':
256
- return input.file_path ?? input.path ?? null;
257
-
258
- case 'Glob':
259
- case 'Grep':
260
- return input.pattern ?? null;
261
-
262
- case 'Bash':
263
- const cmd = input.command;
264
- if (!cmd) return null;
265
- return cmd.length > 30 ? cmd.slice(0, 30) + '...' : cmd;
266
-
267
- default:
268
- return null;
269
- }
270
- }
271
-
272
- module.exports = {
273
- parseTranscript,
274
- // Export for testing
275
- processEntry,
276
- extractTarget
277
- };
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Transcript Parser - Extract tool/agent/todo state from session JSONL
6
+ * @module transcript-parser
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const readline = require('readline');
11
+
12
+ function isNativeTaskTodo(todo) {
13
+ return Boolean(todo && todo._source === 'native_task');
14
+ }
15
+
16
+ function normalizeTodo(todo) {
17
+ if (!todo || typeof todo !== 'object') return null;
18
+ const normalized = {
19
+ content: todo.content ?? '',
20
+ status: todo.status ?? 'pending',
21
+ activeForm: todo.activeForm ?? null
22
+ };
23
+ if (todo.id != null) normalized.id = todo.id;
24
+ return normalized;
25
+ }
26
+
27
+ function extractTaskIdFromString(text) {
28
+ if (!text || typeof text !== 'string') return null;
29
+ const trimmed = text.trim();
30
+ if (!trimmed) return null;
31
+
32
+ try {
33
+ const parsed = JSON.parse(trimmed);
34
+ return extractTaskIdFromValue(parsed);
35
+ } catch {
36
+ // Not JSON, continue with regex extraction.
37
+ }
38
+
39
+ const match = trimmed.match(/["']?task[_-]?id["']?\s*[:=]\s*["']([^"']+)["']/i);
40
+ if (match && match[1]) return match[1];
41
+ return null;
42
+ }
43
+
44
+ function extractTaskIdFromValue(value) {
45
+ if (value == null) return null;
46
+
47
+ if (typeof value === 'string') {
48
+ return extractTaskIdFromString(value);
49
+ }
50
+
51
+ if (typeof value !== 'object') return null;
52
+
53
+ if (typeof value.taskId === 'string' || typeof value.taskId === 'number') {
54
+ return String(value.taskId);
55
+ }
56
+ if (typeof value.task_id === 'string' || typeof value.task_id === 'number') {
57
+ return String(value.task_id);
58
+ }
59
+
60
+ if (Array.isArray(value)) {
61
+ for (const item of value) {
62
+ const taskId = extractTaskIdFromValue(item);
63
+ if (taskId) return taskId;
64
+ }
65
+ return null;
66
+ }
67
+
68
+ for (const fieldValue of Object.values(value)) {
69
+ const taskId = extractTaskIdFromValue(fieldValue);
70
+ if (taskId) return taskId;
71
+ }
72
+ return null;
73
+ }
74
+
75
+ /**
76
+ * Parse transcript JSONL file
77
+ * @param {string} transcriptPath - Path to transcript file
78
+ * @returns {Promise<TranscriptData>}
79
+ */
80
+ async function parseTranscript(transcriptPath) {
81
+ const result = {
82
+ tools: [],
83
+ agents: [],
84
+ todos: [],
85
+ sessionStart: null,
86
+ statuslineActivityCount: 0,
87
+ invalidLineCount: 0,
88
+ lastValidEntryAt: null,
89
+ lastActivityAt: null
90
+ };
91
+
92
+ if (!transcriptPath || !fs.existsSync(transcriptPath)) {
93
+ return result;
94
+ }
95
+
96
+ const toolMap = new Map();
97
+ const agentMap = new Map();
98
+ let latestTodos = [];
99
+
100
+ try {
101
+ const fileStream = fs.createReadStream(transcriptPath);
102
+ const rl = readline.createInterface({
103
+ input: fileStream,
104
+ crlfDelay: Infinity
105
+ });
106
+
107
+ for await (const line of rl) {
108
+ if (!line.trim()) continue;
109
+
110
+ try {
111
+ const entry = JSON.parse(line);
112
+ processEntry(entry, toolMap, agentMap, latestTodos, result);
113
+ } catch {
114
+ result.invalidLineCount += 1;
115
+ }
116
+ }
117
+ } catch {
118
+ // Return partial results on error
119
+ }
120
+
121
+ result.tools = Array.from(toolMap.values()).slice(-20);
122
+ result.agents = Array.from(agentMap.values()).slice(-10);
123
+ result.todos = latestTodos
124
+ .map(normalizeTodo)
125
+ .filter(Boolean);
126
+
127
+ return result;
128
+ }
129
+
130
+ /**
131
+ * Process single JSONL entry
132
+ * @param {Object} entry - Parsed JSON line
133
+ * @param {Map} toolMap - Tool tracking map
134
+ * @param {Map} agentMap - Agent tracking map
135
+ * @param {Array} latestTodos - Latest todo array reference
136
+ * @param {Object} result - Result object
137
+ */
138
+ function processEntry(entry, toolMap, agentMap, latestTodos, result) {
139
+ const parsedTimestamp = entry.timestamp ? new Date(entry.timestamp) : new Date();
140
+ const timestamp = Number.isNaN(parsedTimestamp.getTime()) ? new Date() : parsedTimestamp;
141
+ const timestampIso = timestamp.toISOString();
142
+ let hadActivity = false;
143
+
144
+ result.lastValidEntryAt = timestampIso;
145
+
146
+ // Track session start
147
+ if (!result.sessionStart && entry.timestamp) {
148
+ result.sessionStart = timestamp;
149
+ }
150
+
151
+ const content = entry.message?.content;
152
+ if (!content || !Array.isArray(content)) return;
153
+
154
+ for (const block of content) {
155
+ // Handle tool_use blocks
156
+ if (block.type === 'tool_use' && block.id && block.name) {
157
+ if (block.name === 'Task') {
158
+ result.statuslineActivityCount += 1;
159
+ hadActivity = true;
160
+ // Agent spawn
161
+ agentMap.set(block.id, {
162
+ id: block.id,
163
+ type: block.input?.subagent_type ?? 'unknown',
164
+ model: block.input?.model ?? null,
165
+ description: block.input?.description ?? null,
166
+ status: 'running',
167
+ startTime: timestamp,
168
+ endTime: null
169
+ });
170
+ } else if (block.name === 'TodoWrite') {
171
+ result.statuslineActivityCount += 1;
172
+ hadActivity = true;
173
+ // Legacy: Replace todo array (deprecated, kept for backwards compatibility)
174
+ if (block.input?.todos && Array.isArray(block.input.todos)) {
175
+ latestTodos.length = 0;
176
+ latestTodos.push(
177
+ ...block.input.todos.map(todo => ({
178
+ ...todo,
179
+ _source: 'legacy_todowrite'
180
+ }))
181
+ );
182
+ }
183
+ } else if (block.name === 'TaskCreate') {
184
+ result.statuslineActivityCount += 1;
185
+ hadActivity = true;
186
+ // Native Task API: add new task.
187
+ // Track by tool_use id first; hydrate real task id from matching tool_result when present.
188
+ if (block.input?.subject) {
189
+ latestTodos.push({
190
+ id: block.id,
191
+ content: block.input.subject,
192
+ status: 'pending',
193
+ activeForm: block.input.activeForm || null,
194
+ _source: 'native_task',
195
+ _toolUseId: block.id
196
+ });
197
+ }
198
+ } else if (block.name === 'TaskUpdate') {
199
+ result.statuslineActivityCount += 1;
200
+ hadActivity = true;
201
+ // Native Task API: Update existing task status
202
+ // Match by taskId against native-task ids first.
203
+ // Numeric fallback maps to native-task creation order only (not legacy TodoWrite items).
204
+ if (block.input?.taskId && block.input?.status) {
205
+ const taskId = String(block.input.taskId);
206
+ const nativeTodos = latestTodos.filter(isNativeTaskTodo);
207
+ let task = nativeTodos.find(t => String(t.id) === taskId);
208
+ if (!task && /^\d+$/.test(taskId)) {
209
+ const idx = Number(taskId) - 1;
210
+ if (idx >= 0 && idx < nativeTodos.length) task = nativeTodos[idx];
211
+ }
212
+
213
+ if (task) {
214
+ task.status = block.input.status;
215
+ if (Object.prototype.hasOwnProperty.call(block.input, 'activeForm')) {
216
+ task.activeForm = block.input.activeForm || null;
217
+ }
218
+ }
219
+ }
220
+ } else {
221
+ // Regular tool
222
+ toolMap.set(block.id, {
223
+ id: block.id,
224
+ name: block.name,
225
+ target: extractTarget(block.name, block.input),
226
+ status: 'running',
227
+ startTime: timestamp,
228
+ endTime: null
229
+ });
230
+ }
231
+ }
232
+
233
+ // Handle tool_result blocks
234
+ if (block.type === 'tool_result' && block.tool_use_id) {
235
+ const tool = toolMap.get(block.tool_use_id);
236
+ if (tool) {
237
+ tool.status = block.is_error ? 'error' : 'completed';
238
+ tool.endTime = timestamp;
239
+ }
240
+
241
+ const agent = agentMap.get(block.tool_use_id);
242
+ if (agent) {
243
+ result.statuslineActivityCount += 1;
244
+ hadActivity = true;
245
+ agent.status = 'completed';
246
+ agent.endTime = timestamp;
247
+ }
248
+
249
+ const createdTask = latestTodos.find(
250
+ todo => isNativeTaskTodo(todo) && todo._toolUseId === block.tool_use_id
251
+ );
252
+ if (createdTask) {
253
+ const hydratedId = extractTaskIdFromValue(block.content);
254
+ if (hydratedId) {
255
+ createdTask.id = hydratedId;
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ if (hadActivity) {
262
+ result.lastActivityAt = timestampIso;
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Extract target from tool input
268
+ * @param {string} toolName - Tool name
269
+ * @param {Object} input - Tool input object
270
+ * @returns {string|null} - Extracted target
271
+ */
272
+ function extractTarget(toolName, input) {
273
+ if (!input) return null;
274
+
275
+ switch (toolName) {
276
+ case 'Read':
277
+ case 'Write':
278
+ case 'Edit':
279
+ return input.file_path ?? input.path ?? null;
280
+
281
+ case 'Glob':
282
+ case 'Grep':
283
+ return input.pattern ?? null;
284
+
285
+ case 'Bash':
286
+ const cmd = input.command;
287
+ if (!cmd) return null;
288
+ return cmd.length > 30 ? cmd.slice(0, 30) + '...' : cmd;
289
+
290
+ default:
291
+ return null;
292
+ }
293
+ }
294
+
295
+ module.exports = {
296
+ parseTranscript,
297
+ // Export for testing
298
+ processEntry,
299
+ extractTarget
300
+ };