issue-flow 0.16.0 → 0.17.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 (165) hide show
  1. package/dist/agent-TB6W7PT7.js +30 -0
  2. package/dist/{analyze-556KCJKZ.js → analyze-6M3KEOX7.js} +22 -22
  3. package/dist/{apply-WVV7G7WN.js → apply-ADB3ZK7W.js} +14 -14
  4. package/dist/{bench-UBFGKUHR.js → bench-FM7I7EIV.js} +23 -23
  5. package/dist/{chunk-YA6FWFYW.js → chunk-2SUFAE6X.js} +53 -11
  6. package/dist/chunk-2SUFAE6X.js.map +1 -0
  7. package/dist/{chunk-DBEMD34J.js → chunk-32JSYXEK.js} +8 -8
  8. package/dist/chunk-3R27MJ5R.js +25 -0
  9. package/dist/chunk-3R27MJ5R.js.map +1 -0
  10. package/dist/{chunk-QZOBR6YF.js → chunk-6YQT3SSM.js} +4 -4
  11. package/dist/chunk-6YQT3SSM.js.map +1 -0
  12. package/dist/{chunk-OGVWJO4S.js → chunk-7F7LGMVO.js} +3 -3
  13. package/dist/{chunk-X6GY3CM2.js → chunk-A4H7P7T7.js} +102 -102
  14. package/dist/chunk-A4H7P7T7.js.map +1 -0
  15. package/dist/{chunk-OGN2NX57.js → chunk-ANI2NTR4.js} +9 -9
  16. package/dist/{chunk-VK65RNFA.js → chunk-B3TSS7BT.js} +3 -3
  17. package/dist/chunk-D6ZBGJ3L.js +321 -0
  18. package/dist/chunk-D6ZBGJ3L.js.map +1 -0
  19. package/dist/{chunk-MXCOSPLJ.js → chunk-DGRTJD5R.js} +3 -3
  20. package/dist/{chunk-ROIIEVZH.js → chunk-DUS5ZNKL.js} +474 -361
  21. package/dist/chunk-DUS5ZNKL.js.map +1 -0
  22. package/dist/{chunk-VTF4RWS5.js → chunk-DV7HUC4Z.js} +7 -7
  23. package/dist/{chunk-OOX3RMD3.js → chunk-E6KXCV3T.js} +4 -4
  24. package/dist/{chunk-OLUOZLU5.js → chunk-HJBF4WD2.js} +1653 -1071
  25. package/dist/chunk-HJBF4WD2.js.map +1 -0
  26. package/dist/{chunk-4FUWWBTP.js → chunk-HLAPOUEM.js} +8 -8
  27. package/dist/{chunk-J2LJB2OH.js → chunk-HY5HLFDU.js} +630 -571
  28. package/dist/chunk-HY5HLFDU.js.map +1 -0
  29. package/dist/{chunk-QVLIIGBU.js → chunk-ICM463EO.js} +60 -13
  30. package/dist/chunk-ICM463EO.js.map +1 -0
  31. package/dist/{chunk-KV2K7MK2.js → chunk-ISZ54SVE.js} +9 -9
  32. package/dist/{chunk-GV2DABNZ.js → chunk-KZ5EY5XX.js} +12 -12
  33. package/dist/{chunk-SW2MF47D.js → chunk-KZXQWC7U.js} +19 -19
  34. package/dist/{chunk-2H43OVTU.js → chunk-LPWPFIIB.js} +11 -11
  35. package/dist/{chunk-EPFC4LHT.js → chunk-MI5TREN3.js} +9 -9
  36. package/dist/{chunk-R42YHLDV.js → chunk-PPZ3K4YM.js} +2 -2
  37. package/dist/{chunk-H3EYBJZU.js → chunk-QMIQR7EE.js} +10 -10
  38. package/dist/{chunk-FKWYD44M.js → chunk-QPGEFLMY.js} +2 -2
  39. package/dist/chunk-RCZJQUTC.js +196 -0
  40. package/dist/chunk-RCZJQUTC.js.map +1 -0
  41. package/dist/{chunk-NQCR3HSU.js → chunk-RNFUVKC3.js} +3 -3
  42. package/dist/{chunk-G5LACAXO.js → chunk-RYOUZ6EK.js} +2 -2
  43. package/dist/{chunk-BSBJXPLC.js → chunk-SGTTR4XW.js} +10 -10
  44. package/dist/{chunk-GVOZ6NDO.js → chunk-SOM4QA6C.js} +3 -3
  45. package/dist/{chunk-73TS2H42.js → chunk-UK4E2FUA.js} +132 -34
  46. package/dist/chunk-UK4E2FUA.js.map +1 -0
  47. package/dist/{chunk-PGN2VX4Y.js → chunk-UWDCIFTP.js} +7 -7
  48. package/dist/{chunk-MCLPSL6B.js → chunk-VE3IYNDN.js} +3 -3
  49. package/dist/{chunk-IAMIBZRF.js → chunk-WCCZJL7W.js} +2 -2
  50. package/dist/{chunk-SVDEWOUD.js → chunk-XZUEFTUP.js} +6 -6
  51. package/dist/{chunk-GPLP7EPL.js → chunk-YII4U7ZD.js} +10 -10
  52. package/dist/{chunk-GPLP7EPL.js.map → chunk-YII4U7ZD.js.map} +1 -1
  53. package/dist/{chunk-WLJVL25O.js → chunk-YUNBOUQH.js} +6 -6
  54. package/dist/{chunk-WNROH2YE.js → chunk-YVPZUN6X.js} +2 -2
  55. package/dist/{chunk-Q2TZA6AC.js → chunk-Z5O2XBWA.js} +14 -14
  56. package/dist/cli.js +57 -49
  57. package/dist/cli.js.map +1 -1
  58. package/dist/{config-UE7IP36J.js → config-KGZUPAUP.js} +13 -13
  59. package/dist/{conventions-Z3QC2NSG.js → conventions-RYN7OXJN.js} +15 -15
  60. package/dist/{diagnostics-2Z5HFQOO.js → diagnostics-HTCWF7F4.js} +7 -7
  61. package/dist/execute-QL3ZQIAP.js +37 -0
  62. package/dist/{generate-PB4L7V5N.js → generate-CX6KNHZS.js} +22 -22
  63. package/dist/{git-7MUOGVRG.js → git-A2IP32PQ.js} +2 -2
  64. package/dist/init-PDVQDRS6.js +24 -0
  65. package/dist/{operations-QDJAFZUN.js → operations-CAKIT2BO.js} +15 -15
  66. package/dist/{permissions-XVXXENVP.js → permissions-G4XCAESF.js} +4 -4
  67. package/dist/plan-PRORGS3L.js +34 -0
  68. package/dist/{policy-6WQZB6B2.js → policy-WX6O2JID.js} +14 -14
  69. package/dist/pr-27RMQI5F.js +39 -0
  70. package/dist/pr-review-VNESMAMT.js +32 -0
  71. package/dist/prd-ZNC4T5BS.js +33 -0
  72. package/dist/{ps-CX7756QG.js → ps-76L6ZAZL.js} +12 -12
  73. package/dist/{recorder-RK6XZYF3.js → recorder-N7U66HCO.js} +7 -7
  74. package/dist/{registry-POSB35Q4.js → registry-XLHHYLTR.js} +5 -5
  75. package/dist/{resume-OQJZV3JH.js → resume-VLWIE264.js} +39 -38
  76. package/dist/{resume-OQJZV3JH.js.map → resume-VLWIE264.js.map} +1 -1
  77. package/dist/review-7CREJDKB.js +35 -0
  78. package/dist/routing-VCDYHSXA.js +33 -0
  79. package/dist/run-3MPORLF5.js +56 -0
  80. package/dist/{session-publisher-VVXOCJ2S.js → session-publisher-KAJQRHNZ.js} +3 -2
  81. package/dist/{state-manager-TIC73GQY.js → state-manager-UPHO2EA2.js} +4 -4
  82. package/dist/state-manager-UPHO2EA2.js.map +1 -0
  83. package/dist/{usage-WDDNSIHP.js → usage-U7QNGCPK.js} +12 -12
  84. package/dist/{web-IPGY52AK.js → web-HUNDHCJ4.js} +20 -18
  85. package/dist/{web-IPGY52AK.js.map → web-HUNDHCJ4.js.map} +1 -1
  86. package/package.json +6 -5
  87. package/web/AGENTS.md +10 -11
  88. package/web/public/app.css +38 -0
  89. package/web/public/app.js +277 -56
  90. package/dist/agent-PMWCDWOW.js +0 -30
  91. package/dist/chunk-73TS2H42.js.map +0 -1
  92. package/dist/chunk-7Z4Y3VKM.js +0 -26
  93. package/dist/chunk-7Z4Y3VKM.js.map +0 -1
  94. package/dist/chunk-AOAQU7PD.js +0 -180
  95. package/dist/chunk-AOAQU7PD.js.map +0 -1
  96. package/dist/chunk-J2LJB2OH.js.map +0 -1
  97. package/dist/chunk-OLUOZLU5.js.map +0 -1
  98. package/dist/chunk-QVLIIGBU.js.map +0 -1
  99. package/dist/chunk-QZOBR6YF.js.map +0 -1
  100. package/dist/chunk-ROIIEVZH.js.map +0 -1
  101. package/dist/chunk-X6GY3CM2.js.map +0 -1
  102. package/dist/chunk-YA6FWFYW.js.map +0 -1
  103. package/dist/execute-QYLJ5L4T.js +0 -36
  104. package/dist/init-XBERAZ4O.js +0 -24
  105. package/dist/plan-RXOW32KY.js +0 -34
  106. package/dist/pr-3WFYAVA7.js +0 -39
  107. package/dist/pr-review-RK63ZEMM.js +0 -32
  108. package/dist/prd-LRV6IW3E.js +0 -33
  109. package/dist/review-AEFISJZD.js +0 -35
  110. package/dist/routing-EA5NJGNU.js +0 -94
  111. package/dist/routing-EA5NJGNU.js.map +0 -1
  112. package/dist/run-HSC7R33Y.js +0 -55
  113. /package/dist/{agent-PMWCDWOW.js.map → agent-TB6W7PT7.js.map} +0 -0
  114. /package/dist/{analyze-556KCJKZ.js.map → analyze-6M3KEOX7.js.map} +0 -0
  115. /package/dist/{apply-WVV7G7WN.js.map → apply-ADB3ZK7W.js.map} +0 -0
  116. /package/dist/{bench-UBFGKUHR.js.map → bench-FM7I7EIV.js.map} +0 -0
  117. /package/dist/{chunk-DBEMD34J.js.map → chunk-32JSYXEK.js.map} +0 -0
  118. /package/dist/{chunk-OGVWJO4S.js.map → chunk-7F7LGMVO.js.map} +0 -0
  119. /package/dist/{chunk-OGN2NX57.js.map → chunk-ANI2NTR4.js.map} +0 -0
  120. /package/dist/{chunk-VK65RNFA.js.map → chunk-B3TSS7BT.js.map} +0 -0
  121. /package/dist/{chunk-MXCOSPLJ.js.map → chunk-DGRTJD5R.js.map} +0 -0
  122. /package/dist/{chunk-VTF4RWS5.js.map → chunk-DV7HUC4Z.js.map} +0 -0
  123. /package/dist/{chunk-OOX3RMD3.js.map → chunk-E6KXCV3T.js.map} +0 -0
  124. /package/dist/{chunk-4FUWWBTP.js.map → chunk-HLAPOUEM.js.map} +0 -0
  125. /package/dist/{chunk-KV2K7MK2.js.map → chunk-ISZ54SVE.js.map} +0 -0
  126. /package/dist/{chunk-GV2DABNZ.js.map → chunk-KZ5EY5XX.js.map} +0 -0
  127. /package/dist/{chunk-SW2MF47D.js.map → chunk-KZXQWC7U.js.map} +0 -0
  128. /package/dist/{chunk-2H43OVTU.js.map → chunk-LPWPFIIB.js.map} +0 -0
  129. /package/dist/{chunk-EPFC4LHT.js.map → chunk-MI5TREN3.js.map} +0 -0
  130. /package/dist/{chunk-R42YHLDV.js.map → chunk-PPZ3K4YM.js.map} +0 -0
  131. /package/dist/{chunk-H3EYBJZU.js.map → chunk-QMIQR7EE.js.map} +0 -0
  132. /package/dist/{chunk-FKWYD44M.js.map → chunk-QPGEFLMY.js.map} +0 -0
  133. /package/dist/{chunk-NQCR3HSU.js.map → chunk-RNFUVKC3.js.map} +0 -0
  134. /package/dist/{chunk-G5LACAXO.js.map → chunk-RYOUZ6EK.js.map} +0 -0
  135. /package/dist/{chunk-BSBJXPLC.js.map → chunk-SGTTR4XW.js.map} +0 -0
  136. /package/dist/{chunk-GVOZ6NDO.js.map → chunk-SOM4QA6C.js.map} +0 -0
  137. /package/dist/{chunk-PGN2VX4Y.js.map → chunk-UWDCIFTP.js.map} +0 -0
  138. /package/dist/{chunk-MCLPSL6B.js.map → chunk-VE3IYNDN.js.map} +0 -0
  139. /package/dist/{chunk-IAMIBZRF.js.map → chunk-WCCZJL7W.js.map} +0 -0
  140. /package/dist/{chunk-SVDEWOUD.js.map → chunk-XZUEFTUP.js.map} +0 -0
  141. /package/dist/{chunk-WLJVL25O.js.map → chunk-YUNBOUQH.js.map} +0 -0
  142. /package/dist/{chunk-WNROH2YE.js.map → chunk-YVPZUN6X.js.map} +0 -0
  143. /package/dist/{chunk-Q2TZA6AC.js.map → chunk-Z5O2XBWA.js.map} +0 -0
  144. /package/dist/{config-UE7IP36J.js.map → config-KGZUPAUP.js.map} +0 -0
  145. /package/dist/{conventions-Z3QC2NSG.js.map → conventions-RYN7OXJN.js.map} +0 -0
  146. /package/dist/{diagnostics-2Z5HFQOO.js.map → diagnostics-HTCWF7F4.js.map} +0 -0
  147. /package/dist/{execute-QYLJ5L4T.js.map → execute-QL3ZQIAP.js.map} +0 -0
  148. /package/dist/{generate-PB4L7V5N.js.map → generate-CX6KNHZS.js.map} +0 -0
  149. /package/dist/{git-7MUOGVRG.js.map → git-A2IP32PQ.js.map} +0 -0
  150. /package/dist/{init-XBERAZ4O.js.map → init-PDVQDRS6.js.map} +0 -0
  151. /package/dist/{operations-QDJAFZUN.js.map → operations-CAKIT2BO.js.map} +0 -0
  152. /package/dist/{permissions-XVXXENVP.js.map → permissions-G4XCAESF.js.map} +0 -0
  153. /package/dist/{plan-RXOW32KY.js.map → plan-PRORGS3L.js.map} +0 -0
  154. /package/dist/{policy-6WQZB6B2.js.map → policy-WX6O2JID.js.map} +0 -0
  155. /package/dist/{pr-3WFYAVA7.js.map → pr-27RMQI5F.js.map} +0 -0
  156. /package/dist/{pr-review-RK63ZEMM.js.map → pr-review-VNESMAMT.js.map} +0 -0
  157. /package/dist/{prd-LRV6IW3E.js.map → prd-ZNC4T5BS.js.map} +0 -0
  158. /package/dist/{ps-CX7756QG.js.map → ps-76L6ZAZL.js.map} +0 -0
  159. /package/dist/{recorder-RK6XZYF3.js.map → recorder-N7U66HCO.js.map} +0 -0
  160. /package/dist/{registry-POSB35Q4.js.map → registry-XLHHYLTR.js.map} +0 -0
  161. /package/dist/{review-AEFISJZD.js.map → review-7CREJDKB.js.map} +0 -0
  162. /package/dist/{run-HSC7R33Y.js.map → routing-VCDYHSXA.js.map} +0 -0
  163. /package/dist/{session-publisher-VVXOCJ2S.js.map → run-3MPORLF5.js.map} +0 -0
  164. /package/dist/{state-manager-TIC73GQY.js.map → session-publisher-KAJQRHNZ.js.map} +0 -0
  165. /package/dist/{usage-WDDNSIHP.js.map → usage-U7QNGCPK.js.map} +0 -0
