claude-code-workflow 6.3.37 → 6.3.39

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 (173) hide show
  1. package/.claude/commands/workflow/lite-execute.md +2 -0
  2. package/.codex/agents/action-planning-agent.md +885 -0
  3. package/.codex/agents/ccw-loop-b-complete.md +227 -0
  4. package/.codex/agents/ccw-loop-b-debug.md +172 -0
  5. package/.codex/agents/ccw-loop-b-develop.md +147 -0
  6. package/.codex/agents/ccw-loop-b-init.md +82 -0
  7. package/.codex/agents/ccw-loop-b-validate.md +204 -0
  8. package/.codex/agents/ccw-loop-executor.md +260 -0
  9. package/.codex/agents/cli-discuss-agent.md +391 -0
  10. package/.codex/agents/cli-execution-agent.md +333 -0
  11. package/.codex/agents/cli-explore-agent.md +186 -0
  12. package/.codex/agents/cli-lite-planning-agent.md +736 -0
  13. package/.codex/agents/cli-planning-agent.md +562 -0
  14. package/.codex/agents/code-developer.md +408 -0
  15. package/.codex/agents/conceptual-planning-agent.md +321 -0
  16. package/.codex/agents/context-search-agent.md +585 -0
  17. package/.codex/agents/debug-explore-agent.md +436 -0
  18. package/.codex/agents/doc-generator.md +334 -0
  19. package/.codex/agents/issue-plan-agent.md +417 -0
  20. package/.codex/agents/issue-queue-agent.md +311 -0
  21. package/.codex/agents/memory-bridge.md +96 -0
  22. package/.codex/agents/test-context-search-agent.md +402 -0
  23. package/.codex/agents/test-fix-agent.md +359 -0
  24. package/.codex/agents/ui-design-agent.md +595 -0
  25. package/.codex/agents/universal-executor.md +135 -0
  26. package/.codex/prompts/clean.md +409 -0
  27. package/.codex/prompts/issue-discover-by-prompt.md +364 -0
  28. package/.codex/prompts/issue-discover.md +261 -0
  29. package/.codex/prompts/issue-execute.md +10 -0
  30. package/.codex/prompts/issue-new.md +285 -0
  31. package/.codex/prompts/issue-plan.md +161 -63
  32. package/.codex/prompts/issue-queue.md +298 -288
  33. package/.codex/prompts/lite-execute.md +627 -133
  34. package/.codex/prompts/lite-fix.md +670 -0
  35. package/.codex/prompts/lite-plan-a.md +337 -0
  36. package/.codex/prompts/lite-plan-b.md +485 -0
  37. package/.codex/prompts/{lite-plan.md → lite-plan-c.md} +601 -469
  38. package/.codex/skills/ccw-loop/README.md +171 -0
  39. package/.codex/skills/ccw-loop/SKILL.md +349 -0
  40. package/.codex/skills/ccw-loop/phases/actions/action-complete.md +269 -0
  41. package/.codex/skills/ccw-loop/phases/actions/action-debug.md +286 -0
  42. package/.codex/skills/ccw-loop/phases/actions/action-develop.md +183 -0
  43. package/.codex/skills/ccw-loop/phases/actions/action-init.md +164 -0
  44. package/.codex/skills/ccw-loop/phases/actions/action-menu.md +205 -0
  45. package/.codex/skills/ccw-loop/phases/actions/action-validate.md +250 -0
  46. package/.codex/skills/ccw-loop/phases/orchestrator.md +416 -0
  47. package/.codex/skills/ccw-loop/phases/state-schema.md +388 -0
  48. package/.codex/skills/ccw-loop/specs/action-catalog.md +182 -0
  49. package/.codex/skills/ccw-loop-b/README.md +301 -0
  50. package/.codex/skills/ccw-loop-b/SKILL.md +322 -0
  51. package/.codex/skills/ccw-loop-b/phases/orchestrator.md +257 -0
  52. package/.codex/skills/ccw-loop-b/phases/state-schema.md +181 -0
  53. package/.codex/skills/ccw-loop-b/specs/action-catalog.md +383 -0
  54. package/.codex/skills/parallel-dev-cycle/README.md +382 -0
  55. package/.codex/skills/parallel-dev-cycle/SKILL.md +512 -0
  56. package/.codex/skills/parallel-dev-cycle/phases/agents/code-developer.md +242 -0
  57. package/.codex/skills/parallel-dev-cycle/phases/agents/exploration-planner.md +285 -0
  58. package/.codex/skills/parallel-dev-cycle/phases/agents/requirements-analyst.md +285 -0
  59. package/.codex/skills/parallel-dev-cycle/phases/agents/validation-archivist.md +381 -0
  60. package/.codex/skills/parallel-dev-cycle/phases/orchestrator.md +696 -0
  61. package/.codex/skills/parallel-dev-cycle/phases/state-schema.md +436 -0
  62. package/.codex/skills/parallel-dev-cycle/specs/communication-optimization.md +423 -0
  63. package/.codex/skills/parallel-dev-cycle/specs/coordination-protocol.md +391 -0
  64. package/.codex/skills/parallel-dev-cycle/specs/versioning-strategy.md +330 -0
  65. package/ccw/dist/cli.d.ts.map +1 -1
  66. package/ccw/dist/cli.js +4 -0
  67. package/ccw/dist/cli.js.map +1 -1
  68. package/ccw/dist/commands/install.d.ts.map +1 -1
  69. package/ccw/dist/commands/install.js +39 -8
  70. package/ccw/dist/commands/install.js.map +1 -1
  71. package/ccw/dist/commands/issue.d.ts +3 -0
  72. package/ccw/dist/commands/issue.d.ts.map +1 -1
  73. package/ccw/dist/commands/issue.js +107 -0
  74. package/ccw/dist/commands/issue.js.map +1 -1
  75. package/ccw/dist/commands/upgrade.js +1 -1
  76. package/ccw/dist/commands/upgrade.js.map +1 -1
  77. package/ccw/dist/config/litellm-api-config-manager.d.ts.map +1 -1
  78. package/ccw/dist/config/litellm-api-config-manager.js +3 -2
  79. package/ccw/dist/config/litellm-api-config-manager.js.map +1 -1
  80. package/ccw/dist/core/memory-embedder-bridge.d.ts.map +1 -1
  81. package/ccw/dist/core/memory-embedder-bridge.js +2 -5
  82. package/ccw/dist/core/memory-embedder-bridge.js.map +1 -1
  83. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  84. package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -1
  85. package/ccw/dist/core/routes/codexlens/config-handlers.js +7 -6
  86. package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -1
  87. package/ccw/dist/core/routes/codexlens/semantic-handlers.d.ts.map +1 -1
  88. package/ccw/dist/core/routes/codexlens/semantic-handlers.js +2 -2
  89. package/ccw/dist/core/routes/codexlens/semantic-handlers.js.map +1 -1
  90. package/ccw/dist/core/routes/graph-routes.d.ts.map +1 -1
  91. package/ccw/dist/core/routes/graph-routes.js +17 -2
  92. package/ccw/dist/core/routes/graph-routes.js.map +1 -1
  93. package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -1
  94. package/ccw/dist/core/routes/issue-routes.js +280 -33
  95. package/ccw/dist/core/routes/issue-routes.js.map +1 -1
  96. package/ccw/dist/core/routes/loop-v2-routes.d.ts +9 -0
  97. package/ccw/dist/core/routes/loop-v2-routes.d.ts.map +1 -1
  98. package/ccw/dist/core/routes/loop-v2-routes.js +56 -4
  99. package/ccw/dist/core/routes/loop-v2-routes.js.map +1 -1
  100. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  101. package/ccw/dist/core/routes/system-routes.js +3 -2
  102. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  103. package/ccw/dist/core/server.d.ts.map +1 -1
  104. package/ccw/dist/core/server.js +5 -3
  105. package/ccw/dist/core/server.js.map +1 -1
  106. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  107. package/ccw/dist/tools/claude-cli-tools.js +4 -3
  108. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  109. package/ccw/dist/tools/cli-config-manager.d.ts +1 -0
  110. package/ccw/dist/tools/cli-config-manager.d.ts.map +1 -1
  111. package/ccw/dist/tools/cli-config-manager.js +2 -1
  112. package/ccw/dist/tools/cli-config-manager.js.map +1 -1
  113. package/ccw/dist/tools/codex-lens-lsp.d.ts.map +1 -1
  114. package/ccw/dist/tools/codex-lens-lsp.js +2 -5
  115. package/ccw/dist/tools/codex-lens-lsp.js.map +1 -1
  116. package/ccw/dist/tools/codex-lens.d.ts.map +1 -1
  117. package/ccw/dist/tools/codex-lens.js +22 -32
  118. package/ccw/dist/tools/codex-lens.js.map +1 -1
  119. package/ccw/dist/tools/litellm-client.d.ts +6 -0
  120. package/ccw/dist/tools/litellm-client.d.ts.map +1 -1
  121. package/ccw/dist/tools/litellm-client.js +15 -2
  122. package/ccw/dist/tools/litellm-client.js.map +1 -1
  123. package/ccw/dist/tools/loop-task-manager.d.ts +13 -2
  124. package/ccw/dist/tools/loop-task-manager.d.ts.map +1 -1
  125. package/ccw/dist/tools/loop-task-manager.js.map +1 -1
  126. package/ccw/dist/tools/native-session-discovery.d.ts.map +1 -1
  127. package/ccw/dist/tools/native-session-discovery.js +35 -7
  128. package/ccw/dist/tools/native-session-discovery.js.map +1 -1
  129. package/ccw/dist/utils/codexlens-path.d.ts +36 -0
  130. package/ccw/dist/utils/codexlens-path.d.ts.map +1 -0
  131. package/ccw/dist/utils/codexlens-path.js +56 -0
  132. package/ccw/dist/utils/codexlens-path.js.map +1 -0
  133. package/ccw/dist/utils/uv-manager.d.ts.map +1 -1
  134. package/ccw/dist/utils/uv-manager.js +3 -2
  135. package/ccw/dist/utils/uv-manager.js.map +1 -1
  136. package/ccw/src/cli.ts +4 -0
  137. package/ccw/src/commands/install.ts +51 -8
  138. package/ccw/src/commands/issue.ts +119 -0
  139. package/ccw/src/commands/upgrade.ts +1 -1
  140. package/ccw/src/config/litellm-api-config-manager.ts +3 -2
  141. package/ccw/src/core/memory-embedder-bridge.ts +2 -6
  142. package/ccw/src/core/routes/cli-routes.ts +1 -1
  143. package/ccw/src/core/routes/codexlens/config-handlers.ts +7 -6
  144. package/ccw/src/core/routes/codexlens/semantic-handlers.ts +2 -2
  145. package/ccw/src/core/routes/graph-routes.ts +18 -2
  146. package/ccw/src/core/routes/issue-routes.ts +308 -33
  147. package/ccw/src/core/routes/loop-v2-routes.ts +64 -6
  148. package/ccw/src/core/routes/system-routes.ts +3 -2
  149. package/ccw/src/core/server.ts +6 -3
  150. package/ccw/src/templates/dashboard-css/02-session.css +2 -0
  151. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +103 -1
  152. package/ccw/src/templates/dashboard-css/32-issue-manager.css +32 -0
  153. package/ccw/src/templates/dashboard-js/components/cli-history.js +48 -48
  154. package/ccw/src/templates/dashboard-js/components/navigation.js +6 -0
  155. package/ccw/src/templates/dashboard-js/components/notifications.js +6 -0
  156. package/ccw/src/templates/dashboard-js/components/version-check.js +38 -0
  157. package/ccw/src/templates/dashboard-js/i18n.js +126 -0
  158. package/ccw/src/templates/dashboard-js/state.js +2 -0
  159. package/ccw/src/templates/dashboard-js/views/cli-manager.js +1 -1
  160. package/ccw/src/templates/dashboard-js/views/issue-manager.js +183 -1
  161. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +55 -11
  162. package/ccw/src/templates/dashboard-js/views/loop-monitor.js +112 -11
  163. package/ccw/src/templates/dashboard.html +48 -2
  164. package/ccw/src/tools/claude-cli-tools.ts +4 -3
  165. package/ccw/src/tools/cli-config-manager.ts +3 -1
  166. package/ccw/src/tools/codex-lens-lsp.ts +2 -5
  167. package/ccw/src/tools/codex-lens.ts +27 -38
  168. package/ccw/src/tools/litellm-client.ts +16 -2
  169. package/ccw/src/tools/loop-task-manager.ts +13 -2
  170. package/ccw/src/tools/native-session-discovery.ts +38 -7
  171. package/ccw/src/utils/codexlens-path.ts +60 -0
  172. package/ccw/src/utils/uv-manager.ts +3 -2
  173. package/package.json +1 -1
