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.
|
|
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
|
-
.
|
|
3060
|
-
.
|
|
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"
|
|
3516
|
-
<
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
</
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
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
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
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')
|
|
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
|
|
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-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
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