package/web/public/app.js CHANGED
@@ -4,8 +4,6 @@
4
4
  // todo texto dinâmico entra via textContent (nunca innerHTML com dados
5
5
  // do snapshot).
6
6
  (() => {
7
- 'use strict';
8
-
9
7
  const REFRESH_OPTIONS = [3, 5, 10, 30];
10
8
  const PAUSED = 0;
11
9
  const STORAGE_KEY = 'issue-flow:refresh-seconds';
@@ -129,6 +127,7 @@
129
127
  // guardar o nó levaria a uma referência morta.
130
128
  selectedDetail: null,
131
129
  configWritable: false,
130
+ configData: null,
132
131
  // Identifica o processo que serviu os assets atuais. Uma troca significa
133
132
  // que --restart-web colocou código novo no mesmo origin e exige reload.
134
133
  serverInstanceId: null,
@@ -291,7 +290,8 @@
291
290
  ...story,
292
291
  status: STORY_STATUS_LABELS[status] !== undefined ? status : 'backlog',
293
292
  stage: STORY_STAGE_LABELS[stage] !== undefined ? stage : 'pending',
294
- stageSince: story.stageSince !== null && story.stageSince !== undefined ? story.stageSince : null,
293
+ stageSince:
294
+ story.stageSince !== null && story.stageSince !== undefined ? story.stageSince : null,
295
295
  stageDetail:
296
296
  story.stageDetail !== null && story.stageDetail !== undefined ? story.stageDetail : null,
297
297
  dependencies: list(story.dependencies),
@@ -613,9 +613,7 @@
613
613
  }
614
614
 
615
615
  const nextId =
616
- resolved.session && resolved.session.sessionId != null
617
- ? resolved.session.sessionId
618
- : null;
616
+ resolved.session && resolved.session.sessionId != null ? resolved.session.sessionId : null;
619
617
  const sessionChanged = state.detailSessionId !== nextId;
620
618
  if (sessionChanged) {
621
619
  clearDetailState();
@@ -662,6 +660,12 @@
662
660
  state.snapshot = await res.json();
663
661
  render();
664
662
  }
663
+ const configUrl = 'api/config?session=' + encodeURIComponent(state.detailSessionId || '');
664
+ const configRes = await fetch(configUrl, { cache: 'no-store' });
665
+ if (configRes.ok) {
666
+ state.configData = await configRes.json();
667
+ if (state.snapshot) renderConfiguration(state.snapshot);
668
+ }
665
669
  if (state.eventsUrl) {
666
670
  const eventsRes = await fetch(state.eventsUrl, { cache: 'no-store' });
667
671
  if (!eventsRes.ok) throw new Error('HTTP ' + eventsRes.status);
@@ -714,10 +718,7 @@
714
718
  function renderDashboard(sessions) {
715
719
  const active = document.activeElement;
716
720
  const focusedId =
717
- active &&
718
- active.dataset &&
719
- els.dashboard.contains(active) &&
720
- active.dataset.sessionId
721
+ active && active.dataset && els.dashboard.contains(active) && active.dataset.sessionId
721
722
  ? active.dataset.sessionId
722
723
  : null;
723
724
 
@@ -753,20 +754,15 @@
753
754
  if (session.issueNumber !== null && session.issueNumber !== undefined) {
754
755
  titleRow.appendChild(el('span', 'dashboard-issue', '#' + session.issueNumber));
755
756
  }
756
- titleRow.appendChild(
757
- el('span', 'dashboard-title', session.issueTitle || 'Sem título'),
758
- );
757
+ titleRow.appendChild(el('span', 'dashboard-title', session.issueTitle || 'Sem título'));
759
758
  card.appendChild(titleRow);
760
759
 
761
760
  const summary = truncateText(session.issueDescription, DESCRIPTION_PREVIEW);
762
761
  card.appendChild(el('span', 'dashboard-summary muted', summary || 'Sem descrição'));
763
762
 
764
763
  const meta = el('span', 'dashboard-meta-row');
765
- meta.appendChild(
766
- el('span', null, 'Fase: ' + (session.currentPhase || '—')),
767
- );
768
- const percent =
769
- typeof session.progressPercent === 'number' ? session.progressPercent : 0;
764
+ meta.appendChild(el('span', null, 'Fase: ' + (session.currentPhase || '—')));
765
+ const percent = typeof session.progressPercent === 'number' ? session.progressPercent : 0;
770
766
  meta.appendChild(el('span', null, percent + '%'));
771
767
  const elapsed =
772
768
  typeof session.elapsedSeconds === 'number'
@@ -931,14 +927,19 @@
931
927
 
932
928
  const heading = el('p', 'issue-summary-title');
933
929
  heading.appendChild(
934
- el('span', 'mono', issue.number !== null && issue.number !== undefined ? '#' + issue.number : '—'),
930
+ el(
931
+ 'span',
932
+ 'mono',
933
+ issue.number !== null && issue.number !== undefined ? '#' + issue.number : '—',
934
+ ),
935
935
  );
936
936
  heading.appendChild(document.createTextNode(' ' + (issue.title || 'Sem título')));
937
937
  els.issueSummary.appendChild(heading);
938
938
 
939
939
  const meta = el('div', 'issue-summary-meta');
940
940
  const state = issue.state || null;
941
- const stateClass = state === 'open' ? 'state-open' : state === 'closed' ? 'state-closed' : 'state-unknown';
941
+ const stateClass =
942
+ state === 'open' ? 'state-open' : state === 'closed' ? 'state-closed' : 'state-unknown';
942
943
  meta.appendChild(el('span', 'badge ' + stateClass, state || 'estado desconhecido'));
943
944
  meta.appendChild(el('span', 'muted', 'Prioridade: Não definida'));
944
945
  els.issueSummary.appendChild(meta);
@@ -952,7 +953,9 @@
952
953
  els.issueSummary.appendChild(labelRow);
953
954
  }
954
955
 
955
- els.issueSummary.appendChild(el('p', 'issue-description', issue.description || 'Sem descrição.'));
956
+ els.issueSummary.appendChild(
957
+ el('p', 'issue-description', issue.description || 'Sem descrição.'),
958
+ );
956
959
  }
957
960
 
958
961
  function metaRow(grid, label, value, className) {
@@ -1063,6 +1066,7 @@
1063
1066
  env: 'variável de ambiente',
1064
1067
  cli: 'override da execução',
1065
1068
  fallback: 'fallback',
1069
+ recommended: 'política recomendada',
1066
1070
  };
1067
1071
  return labels[source] || source || 'não informado';
1068
1072
  }