@@ -1732,12 +1732,25 @@
1732
1732
  align-items: center;
1733
1733
  justify-content: space-between;
1734
1734
  gap: 1rem;
1735
- margin-bottom: 0.75rem;
1736
1735
  padding: 0.75rem 1rem;
1737
1736
  background: hsl(var(--muted) / 0.2);
1738
1737
  border-bottom: 1px solid hsl(var(--border));
1739
1738
  }
1740
1739
 
1740
+ .solution-title-row {
1741
+ display: flex;
1742
+ align-items: center;
1743
+ gap: 0.5rem;
1744
+ flex: 1;
1745
+ }
1746
+
1747
+ .solution-badges {
1748
+ display: flex;
1749
+ align-items: center;
1750
+ gap: 0.5rem;
1751
+ flex-shrink: 0;
1752
+ }
1753
+
1741
1754
  .solution-title {
1742
1755
  font-weight: 600;
1743
1756
  font-size: 0.95rem;
@@ -2782,6 +2795,39 @@
2782
2795
  border-bottom: 1px solid hsl(var(--border));
2783
2796
  }
2784
2797
 
2798
+ .solution-details {
2799
+ padding: 0.75rem 1rem;
2800
+ border-bottom: 1px solid hsl(var(--border) / 0.5);
2801
+ }
2802
+
2803
+ .solution-details:last-child {
2804
+ border-bottom: none;
2805
+ }
2806
+
2807
+ .details-label {
2808
+ font-size: 0.8125rem;
2809
+ font-weight: 600;
2810
+ margin: 0 0 0.5rem 0;
2811
+ color: hsl(var(--foreground));
2812
+ }
2813
+
2814
+ .details-list {
2815
+ margin: 0;
2816
+ padding-left: 1.25rem;
2817
+ list-style: disc;
2818
+ }
2819
+
2820
+ .details-list li {
2821
+ font-size: 0.8125rem;
2822
+ line-height: 1.6;
2823
+ color: hsl(var(--muted-foreground));
2824
+ margin-bottom: 0.375rem;
2825
+ }
2826
+
2827
+ .details-list li:last-child {
2828
+ margin-bottom: 0;
2829
+ }
2830
+
2785
2831
  .solution-approach,
