great-cto 3.27.0 → 3.27.1

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "great-cto",
3
3
  "description": "You already have the agent. This is everything around it. great_cto runs Claude Code as a pipeline of 70 specialist agents \u2014 an independent model checks each stage before the next builds on it, spending caps refuse rather than warn, and three decisions stay yours: what gets built, how, and whether it ships.",
4
- "version": "3.27.0",
4
+ "version": "3.27.1",
5
5
  "author": {
6
6
  "name": "Alexander Velikiy",
7
7
  "url": "https://hashnode.com/@Greatcto"
@@ -3035,6 +3035,41 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
3035
3035
  @media (prefers-reduced-motion: reduce) {
3036
3036
  *, *::before, *::after { transition-duration: 1ms !important; animation-duration: 1ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
3037
3037
  }
3038
+ /* ── Fidelity pass (v3.27.1): the density the design canvas draws. These come
3039
+ after the rules they override — same specificity, later wins. ── */
3040
+ .metric-card { padding: 14px 16px; }
3041
+ .metric-card::before { display: none; }
3042
+ .metric-num { font-size: var(--fs-num-m); }
3043
+ .metric-label { margin-top: 6px; }
3044
+ .inbox-greet { font-family: var(--sans); font-size: var(--fs-small); color: var(--text2); line-height: 1.5; margin: 0 0 12px; font-weight: 400; letter-spacing: 0; }
3045
+ .inbox-row { padding: 8px 12px; gap: 12px; }
3046
+ .inbox-row .ttl { font-size: var(--fs-small); }
3047
+ /* A stalled task is one line: id · reason · title · agent, and the re-run button
3048
+ sits at the row's right instead of on a second grid row under it. */
3049
+ .inbox-row { grid-template-columns: 110px 1fr auto auto; align-items: center; }
3050
+ .inbox-row .ttl { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
3051
+ .inbox-row .ttl > :first-child { display: inline; }
3052
+ .inbox-row .ttl .why { display: inline-block; font-size: var(--fs-eyebrow); padding: 0 6px; line-height: 18px; white-space: nowrap; }
3053
+ .inbox-row .ttl .meta { margin-top: 0; }
3054
+ .inbox-row .ttl .ttl-desc { flex-basis: 100%; -webkit-line-clamp: 1; margin-top: 0; }
3055
+ .inbox-row .id { padding-top: 0; }
3056
+ .agent-row .budget-chip { display: block; font-size: var(--fs-eyebrow); line-height: 14px; padding: 0 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 96px; margin-left: auto; }
3057
+ .inbox-section-head h3 { font-size: var(--fs-small); }
3058
+ .fleet-title-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
3059
+ .fleet-controls-row { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
3060
+ .fleet-controls-row input[type="search"] { width: 260px; max-width: 100%; background: var(--bg-muted); border: 1px solid var(--border); color: var(--text); font-family: var(--mono); font-size: var(--fs-small); padding: 6px 10px; }
3061
+ .fleet-controls-row select { background: var(--bg-muted); border: 1px solid var(--border); color: var(--text); font-family: var(--mono); font-size: var(--fs-small); padding: 5px 8px; }
3062
+ .fleet-list { padding: 0; margin: 0; list-style: none; }
3063
+ .fleet-list > li { margin: 0; }
3064
+ .fleet-head, .agent-row { display: grid; grid-template-columns: 10px minmax(200px, 1fr) minmax(220px, 1.3fr) 130px 48px 56px 100px 16px; gap: 12px; align-items: center; }
3065
+ .fleet-head { padding: 6px 12px; font-size: var(--fs-eyebrow); letter-spacing: .08em; text-transform: uppercase; color: var(--text2); border-bottom: 1px solid var(--border); }
3066
+ .agent-row { min-height: 36px; padding: 4px 12px; border-radius: 0; border: none; border-bottom: 1px solid var(--border); width: 100%; }
3067
+ .agent-row .ar-name { font-size: var(--fs-small); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
3068
+ .agent-row .ar-posture { display: flex; gap: 6px; flex-wrap: nowrap; overflow: hidden; }
3069
+ .agent-row .ar-status { width: 6px; height: 6px; border-radius: 50%; }
3070
+ .agent-row .ar-chev { color: var(--text3); }
3071
+ .budgets-table .bt-desc { display: none; }
3072
+ .mp-card { padding: 14px 16px; }
3038
3073
  /* ── 768–1199: the sidebar becomes a 56px icon rail (DESIGN §9). Labels leave
3039
3074
  the screen but not the element — every nav item carries its name as
3040
3075
  aria-label and title. The Views block and the switcher's text go with the
@@ -3056,8 +3091,15 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
3056
3091
 
3057
3092
  .harness-hosts, .so-options { grid-template-columns: 1fr; }
3058
3093
 
3059
- .ar-cells { grid-template-columns: 1fr auto; }
3060
- .ar-posture { grid-column: 1 / -1; }
3094
+ .fleet-head { display: none; }
3095
+ .agent-row { grid-template-columns: 10px 1fr auto auto auto 16px; grid-template-areas: "dot name name name name chev" "dot posture posture posture posture chev" "dot last runs pass spend chev"; row-gap: 4px; padding: 8px 12px; }
3096
+ .agent-row .ar-status { grid-area: dot; }
3097
+ .agent-row .ar-name { grid-area: name; white-space: normal; }
3098
+ .agent-row .ar-posture { grid-area: posture; flex-wrap: wrap; }
3099
+ .agent-row .ar-last { grid-area: last; }
3100
+ .agent-row .ar-chev { grid-area: chev; }
3101
+ .fleet-controls-row { flex-wrap: wrap; }
3102
+ .fleet-controls-row input[type="search"] { width: 100%; }
3061
3103
 
3062
3104
  /* The one asymmetry DESIGN §3.2 draws: an expensive or unclassified gate's
3063
3105
  Reject/Approve stack full-width at phone width; a routine gate's may sit
@@ -3319,6 +3361,10 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
3319
3361
  <!-- Inbox -->
3320
3362
  <div class="panel active" id="panel-inbox">
3321
3363
  <div class="inbox-page">
3364
+ <!-- Fidelity pass (v3.27.1): the design's header is the screen's name and
3365
+ its count; the sentence the board used to shout in 52px display
3366
+ type is still said, one line, muted, because it carries the stall. -->
3367
+ <div class="panel-head" style="margin-bottom:6px"><h1 class="page-title" style="margin:0">Decisions <span id="decisions-count" class="muted" style="font-weight:400;font-size:var(--fs-title-s)"></span></h1></div>
3322
3368
  <div class="inbox-greet" id="inbox-greet">Good morning. Here's what needs your decision.</div>
3323
3369
  <!-- Top rung of the evidence ladder: are the bytes that were reviewed
3324
3370
  still the bytes in the tree? Hidden while they match — and now only
@@ -3507,34 +3553,22 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
3507
3553
  the redesign: a count of installed agents is not a decision (brief,
3508
3554
  "What must NOT be on the board"). The view title carries the one
3509
3555
  number that is — how many need attention, of how many. -->
3510
- <section aria-label="Fleet summary">
3511
- <h1 class="page-title" id="fleet-view-title">Fleet</h1>
3556
+ <section aria-label="Fleet summary" class="fleet-title-row">
3557
+ <h1 class="page-title" id="fleet-view-title" style="margin:0">Fleet</h1>
3512
3558
  </section>
3513
3559
 
3514
3560
  <!-- §3.1 Fleet controls -->
3515
- <section aria-label="Fleet controls" style="margin-top:20px">
3516
- <div class="mp-card fleet-controls" style="display:flex;flex-wrap:wrap;align-items:center;gap:12px 20px;padding:8px 12px">
3517
- <div class="fleet-search">
3518
- <input type="search" id="fleet-search" placeholder="Filter agents (press / to focus)" aria-label="Filter agents by slug" />
3519
- <span class="search-hint"><kbd>/</kbd> focus · <kbd>Enter</kbd> open · <kbd>Esc</kbd> close</span>
3520
- </div>
3521
- <!-- The Domain / Activity / Health facet chips left with the redesign:
3522
- domain is the grouping, activity and health are the saved views in
3523
- the sidebar (DESIGN §5 — five views, not user-creatable). The
3524
- functions stay for the drawer's deep links. -->
3525
- <div class="fleet-sort">
3526
- <label for="fleet-sort-by">Sort by</label>
3527
- <select id="fleet-sort-by">
3528
- <option value="runs_30d">runs (30d)</option>
3529
- <option value="last_run">last run</option>
3530
- <option value="success_rate">success rate</option>
3531
- <option value="savings_x">savings ×</option>
3532
- <option value="llm_usd_30d_est">LLM spend (30d)</option>
3533
- <option value="slug">slug A→Z</option>
3534
- </select>
3535
- <button type="button" id="fleet-reset-filters">Reset filters</button>
3536
- </div>
3537
- </div>
3561
+ <section aria-label="Fleet controls" class="fleet-controls-row">
3562
+ <input type="search" id="fleet-search" placeholder="Filter agents ( / )" aria-label="Filter agents by slug" />
3563
+ <label for="fleet-sort-by" class="muted cap">Sort</label>
3564
+ <select id="fleet-sort-by">
3565
+ <option value="runs_30d">runs (30d)</option>
3566
+ <option value="last_run">last run</option>
3567
+ <option value="success_rate">success rate</option>
3568
+ <option value="llm_usd_30d_est">LLM spend (30d)</option>
3569
+ <option value="slug">slug A→Z</option>
3570
+ </select>
3571
+ <button type="button" id="fleet-reset-filters" class="btn-ghost-sm">Reset</button>
3538
3572
  </section>
3539
3573
 
3540
3574
  <!-- §3.1 Fleet list -->
@@ -3621,16 +3655,11 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
3621
3655
  needs the button to declare one. -->
3622
3656
  <div class="mp-section-label" style="margin-top:24px">Agent budgets</div>
3623
3657
  <div id="agent-budgets" class="mp-card" style="padding:12px 16px;font-size:var(--fs-small);margin-bottom:4px;"></div>
3624
- <div class="mp-section-label" id="mp-cost-label" style="margin-top:24px">Cost · last 30 days</div>
3625
- <div class="mp-card cost-panel" id="cost-panel">
3626
- <div class="cost-empty">Loading…</div>
3627
- </div>
3628
- <p class="muted" style="max-width:70ch;margin:14px 0 12px">
3629
- A cap on what one agent may spend. When measured spend passes it, the pipeline
3630
- refuses to dispatch that agent and says so — it does not fail quietly.
3631
- Spend is measured from verdicts that carry a cost; while none does, the cap
3632
- cannot fire and says that too. An estimate never refuses.
3633
- </p>
3658
+ <!-- The old cost panel (four tiles: 'vs human team', a projected month, a
3659
+ daily burn, an empty chart) left in the fidelity pass — a forecast and a
3660
+ human-team comparison are two of the brief's refusals, and the
3661
+ Ledger head already carries spend with its provenance. -->
3662
+
3634
3663
  <!-- Whether the judge is connected at all. Without a key nothing breaks
3635
3664
  — every stage is scored `unverifiable`, honestly — but "not
3636
3665
  connected" and "nothing to check" read the same from here, and the
@@ -3957,6 +3986,7 @@ function gateChip(t) {
3957
3986
  }
3958
3987
  function renderInbox(d) {
3959
3988
  inboxSecondOpinion = d?.second_opinion || null;
3989
+ { const c = document.getElementById('decisions-count'); const n = (d?.pending_gates || []).length; if (c) c.textContent = n ? `${n} waiting` : 'nothing waiting'; }
3960
3990
  for (const g of (d?.pending_gates || [])) if (g?.id && g.reversibility) GATE_REVERSIBILITY[g.id] = g.reversibility;
3961
3991
  if (d && Array.isArray(d.pending_gates)) d = { ...d, pending_gates: sortGatesByCostOfUndo(d.pending_gates) };
3962
3992
  // Kept so renderResume can ask what this section is already showing, rather
@@ -8201,7 +8231,7 @@ function switchTab(id, el) {
8201
8231
  // promised 50 unread and the screen showed settings. Declared and not
8202
8232
  // consumed, in the UI this time.
8203
8233
  if (lid === 'notifications') loadNotifHistory();
8204
- if (lid === 'budgets') { loadBudgetsPage(); refreshCost(); }
8234
+ if (lid === 'budgets') loadBudgetsPage();
8205
8235
  if (lid === 'agents') {
8206
8236
  // pqsd(), not pqs(): this call omitted `days` entirely, so the server applied
8207
8237
  // its 30-day default and overwrote whatever window the period chips had
@@ -8530,7 +8560,8 @@ function renderFleetList() {
8530
8560
  const order = [...DOMAINS, ...Object.keys(byDomain).filter((d) => !DOMAINS.includes(d))];
8531
8561
  const expanded = order.filter((d) => (byDomain[d] || []).length);
8532
8562
  const collapsed = order.filter((d) => !(byDomain[d] || []).length && totals[d]);
8533
- const rows = expanded.map((d) => `
8563
+ const head = `<li class="fleet-head" aria-hidden="true"><span></span><span>Agent</span><span>Posture</span><span>Last verdict</span><span class="tab">Runs</span><span class="tab">Pass</span><span class="tab">30d $</span><span></span></li>`;
8564
+ const rows = head + expanded.map((d) => `
8534
8565
  <li class="fleet-group-head"><span>${esc(d)} · ${byDomain[d].length} of ${totals[d] || 0}</span></li>
8535
8566
  ${byDomain[d].map(agentRowHtml).join('')}`).join('');
8536
8567
  const tail = collapsed.length
@@ -8586,18 +8617,12 @@ function agentRowHtml(a) {
8586
8617
  onclick="openAgentDrawer('${esc(a.slug)}')"
8587
8618
  onkeydown="if(event.key==='Enter'){event.preventDefault();openAgentDrawer('${esc(a.slug)}')}">
8588
8619
  <span class="ar-status" aria-hidden="true"></span>
8589
- <span class="ar-body">
8590
- <span class="ar-name">${esc(a.slug)} <span class="mono cap muted" style="font-weight:400">${model}</span></span>
8591
- <span class="ar-cells">
8592
- <span class="ar-posture">${postureChips(a)}</span>
8593
- <span class="mono cap ar-last">${last}</span>
8594
- <span class="mono cap tab" title="runs in the last 30 days">${runs}</span>
8595
- <span class="mono cap tab" title="pass rate over those runs">${pass}</span>
8596
- <span class="mono cap tab" title="LLM spend, last 30 days">${spend}</span>
8597
- ${budgetChip(a.budget)}
8598
- ${a.retired ? '<span style="color:var(--agent-retired)">retired</span>' : ''}
8599
- </span>
8600
- </span>
8620
+ <span class="ar-name">${esc(a.slug)} <span class="mono cap muted" style="font-weight:400">${model}</span>${a.retired ? ' <span class="cap" style="color:var(--agent-retired)">retired</span>' : ''}</span>
8621
+ <span class="ar-posture">${postureChips(a)}</span>
8622
+ <span class="mono cap ar-last">${last}</span>
8623
+ <span class="mono cap tab" title="runs in the last 30 days">${runs}</span>
8624
+ <span class="mono cap tab" title="pass rate over those runs">${pass}</span>
8625
+ <span class="mono cap tab" title="LLM spend, last 30 days">${spend}${budgetChip(a.budget)}</span>
8601
8626
  <span class="ar-chev" aria-hidden="true">›</span>
8602
8627
  </button>
8603
8628
  </li>`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "great-cto",
3
- "version": "3.27.0",
3
+ "version": "3.27.1",
4
4
  "description": "One command install for the great_cto Claude Code plugin. Auto-detects your stack, picks the right archetype, bootstraps PROJECT.md.",
5
5
  "keywords": [
6
6
  "claude-code",