@@ -1107,7 +1111,9 @@
1107
1111
  nowRow(
1108
1112
  summary,
1109
1113
  'Harness padrão',
1110
- (config.defaultProvider.value || '—') + ' · ' + configSourceLabel(config.defaultProvider.source),
1114
+ (config.defaultProvider.value || '—') +
1115
+ ' · ' +
1116
+ configSourceLabel(config.defaultProvider.source),
1111
1117
  );
1112
1118
  nowRow(
1113
1119
  summary,
@@ -1120,21 +1126,126 @@
1120
1126
  nowRow(summary, 'Precedência', list(config.precedence).join(' → '));
1121
1127
  els.configuration.appendChild(summary);
1122
1128
 
1129
+ const liveRouting = state.configData && state.configData.routing;
1130
+ if (liveRouting) {
1131
+ const routingSummary = el('dl', 'now-grid config-routing-summary');
1132
+ nowRow(routingSummary, 'Routing', liveRouting.mode + ' · perfil ' + liveRouting.profile);
1133
+ nowRow(
1134
+ routingSummary,
1135
+ 'Política',
1136
+ liveRouting.policy === 'recommended' ? 'recomendada (opt-in)' : 'score adaptativo',
1137
+ );
1138
+ els.configuration.appendChild(routingSummary);
1139
+
1140
+ if (state.configWritable) {
1141
+ const routingForm = el('form', 'config-form config-routing-form');
1142
+ const mode = el('select');
1143
+ mode.setAttribute('aria-label', 'Modo de routing');
1144
+ for (const value of ['off', 'shadow', 'recommend', 'active']) {
1145
+ const option = el('option', null, value);
1146
+ option.value = value;
1147
+ mode.appendChild(option);
1148
+ }
1149
+ mode.value = liveRouting.mode;
1150
+ const profile = el('select');
1151
+ profile.setAttribute('aria-label', 'Perfil de routing');
1152
+ for (const value of ['economy', 'balanced', 'quality', 'speed']) {
1153
+ const option = el('option', null, value);
1154
+ option.value = value;
1155
+ profile.appendChild(option);
1156
+ }
1157
+ profile.value = liveRouting.profile;
1158
+ const saveRouting = el('button', 'config-save', 'Salvar routing');
1159
+ saveRouting.type = 'submit';
1160
+ const applyPolicy = el(
1161
+ 'button',
1162
+ 'config-save config-policy',
1163
+ 'Aplicar política recomendada',
1164
+ );
1165
+ applyPolicy.type = 'button';
1166
+ const routingFeedback = el('span', 'muted');
1167
+ routingForm.appendChild(mode);
1168
+ routingForm.appendChild(profile);
1169
+ routingForm.appendChild(saveRouting);
1170
+ routingForm.appendChild(applyPolicy);
1171
+ routingForm.appendChild(routingFeedback);
1172
+ routingForm.addEventListener('submit', async (event) => {
1173
+ event.preventDefault();
1174
+ await saveRoutingConfig(
1175
+ { mode: mode.value, profile: profile.value },
1176
+ saveRouting,
1177
+ routingFeedback,
1178
+ );
1179
+ });
1180
+ applyPolicy.addEventListener('click', async () => {
1181
+ await saveRoutingConfig({ policy: 'recommended' }, applyPolicy, routingFeedback);
1182
+ });
1183
+ els.configuration.appendChild(routingForm);
1184
+ }
1185
+ }
1186
+
1123
1187
  const phases = el('div', 'config-phase-grid');
1124
1188
  for (const phase of list(config.phases)) {
1125
- const row = el('button', 'config-phase-row');
1126
- row.type = 'button';
1127
- row.appendChild(el('span', 'mono', phase.phase));
1128
- row.appendChild(el('span', null, phase.provider.value || '—'));
1129
- row.appendChild(el('span', null, phase.model.value || 'default do provider'));
1130
- row.appendChild(
1131
- el(
1132
- 'span',
1133
- 'muted',
1134
- configSourceLabel(phase.provider.source) + ' / ' + configSourceLabel(phase.model.source),
1135
- ),
1136
- );
1137
- row.addEventListener('click', () => openDrawer('phase', phase.phase));
1189
+ const row = el(state.configWritable ? 'form' : 'button', 'config-phase-row');
1190
+ if (!state.configWritable) row.type = 'button';
1191
+ if (state.configWritable) {
1192
+ row.classList.add('is-editable');
1193
+ const phaseButton = el('button', 'config-phase-open mono', phase.phase);
1194
+ phaseButton.type = 'button';
1195
+ phaseButton.addEventListener('click', () => openDrawer('phase', phase.phase));
1196
+ row.appendChild(phaseButton);
1197
+ const provider = el('select');
1198
+ provider.setAttribute('aria-label', 'Harness para ' + phase.phase);
1199
+ fillProviderSelect(provider, phase.provider.value || 'claude');
1200
+ const model = el('select');
1201
+ model.setAttribute('aria-label', 'Tier e modelo para ' + phase.phase);
1202
+ fillModelSelect(model, provider.value, phase.model.value || '');
1203
+ provider.addEventListener('change', () => fillModelSelect(model, provider.value, ''));
1204
+ const save = el('button', 'config-save', 'Salvar');
1205
+ save.type = 'submit';
1206
+ const feedback = el('span', 'muted config-phase-feedback');
1207
+ row.appendChild(provider);
1208
+ row.appendChild(model);
1209
+ row.appendChild(save);
1210
+ row.appendChild(feedback);
1211
+ row.addEventListener('submit', async (event) => {
1212
+ event.preventDefault();
1213
+ save.disabled = true;
1214
+ feedback.textContent = 'salvando…';
1215
+ try {
1216
+ const response = await fetch('api/config/agent', {
1217
+ method: 'POST',
1218
+ headers: { 'Content-Type': 'application/json' },
1219
+ body: JSON.stringify({
1220
+ provider: provider.value,
1221
+ model: model.value,
1222
+ phase: phase.phase,
1223
+ }),
1224
+ });
1225
+ const result = await response.json();
1226
+ if (!response.ok) throw new Error(result.error || 'falha ao salvar');
1227
+ feedback.textContent = 'salvo para a próxima execução';
1228
+ } catch (error) {
1229
+ feedback.textContent = error.message || 'falha ao salvar';
1230
+ } finally {
1231
+ save.disabled = false;
1232
+ }
1233
+ });
1234
+ } else {
1235
+ row.appendChild(el('span', 'mono', phase.phase));
1236
+ row.appendChild(el('span', null, phase.provider.value || '—'));
1237
+ row.appendChild(el('span', null, phase.model.value || 'default do provider'));
1238
+ row.appendChild(
1239
+ el(
1240
+ 'span',
1241
+ 'muted',
1242
+ configSourceLabel(phase.provider.source) +
1243
+ ' / ' +
1244
+ configSourceLabel(phase.model.source),
1245
+ ),
1246
+ );
1247
+ row.addEventListener('click', () => openDrawer('phase', phase.phase));
1248
+ }
1138
1249
  phases.appendChild(row);
1139
1250
  }
1140
1251
  els.configuration.appendChild(phases);
@@ -1182,6 +1293,68 @@
1182
1293
  els.configuration.appendChild(form);
1183
1294
  }