2786
2832
  .solution-dependencies,
2787
2833
  .solution-concerns {
@@ -3976,6 +4022,62 @@
3976
4022
  border-top: 1px solid hsl(var(--border) / 0.5);
3977
4023
  }
3978
4024
 
4025
+ /* Badge - generic badge styling */
4026
+ .badge {
4027
+ display: inline-flex;
4028
+ align-items: center;
4029
+ padding: 0.25rem 0.625rem;
4030
+ border-radius: 0.25rem;
4031
+ font-size: 0.75rem;
4032
+ font-weight: 500;
4033
+ white-space: nowrap;
4034
+ }
4035
+
4036
+ .badge.feasibility {
4037
+ background: hsl(var(--primary) / 0.1);
4038
+ color: hsl(var(--primary));
4039
+ }
4040
+
4041
+ .badge.effort {
4042
+ background: hsl(var(--muted));
4043
+ color: hsl(var(--foreground));
4044
+ }
4045
+
4046
+ .badge.effort.low {
4047
+ background: hsl(142 70% 50% / 0.15);
4048
+ color: hsl(142 70% 35%);
4049
+ }
4050
+
4051
+ .badge.effort.medium {
4052
+ background: hsl(30 90% 50% / 0.15);
4053
+ color: hsl(30 90% 40%);
4054
+ }
4055
+
4056
+ .badge.effort.high {
4057
+ background: hsl(0 70% 50% / 0.15);
4058
+ color: hsl(0 70% 45%);
4059
+ }
4060
+
4061
+ .badge.risk {
4062
+ background: hsl(var(--muted));
4063
+ color: hsl(var(--foreground));
4064
+ }
4065
+
4066
+ .badge.risk.low {
4067
+ background: hsl(142 70% 50% / 0.15);
4068
+ color: hsl(142 70% 35%);
4069
+ }
4070
+
4071
+ .badge.risk.medium {
4072
+ background: hsl(30 90% 50% / 0.15);
4073
+ color: hsl(30 90% 40%);
4074
+ }
4075
+
4076
+ .badge.risk.high {
4077
+ background: hsl(0 70% 50% / 0.15);
4078
+ color: hsl(0 70% 45%);
4079
+ }
4080
+
3979
4081
  /* Feasibility badge */
3980
4082
  .feasibility-badge {
3981
4083
  display: inline-flex;
@@ -1508,6 +1508,38 @@
1508
1508
  transform: translateY(0);
1509
1509
  }
1510
1510
 
1511
+ .issue-pull-btn {
1512
+ display: inline-flex;
1513
+ align-items: center;
1514
+ gap: 0.375rem;
1515
+ padding: 0.5rem 1rem;
1516
+ background: #1a1a1a;
1517
+ color: #ffffff;
1518
+ border: 1px solid #2d2d2d;
1519
+ border-radius: 0.375rem;
1520
+ font-size: 0.875rem;
1521
+ font-weight: 500;
1522
+ cursor: pointer;
1523
+ transition: all 0.15s ease;
1524
+ }
1525
+
1526
+ .issue-pull-btn:hover {
1527
+ background: #2d2d2d;
1528
+ border-color: #404040;
1529
+ transform: translateY(-1px);
1530
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
1531
+ }
1532
+
1533
+ .issue-pull-btn:active {
1534
+ transform: translateY(0);
1535
+ background: #1a1a1a;
1536
+ }
1537
+
1538
+ .issue-pull-btn:disabled {
1539
+ opacity: 0.5;
1540
+ cursor: not-allowed;
1541
+ }
1542
+
1511
1543
  /* ==========================================
1512
1544
  ISSUE STATS
1513
1545
  ========================================== */