1184
1295
 
1296
+ function catalog() {
1297
+ return list(state.configData && state.configData.catalog);
1298
+ }
1299
+
1300
+ function fillProviderSelect(select, selected) {
1301
+ clear(select);
1302
+ const entries = catalog().filter((entry) => entry.installed && entry.authenticated);
1303
+ const providers = entries.length
1304
+ ? entries.map((entry) => entry.provider)
1305
+ : ['claude', 'codex', 'cursor', 'antigravity'];
1306
+ if (!providers.includes(selected)) providers.push(selected);
1307
+ for (const provider of providers) {
1308
+ const option = el('option', null, provider);
1309
+ option.value = provider;
1310
+ select.appendChild(option);
1311
+ }
1312
+ select.value = selected;
1313
+ }
1314
+
1315
+ function fillModelSelect(select, provider, selected) {
1316
+ clear(select);
1317
+ const defaultOption = el('option', null, 'default do provider');
1318
+ defaultOption.value = '';
1319
+ select.appendChild(defaultOption);
1320
+ const entry = catalog().find((candidate) => candidate.provider === provider);
1321
+ for (const model of list(entry && entry.models)) {
1322
+ if (!model.id) continue;
1323
+ const option = el('option', null, model.tier + ' · ' + model.id);
1324
+ option.value = model.id;
1325
+ select.appendChild(option);
1326
+ }
1327
+ if (
1328
+ selected &&
1329
+ !Array.prototype.some.call(select.options, (option) => option.value === selected)
1330
+ ) {
1331
+ const current = el('option', null, 'configurado · ' + selected);
1332
+ current.value = selected;
1333
+ select.appendChild(current);
1334
+ }
1335
+ select.value = selected || '';
1336
+ }
1337
+
1338
+ async function saveRoutingConfig(values, button, feedback) {
1339
+ button.disabled = true;
1340
+ feedback.textContent = 'salvando…';
1341
+ try {
1342
+ const response = await fetch('api/config/routing', {
1343
+ method: 'POST',
1344
+ headers: { 'Content-Type': 'application/json' },
1345
+ body: JSON.stringify(values),
1346
+ });
1347
+ const result = await response.json();
1348
+ if (!response.ok) throw new Error(result.error || 'falha ao salvar');
1349
+ state.configData.routing = Object.assign({}, state.configData.routing, values);
1350
+ feedback.textContent = 'salvo para execuções futuras';
1351
+ } catch (error) {
1352
+ feedback.textContent = error.message || 'falha ao salvar';
1353
+ } finally {
1354
+ button.disabled = false;
1355
+ }
1356
+ }
1357
+
1185
1358
  function renderPhases(snapshot) {
1186
1359
  clear(els.phases);
1187
1360
  if (snapshot.phases.length === 0) {
@@ -1191,7 +1364,9 @@
1191
1364
  for (const phase of snapshot.phases) {
1192
1365
  const item = el('li');
1193
1366
  item.className = 'detail-row';
1194
- item.appendChild(el('span', 'item-icon icon-' + phase.status, PHASE_ICONS[phase.status] || '○'));
1367
+ item.appendChild(
1368
+ el('span', 'item-icon icon-' + phase.status, PHASE_ICONS[phase.status] || '○'),
1369
+ );
1195
1370
  const main = el('div', 'item-main');
1196
1371
  main.appendChild(el('div', 'item-title', phase.name));
1197
1372
  if (phase.error) main.appendChild(el('div', 'item-error', phase.error));
@@ -1236,7 +1411,8 @@
1236
1411
  for (const story of snapshot.stories) {
1237
1412
  // stage vem com default no schema ('pending'), mas session.json gravado
1238
1413
  // antes da issue 38 pode chegar sem ele.
1239
- const storyStage = story.stage !== null && story.stage !== undefined ? story.stage : 'pending';
1414
+ const storyStage =
1415
+ story.stage !== null && story.stage !== undefined ? story.stage : 'pending';
1240
1416
  const item = el('li', storyStage === 'executing' ? 'story-executing' : null);
1241
1417
  item.classList.add('detail-row');
1242
1418
  const status = story.passes ? 'completed' : 'pending';
@@ -1249,10 +1425,15 @@
1249
1425
 
1250
1426
  // status/dependencies vêm com default no schema (backlog/[]), mas
1251
1427
  // session.json gravado antes de #29 pode chegar sem eles.
1252
- const storyStatus = story.status !== null && story.status !== undefined ? story.status : 'backlog';
1428
+ const storyStatus =
1429
+ story.status !== null && story.status !== undefined ? story.status : 'backlog';
1253
1430
  const meta = el('div', 'story-meta');
1254
1431
  meta.appendChild(
1255
- el('span', 'badge story-status-' + storyStatus, STORY_STATUS_LABELS[storyStatus] || storyStatus),
1432
+ el(
1433
+ 'span',
1434
+ 'badge story-status-' + storyStatus,
1435
+ STORY_STATUS_LABELS[storyStatus] || storyStatus,
1436
+ ),
1256
1437
  );
1257
1438
  const dependencies = story.dependencies || [];
1258
1439
  if (dependencies.length > 0) {
@@ -1295,7 +1476,11 @@
1295
1476
 
1296
1477
  const head = el('span', 'kanban-card-head');
1297
1478
  head.appendChild(
1298
- el('span', 'item-icon icon-' + (story.passes ? 'completed' : 'pending'), story.passes ? '✓' : '○'),
1479
+ el(
1480
+ 'span',
1481
+ 'item-icon icon-' + (story.passes ? 'completed' : 'pending'),
1482
+ story.passes ? '✓' : '○',
1483
+ ),
1299
1484
  );
1300
1485
  head.appendChild(el('span', 'story-id', story.id));
1301
1486
  card.appendChild(head);
@@ -1378,16 +1563,30 @@
1378
1563
  item.appendChild(title);
1379
1564
  const grid = el('dl', 'now-grid execution-grid');
1380
1565
  nowRow(grid, 'Harness', execution.agent?.harness || '—');
1381
- nowRow(grid, 'Modelo', execution.agent?.model?.resolved || execution.agent?.model?.requested || '—');
1566
+ nowRow(
1567
+ grid,
1568
+ 'Modelo',
1569
+ execution.agent?.model?.resolved || execution.agent?.model?.requested || '—',
1570
+ );
1382
1571
  nowRow(grid, 'Início', formatClock(execution.startedAt));
1383
- nowRow(grid, 'Fim', execution.finishedAt ? formatClock(execution.finishedAt) : 'em andamento');
1384
- nowRow(grid, 'Duração', metric(execution.durationMs) !== null ? formatDuration(execution.durationMs / 1000) : '—');
1572
+ nowRow(
1573
+ grid,
1574
+ 'Fim',
1575
+ execution.finishedAt ? formatClock(execution.finishedAt) : 'em andamento',
1576
+ );
1577
+ nowRow(
1578
+ grid,
1579
+ 'Duração',
1580
+ metric(execution.durationMs) !== null ? formatDuration(execution.durationMs / 1000) : '—',
1581
+ );
1385
1582
  nowRow(grid, 'Tokens', formatUsage(execution.usage || {}) || '—');
1386
1583
  nowRow(grid, 'Custo', executionCost(execution));
1387
- if (execution.correctionCycle) nowRow(grid, 'Correção', 'ciclo ' + execution.correctionCycle);
1584
+ if (execution.correctionCycle)
1585
+ nowRow(grid, 'Correção', 'ciclo ' + execution.correctionCycle);
1388
1586
  if (execution.verdict?.status) nowRow(grid, 'Veredito', execution.verdict.status);
1389
1587
  item.appendChild(grid);
1390
- if (execution.failure?.message) item.appendChild(el('p', 'item-error', execution.failure.message));
1588
+ if (execution.failure?.message)
1589
+ item.appendChild(el('p', 'item-error', execution.failure.message));
1391
1590
  timeline.appendChild(item);
1392
1591
  }
1393
1592
  body.appendChild(timeline);
@@ -1427,7 +1626,9 @@
1427
1626
  if (entries.length === 0) return;
1428
1627
  drawerSection('Diagnóstico global persistente', (body) => {
1429
1628
  const details = el('details', 'process-output');
1430
- details.appendChild(el('summary', null, entries.length + ' registro(s) em ~/.issue-flow/logs'));
1629
+ details.appendChild(
1630
+ el('summary', null, entries.length + ' registro(s) em ~/.issue-flow/logs'),
1631
+ );
1431
1632
  const output = el('pre', 'process-output-body');
1432
1633
  output.textContent = entries
1433
1634
  .slice(0, 200)
@@ -1444,7 +1645,8 @@
1444
1645
  const kind = state.selectedDetail.kind;
1445
1646
  const id = state.selectedDetail.id;
1446
1647
  const story = kind === 'story' ? getStoryById(snapshot, id) : null;
1447
- const phase = kind === 'phase' ? list(snapshot.phases).find((entry) => entry.name === id) : null;
1648
+ const phase =
1649
+ kind === 'phase' ? list(snapshot.phases).find((entry) => entry.name === id) : null;
1448
1650
  if ((kind === 'story' && story === null) || (kind === 'phase' && !phase)) {
1449
1651
  closeDrawer();
1450
1652
  return;
@@ -1457,9 +1659,15 @@
1457
1659
  const grid = el('dl', 'now-grid drawer-summary-grid');
1458
1660
  nowRow(grid, 'Início', phase.startedAt ? formatClock(phase.startedAt) : '—');
1459
1661
  nowRow(grid, 'Fim', phase.endedAt ? formatClock(phase.endedAt) : '—');
1460
- nowRow(grid, 'Duração', metric(phase.durationSeconds) !== null ? formatDuration(phase.durationSeconds) : '—');
1662
+ nowRow(
1663
+ grid,
1664
+ 'Duração',
1665
+ metric(phase.durationSeconds) !== null ? formatDuration(phase.durationSeconds) : '—',
1666
+ );
1461
1667
  nowRow(grid, 'Uso total', formatUsage(phase) || '—');
1462
- const configured = list(snapshot.configuration?.phases).find((entry) => entry.phase === phase.name);
1668
+ const configured = list(snapshot.configuration?.phases).find(
1669
+ (entry) => entry.phase === phase.name,
1670
+ );
1463
1671
  if (configured) {
1464
1672
  nowRow(grid, 'Harness efetivo', configured.provider.value || '—');
1465
1673
  nowRow(grid, 'Origem', configSourceLabel(configured.provider.source));
@@ -1499,7 +1707,8 @@
1499
1707
  return;
1500
1708
  }
1501
1709
  const items = el('ul', 'drawer-list');
1502
- for (const criterion of story.acceptanceCriteria) items.appendChild(el('li', null, criterion));
1710
+ for (const criterion of story.acceptanceCriteria)
1711
+ items.appendChild(el('li', null, criterion));
1503
1712
  body.appendChild(items);
1504
1713
  });
1505
1714
 
@@ -1613,9 +1822,7 @@
1613
1822
  function renderLogs(snapshot) {
1614
1823
  clear(els.logs);
1615
1824
  const filter = state.logFilter;
1616
- const entries = snapshot.logs.filter(
1617
- (entry) => filter === 'all' || entry.level === filter,
1618
- );
1825
+ const entries = snapshot.logs.filter((entry) => filter === 'all' || entry.level === filter);
1619
1826
  if (entries.length === 0) {
1620
1827
  els.logs.appendChild(el('p', 'empty', 'Nenhum log para exibir.'));
1621
1828
  return;
@@ -1659,9 +1866,20 @@
1659
1866
  case 'agent:activity':
1660
1867
  return 'Atividade recebida de ' + event.provider;
1661
1868
  case 'agent:result':
1662
- return event.provider + (event.success ? ' concluiu a tentativa' : ' falhou: ' + (event.failureKind || 'desconhecida'));
1869
+ return (
1870
+ event.provider +
1871
+ (event.success
1872
+ ? ' concluiu a tentativa'
1873
+ : ' falhou: ' + (event.failureKind || 'desconhecida'))
1874
+ );
1663
1875
  case 'failover':
1664
- return 'Failover de ' + event.from + ' para ' + event.to + (event.reason ? ': ' + event.reason : '');
1876
+ return (
1877
+ 'Failover de ' +
1878
+ event.from +
1879
+ ' para ' +
1880
+ event.to +
1881
+ (event.reason ? ': ' + event.reason : '')
1882
+ );
1665
1883
  case 'correction:cycle':
1666
1884
  return 'Ciclo de correção ' + event.cycle + '/' + event.maxCycles;
1667
1885
  case 'log':
@@ -1791,7 +2009,10 @@
1791
2009
  serverInstanceChanged(healthRes);
1792
2010
  const health = await healthRes.json();
1793
2011
  renderMonitorVersion(health.version);
1794
- state.configWritable = list(health.capabilities).includes('config:agent:write');
2012
+ const capabilities = list(health.capabilities);
2013
+ state.configWritable =
2014
+ capabilities.includes('config:agent:write') &&
2015
+ capabilities.includes('config:routing:write');
1795
2016
  const suggested = Number(health.refreshSeconds);
1796
2017
  if (stored === null && Number.isFinite(suggested) && suggested > 0) {
1797
2018
  state.refreshSeconds = suggested;
@@ -1,30 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- AGENT_COMMAND_SCHEMA_VERSION,
4
- persistFirstAgentChoice,
5
- runAgent,
6
- runAgentUse,
7
- writeAgentPreference
8
- } from "./chunk-PGN2VX4Y.js";
9
- import "./chunk-J2LJB2OH.js";
10
- import "./chunk-VTF4RWS5.js";
11
- import "./chunk-SVDEWOUD.js";
12
- import "./chunk-ROIIEVZH.js";
13
- import "./chunk-FKWYD44M.js";
14
- import "./chunk-HAKDLR6N.js";
15
- import "./chunk-WNROH2YE.js";
16
- import "./chunk-GPLP7EPL.js";
17
- import "./chunk-P3LRUNC6.js";
18
- import "./chunk-R42YHLDV.js";
19
- import "./chunk-GVOZ6NDO.js";
20
- import "./chunk-QVLIIGBU.js";
21
- import "./chunk-7Z4Y3VKM.js";
22
- import "./chunk-XEYH6ZZI.js";
23
- export {
24
- AGENT_COMMAND_SCHEMA_VERSION,
25
- persistFirstAgentChoice,
26
- runAgent,
27
- runAgentUse,
28
- writeAgentPreference
29
- };
30
- //# sourceMappingURL=agent-PMWCDWOW.js.map