@@ -102,7 +102,7 @@ function renderCliHistory() {
102
102
  if (cliExecutionHistory.length === 0) {
103
103
  container.innerHTML = `
104
104
  <div class="cli-history-header">
105
- <h3><i data-lucide="history" class="w-4 h-4"></i> Execution History</h3>
105
+ <h3><i data-lucide="history" class="w-4 h-4"></i> ${t('cli.executionHistory')}</h3>
106
106
  <div class="cli-history-controls">
107
107
  ${renderHistorySearch()}
108
108
  ${renderToolFilter()}
@@ -113,7 +113,7 @@ function renderCliHistory() {
113
113
  </div>
114
114
  <div class="empty-state">
115
115
  <i data-lucide="terminal" class="w-8 h-8"></i>
116
- <p>No executions yet</p>
116
+ <p>${t('cli.noExecutions')}</p>
117
117
  </div>
118
118
  `;
119
119
 
@@ -124,7 +124,7 @@ function renderCliHistory() {
124
124
  const historyHtml = filteredHistory.length === 0
125
125
  ? `<div class="empty-state">
126
126
  <i data-lucide="search-x" class="w-6 h-6"></i>
127
- <p>No matching results</p>
127
+ <p>${t('cli.noMatchingResults')}</p>
128
128
  </div>`
129
129
  : filteredHistory.map(exec => {
130
130
  const statusIcon = exec.status === 'success' ? 'check-circle' :
@@ -140,7 +140,7 @@ function renderCliHistory() {
140
140
  // Native session indicator
141
141
  const hasNative = exec.hasNativeSession || exec.nativeSessionId;
142
142
  const nativeBadge = hasNative
143
- ? `<span class="cli-native-badge" title="Native session: ${exec.nativeSessionId}">
143
+ ? `<span class="cli-native-badge" title="${t('cli.nativeSessionBadge')}: ${exec.nativeSessionId}">
144
144
  <i data-lucide="file-json" class="w-3 h-3"></i>
145
145
  </span>`
146
146
  : '';
@@ -173,14 +173,14 @@ function renderCliHistory() {
173
173
  <i data-lucide="copy" class="w-3.5 h-3.5"></i>
174
174
  </button>
175
175
  ${hasNative ? `
176
- <button class="btn-icon" onclick="event.stopPropagation(); showNativeSessionDetail('${exec.id}', '${sourceDirEscaped}')" title="View Native Session">
176
+ <button class="btn-icon" onclick="event.stopPropagation(); showNativeSessionDetail('${exec.id}', '${sourceDirEscaped}')" title="${t('cli.viewNativeSession')}">
177
177
  <i data-lucide="file-json" class="w-3.5 h-3.5"></i>
178
178
  </button>
179
179
  ` : ''}
180
- <button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail('${exec.id}', '${sourceDirEscaped}')" title="View Details">
180
+ <button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail('${exec.id}', '${sourceDirEscaped}')" title="${t('cli.viewDetails')}">
181
181
  <i data-lucide="eye" class="w-3.5 h-3.5"></i>
182
182
  </button>
183
- <button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution('${exec.id}', '${sourceDirEscaped}')" title="Delete">
183
+ <button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution('${exec.id}', '${sourceDirEscaped}')" title="${t('cli.delete')}">
184
184
  <i data-lucide="trash-2" class="w-3.5 h-3.5"></i>
185
185
  </button>
186
186
  </div>
@@ -211,7 +211,7 @@ function renderHistorySearch() {
211
211
  return `
212
212
  <input type="text"
213
213
  class="cli-history-search"
214
- placeholder="Search history..."
214
+ placeholder="${t('cli.searchHistory')}"
215
215
  value="${escapeHtml(cliHistorySearch)}"
216
216
  onkeyup="searchCliHistory(this.value)"
217
217
  oninput="searchCliHistory(this.value)">
@@ -224,7 +224,7 @@ function renderToolFilter() {
224
224
  <select class="cli-tool-filter" onchange="filterCliHistory(this.value)">
225
225
  ${tools.map(tool => `
226
226
  <option value="${tool === 'all' ? '' : tool}" ${cliHistoryFilter === (tool === 'all' ? null : tool) ? 'selected' : ''}>
227
- ${tool === 'all' ? 'All Tools' : tool.charAt(0).toUpperCase() + tool.slice(1)}
227
+ ${tool === 'all' ? t('cli.allTools') : tool.charAt(0).toUpperCase() + tool.slice(1)}
228
228
  </option>
229
229
  `).join('')}
230
230
  </select>
@@ -235,7 +235,7 @@ function renderToolFilter() {
235
235
  async function showExecutionDetail(executionId, sourceDir) {
236
236
  const conversation = await loadExecutionDetail(executionId, sourceDir);
237
237
  if (!conversation) {
238
- showRefreshToast('Conversation not found', 'error');
238
+ showRefreshToast(t('cli.conversationNotFound'), 'error');
239
239
  return;
240
240
  }
241
241
 
@@ -264,7 +264,7 @@ async function showExecutionDetail(executionId, sourceDir) {
264
264
  <div class="cli-turn-header">
265
265
  <div class="cli-turn-marker">
266
266
  <span class="cli-turn-number">${isFirst ? '▶' : '↳'} Turn ${turn.turn}</span>
267
- ${isLast ? '<span class="cli-turn-latest-badge">Latest</span>' : ''}
267
+ ${isLast ? `<span class="cli-turn-latest-badge">${t('cli.latest')}</span>` : ''}
268
268
  </div>
269
269
  <div class="cli-turn-meta">
270
270
  <span class="cli-turn-time"><i data-lucide="clock" class="w-3 h-3"></i> ${turnTime}</span>
@@ -276,12 +276,12 @@ async function showExecutionDetail(executionId, sourceDir) {
276
276
  </div>
277
277
  <div class="cli-turn-body">
278
278
  <div class="cli-detail-section cli-prompt-section">
279
- <h4><i data-lucide="user" class="w-3.5 h-3.5"></i> User Prompt</h4>
279
+ <h4><i data-lucide="user" class="w-3.5 h-3.5"></i> ${t('cli.userPrompt')}</h4>
280
280
  <pre class="cli-detail-prompt">${escapeHtml(turn.prompt)}</pre>
281
281
  </div>
282
282
  ${turn.output.stdout ? `
283
283
  <div class="cli-detail-section cli-output-section">
284
- <h4><i data-lucide="bot" class="w-3.5 h-3.5"></i> Assistant Response</h4>
284
+ <h4><i data-lucide="bot" class="w-3.5 h-3.5"></i> ${t('cli.assistantResponse')}</h4>
285
285
  <pre class="cli-detail-output">${escapeHtml(turn.output.stdout)}</pre>
286
286
  </div>
287
287
  ` : ''}
@@ -340,7 +340,7 @@ async function showExecutionDetail(executionId, sourceDir) {
340
340
  concatenatedPromptHtml = `
341
341
  <div class="cli-concat-section" id="concatPromptSection" style="display: none;">
342
342
  <div class="cli-detail-section">
343
- <h4><i data-lucide="layers" class="w-3.5 h-3.5"></i> Concatenated Prompt (sent to CLI)</h4>
343
+ <h4><i data-lucide="layers" class="w-3.5 h-3.5"></i> ${t('cli.concatenatedPrompt')}</h4>
344
344
  <div class="cli-concat-format-selector">
345
345
  <button class="btn btn-xs ${true ? 'btn-primary' : 'btn-outline'}" onclick="switchConcatFormat('plain', '${executionId}')">Plain</button>
346
346
  <button class="btn btn-xs btn-outline" onclick="switchConcatFormat('yaml', '${executionId}')">YAML</button>
@@ -372,7 +372,7 @@ async function showExecutionDetail(executionId, sourceDir) {
372
372
  ${hasNativeSession ? `
373
373
  <div class="cli-detail-native-action">
374
374
  <button class="btn btn-sm btn-primary" onclick="showNativeSessionDetail('${executionId}', '${sourceDirEscaped}')">
375
- <i data-lucide="eye" class="w-3.5 h-3.5"></i> View Full Process Conversation
375
+ <i data-lucide="eye" class="w-3.5 h-3.5"></i> ${t('cli.viewFullConversation')}
376
376
  </button>
377
377
  </div>
378
378
  ` : ''}
@@ -380,10 +380,10 @@ async function showExecutionDetail(executionId, sourceDir) {
380
380
  ${turnCount > 1 ? `
381
381
  <div class="cli-view-toggle">
382
382
  <button class="btn btn-sm btn-outline active" onclick="toggleConversationView('turns')">
383
- <i data-lucide="list" class="w-3.5 h-3.5"></i> Per-Turn View
383
+ <i data-lucide="list" class="w-3.5 h-3.5"></i> ${t('cli.perTurnView')}
384
384
  </button>
385
385
  <button class="btn btn-sm btn-outline" onclick="toggleConversationView('concat')">
386
- <i data-lucide="layers" class="w-3.5 h-3.5"></i> Concatenated View
386
+ <i data-lucide="layers" class="w-3.5 h-3.5"></i> ${t('cli.concatenatedView')}
387
387
  </button>
388
388
  </div>
389
389
  ` : ''}
@@ -393,15 +393,15 @@ async function showExecutionDetail(executionId, sourceDir) {
393
393
  ${concatenatedPromptHtml}
394
394
  <div class="cli-detail-actions">
395
395
  <button class="btn btn-sm btn-outline" onclick="copyConversationId('${executionId}')">
396
- <i data-lucide="copy" class="w-3.5 h-3.5"></i> Copy ID
396
+ <i data-lucide="copy" class="w-3.5 h-3.5"></i> ${t('cli.copyId')}
397
397
  </button>
398
398
  ${turnCount > 1 ? `
399
399
  <button class="btn btn-sm btn-outline" onclick="copyConcatenatedPrompt('${executionId}')">
400
- <i data-lucide="clipboard-copy" class="w-3.5 h-3.5"></i> Copy Full Prompt
400
+ <i data-lucide="clipboard-copy" class="w-3.5 h-3.5"></i> ${t('cli.copyFullPrompt')}
401
401
  </button>
402
402
  ` : ''}
403
403
  <button class="btn btn-sm btn-outline btn-danger" onclick="confirmDeleteExecution('${executionId}'); closeModal();">
404
- <i data-lucide="trash-2" class="w-3.5 h-3.5"></i> Delete
404
+ <i data-lucide="trash-2" class="w-3.5 h-3.5"></i> ${t('cli.delete')}
405
405
  </button>
406
406
  </div>
407
407
  `;
@@ -409,7 +409,7 @@ async function showExecutionDetail(executionId, sourceDir) {
409
409
  // Store conversation data for format switching
410
410
  window._currentConversation = conversation;
411
411
 
412
- showModal('Conversation Detail', modalContent);
412
+ showModal(t('cli.conversationDetail'), modalContent);
413
413
  }
414
414
 
415
415
  // ========== Actions ==========
@@ -433,12 +433,12 @@ function searchCliHistory(query) {
433
433
  async function refreshCliHistory() {
434
434
  await loadCliHistory();
435
435
  renderCliHistory();
436
- showRefreshToast('History refreshed', 'success');
436
+ showRefreshToast(t('cli.historyRefreshed'), 'success');
437
437
  }
438
438
 
439
439
  // ========== Delete Execution ==========
440
440
  function confirmDeleteExecution(executionId, sourceDir) {
441
- if (confirm('Delete this execution record? This action cannot be undone.')) {
441
+ if (confirm(t('cli.confirmDelete'))) {
442
442
  deleteExecution(executionId, sourceDir);
443
443
  }
444
444
  }
@@ -471,10 +471,10 @@ async function deleteExecution(executionId, sourceDir) {
471
471
  } else {
472
472
  renderCliHistory();
473
473
  }
474
- showRefreshToast('Execution deleted', 'success');
474
+ showRefreshToast(t('cli.executionDeleted'), 'success');
475
475
  } catch (err) {
476
476
  console.error('Failed to delete execution:', err);
477
- showRefreshToast('Delete failed: ' + err.message, 'error');
477
+ showRefreshToast(t('cli.deleteFailed') + ': ' + err.message, 'error');
478
478
  }
479
479
  }
480
480
 
@@ -483,10 +483,10 @@ async function copyCliExecutionId(executionId) {
483
483
  if (navigator.clipboard) {
484
484
  try {
485
485
  await navigator.clipboard.writeText(executionId);
486
- showRefreshToast('ID copied: ' + executionId, 'success');
486
+ showRefreshToast(t('cli.idCopied') + ': ' + executionId, 'success');
487
487
  } catch (err) {
488
488
  console.error('Failed to copy ID:', err);
489
- showRefreshToast('Failed to copy ID', 'error');
489
+ showRefreshToast(t('cli.failedToCopy'), 'error');
490
490
  }
491
491
  }
492
492
  }
@@ -494,16 +494,16 @@ async function copyCliExecutionId(executionId) {
494
494
  async function copyExecutionPrompt(executionId) {
495
495
  const detail = await loadExecutionDetail(executionId);
496
496
  if (!detail) {
497
- showRefreshToast('Execution not found', 'error');
497
+ showRefreshToast(t('cli.executionNotFound'), 'error');
498
498
  return;
499
499
  }
500
500
 
501
501
  if (navigator.clipboard) {
502
502
  try {
503
503
  await navigator.clipboard.writeText(detail.prompt);
504
- showRefreshToast('Prompt copied to clipboard', 'success');
504
+ showRefreshToast(t('cli.promptCopied'), 'success');
505
505
  } catch (err) {
506
- showRefreshToast('Failed to copy', 'error');
506
+ showRefreshToast(t('cli.failedToCopy'), 'error');
507
507
  }
508
508
  }
509
509
  }
@@ -512,7 +512,7 @@ async function copyConversationId(conversationId) {
512
512
  if (navigator.clipboard) {
513
513
  try {
514
514
  await navigator.clipboard.writeText(conversationId);
515
- showRefreshToast('ID copied to clipboard', 'success');
515
+ showRefreshToast(t('cli.idCopied'), 'success');
516
516
  } catch (err) {
517
517
  showRefreshToast('Failed to copy', 'error');
518
518
  }
@@ -667,7 +667,7 @@ function switchConcatFormat(format, executionId) {
667
667
  async function copyConcatenatedPrompt(executionId) {
668
668
  var conversation = window._currentConversation;
669
669
  if (!conversation) {
670
- showRefreshToast('Conversation not found', 'error');
670
+ showRefreshToast(t('cli.conversationNotFound'), 'error');
671
671
  return;
672
672
  }
673
673
 
@@ -675,7 +675,7 @@ async function copyConcatenatedPrompt(executionId) {
675
675
  if (navigator.clipboard) {
676
676
  try {
677
677
  await navigator.clipboard.writeText(prompt);
678
- showRefreshToast('Full prompt copied to clipboard', 'success');
678
+ showRefreshToast(t('cli.fullPromptCopied'), 'success');
679
679
  } catch (err) {
680
680
  showRefreshToast('Failed to copy', 'error');
681
681
  }
@@ -692,7 +692,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
692
692
  const nativeSession = await loadNativeSessionContent(executionId, sourceDir);
693
693
 
694
694
  if (!nativeSession) {
695
- showRefreshToast('Native session not found', 'error');
695
+ showRefreshToast(t('cli.nativeSessionNotFound'), 'error');
696
696
  return;
697
697
  }
698
698
 
@@ -718,7 +718,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
718
718
  <details class="turn-thinking-details">
719
719
  <summary class="turn-thinking-summary">
720
720
  <i data-lucide="brain" class="w-3 h-3"></i>
721
- 💭 Thinking Process (${turn.thoughts.length} thoughts)
721
+ 💭 ${t('cli.thinkingProcess')} (${turn.thoughts.length} ${t('cli.thoughts')})
722
722
  </summary>
723
723
  <div class="turn-thinking-content">
724
724
  <ul class="native-thoughts-list">
@@ -734,7 +734,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
734
734
  ? `<div class="native-tools-section">
735
735
  <div class="turn-tool-calls-header">
736
736
  <i data-lucide="wrench" class="w-3 h-3"></i>
737
- <strong>Tool Calls (${turn.toolCalls.length})</strong>
737
+ <strong>${t('cli.toolCalls')} (${turn.toolCalls.length})</strong>
738
738
  </div>
739
739
  <div class="native-tools-list">
740
740
  ${turn.toolCalls.map((tc, tcIdx) => `
@@ -768,11 +768,11 @@ async function showNativeSessionDetail(executionId, sourceDir) {
768
768
  <div class="native-turn-header">
769
769
  <span class="native-turn-role">
770
770
  <i data-lucide="${roleIcon}" class="w-3.5 h-3.5"></i>
771
- ${turn.role === 'user' ? 'User' : 'Assistant'}
771
+ ${turn.role === 'user' ? t('cli.user') : t('cli.assistant')}
772
772
  </span>
773
773
  <span class="native-turn-number">Turn ${turn.turnNumber}</span>
774
774
  ${tokenInfo}
775
- ${isLast ? '<span class="native-turn-latest">Latest</span>' : ''}
775
+ ${isLast ? `<span class="native-turn-latest">${t('cli.latest')}</span>` : ''}
776
776
  </div>
777
777
  <div class="native-turn-content">
778
778
  <pre>${escapeHtml(turn.content)}</pre>
@@ -788,7 +788,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
788
788
  const totalTokensHtml = nativeSession.totalTokens
789
789
  ? `<div class="native-tokens-summary">
790
790
  <i data-lucide="bar-chart-3" class="w-4 h-4"></i>
791
- <strong>Total Tokens:</strong>
791
+ <strong>${t('cli.totalTokens')}:</strong>
792
792
  ${nativeSession.totalTokens.total || 0}
793
793
  (Input: ${nativeSession.totalTokens.input || 0},
794
794
  Output: ${nativeSession.totalTokens.output || 0}
@@ -816,13 +816,13 @@ async function showNativeSessionDetail(executionId, sourceDir) {
816
816
  </div>
817
817
  <div class="native-session-actions">
818
818
  <button class="btn btn-sm btn-outline" onclick="copyNativeSessionId('${nativeSession.sessionId}')">
819
- <i data-lucide="copy" class="w-3.5 h-3.5"></i> Copy Session ID
819
+ <i data-lucide="copy" class="w-3.5 h-3.5"></i> ${t('cli.copySessionId')}
820
820
  </button>
821
821
  <button class="btn btn-sm btn-outline" onclick="copyNativeSessionPath('${executionId}')">
822
- <i data-lucide="file" class="w-3.5 h-3.5"></i> Copy File Path
822
+ <i data-lucide="file" class="w-3.5 h-3.5"></i> ${t('cli.copyFilePath')}
823
823
  </button>
824
824
  <button class="btn btn-sm btn-outline" onclick="exportNativeSession('${executionId}')">
825
- <i data-lucide="download" class="w-3.5 h-3.5"></i> Export JSON
825
+ <i data-lucide="download" class="w-3.5 h-3.5"></i> ${t('cli.exportJson')}
826
826
  </button>
827
827
  </div>
828
828
  </div>
@@ -831,7 +831,7 @@ async function showNativeSessionDetail(executionId, sourceDir) {
831
831
  // Store for export
832
832
  window._currentNativeSession = nativeSession;
833
833
 
834
- showModal('Native Session Detail', modalContent, { size: 'lg' });
834
+ showModal(t('cli.nativeSessionDetail'), modalContent, { size: 'lg' });
835
835
  }
836
836
 
837
837
  /**
@@ -841,7 +841,7 @@ async function copyNativeSessionId(sessionId) {
841
841
  if (navigator.clipboard) {
842
842
  try {
843
843
  await navigator.clipboard.writeText(sessionId);
844
- showRefreshToast('Session ID copied', 'success');
844
+ showRefreshToast(t('cli.sessionIdCopied'), 'success');
845
845
  } catch (err) {
846
846
  showRefreshToast('Failed to copy', 'error');
847
847
  }
@@ -858,13 +858,13 @@ async function copyNativeSessionPath(executionId) {
858
858
  if (navigator.clipboard) {
859
859
  try {
860
860
  await navigator.clipboard.writeText(exec.nativeSessionPath);
861
- showRefreshToast('File path copied', 'success');
861
+ showRefreshToast(t('cli.filePathCopied'), 'success');
862
862
  } catch (err) {
863
863
  showRefreshToast('Failed to copy', 'error');
864
864
  }
865
865
  }
866
866
  } else {
867
- showRefreshToast('Path not available', 'error');
867
+ showRefreshToast(t('cli.pathNotAvailable'), 'error');
868
868
  }
869
869
  }
870
870
 
@@ -874,7 +874,7 @@ async function copyNativeSessionPath(executionId) {
874
874
  function exportNativeSession(executionId) {
875
875
  const session = window._currentNativeSession;
876
876
  if (!session) {
877
- showRefreshToast('No session data', 'error');
877
+ showRefreshToast(t('cli.noSessionData'), 'error');
878
878
  return;
879
879
  }
880
880
 
@@ -887,7 +887,7 @@ function exportNativeSession(executionId) {
887
887
  a.click();
888
888
  document.body.removeChild(a);
889
889
  URL.revokeObjectURL(url);
890
- showRefreshToast('Session exported', 'success');
890
+ showRefreshToast(t('cli.sessionExported'), 'success');
891
891
  }
892
892
 
893
893
  // ========== Helpers ==========
@@ -303,6 +303,12 @@ async function refreshWorkspace() {
303
303
  liteTaskDataStore[sessionKey] = s;
304
304
  });
305
305
 
306
+ // Populate multiCliPlan sessions
307
+ (data.liteTasks?.multiCliPlan || []).forEach(s => {
308
+ const sessionKey = `multi-cli-${s.id}`.replace(/[^a-zA-Z0-9-]/g, '-');
309
+ liteTaskDataStore[sessionKey] = s;
310
+ });
311
+
306
312
  // Update global data
307
313
  window.workflowData = data;
308
314
 
@@ -827,6 +827,12 @@ async function refreshWorkspaceData(newData) {
827
827
  liteTaskDataStore[key] = s;
828
828
  });
829
829
 
830
+ // Populate multiCliPlan sessions
831
+ (newData.liteTasks?.multiCliPlan || []).forEach(s => {
832
+ const key = `multi-cli-${s.id}`.replace(/[^a-zA-Z0-9-]/g, '-');
833
+ liteTaskDataStore[key] = s;
834
+ });
835
+
830
836
  // Update UI silently
831
837
  updateStats();
832
838
  updateBadges();
@@ -60,6 +60,9 @@ async function checkForUpdatesNow() {
60
60
  btn.disabled = true;
61
61
  }
62
62
 
63
+ // Show checking state on badge
64
+ updateVersionBadge('checking');
65
+
63
66
  // Show checking notification
64
67
  console.log('[Version Check] Starting update check...');
65
68
  if (typeof addGlobalNotification === 'function') {
@@ -83,6 +86,9 @@ async function checkForUpdatesNow() {
83
86
  versionCheckData = data;
84
87
  console.log('[Version Check] Result:', data);
85
88
 
89
+ // Update badge based on result
90
+ updateVersionBadge(data.hasUpdate ? 'has-update' : 'none');
91
+
86
92
  if (data.hasUpdate) {
87
93
  // New version available
88
94
  console.log('[Version Check] Update available:', data.latestVersion);
@@ -109,6 +115,8 @@ async function checkForUpdatesNow() {
109
115
  }
110
116
  } catch (err) {
111
117
  console.error('[Version Check] Error:', err);
118
+ // Clear badge on error
119
+ updateVersionBadge('none');
112
120
  if (typeof addGlobalNotification === 'function') {
113
121
  addGlobalNotification(
114
122
  'error',
@@ -154,6 +162,9 @@ async function checkForUpdates() {
154
162
 
155
163
  versionCheckData = await res.json();
156
164
 
165
+ // Update badge
166
+ updateVersionBadge(versionCheckData.hasUpdate ? 'has-update' : 'none');
167
+
157
168
  if (versionCheckData.hasUpdate && !versionBannerDismissed) {
158
169
  showUpdateBanner(versionCheckData);
159
170
  addGlobalNotification(
@@ -299,3 +310,30 @@ function getVersionInfo() {
299
310
  function isAutoUpdateEnabled() {
300
311
  return autoUpdateEnabled;
301
312
  }
313
+
314
+ /**
315
+ * Update version badge state
316
+ * @param {string} state - 'checking', 'has-update', 'none'
317
+ */
318
+ function updateVersionBadge(state) {
319
+ const badge = document.getElementById('versionBadge');
320
+ if (!badge) return;
321
+
322
+ // Remove all state classes
323
+ badge.classList.remove('has-update', 'checking');
324
+ badge.textContent = '';
325
+
326
+ switch (state) {
327
+ case 'checking':
328
+ badge.classList.add('checking');
329
+ break;
330
+ case 'has-update':
331
+ badge.classList.add('has-update');
332
+ badge.textContent = '!';
333
+ break;
334
+ case 'none':
335
+ default:
336
+ // Hide badge
337
+ break;
338
+ }
339
+ }