great-cto 3.10.0 → 3.12.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.
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "great_cto",
|
|
3
3
|
"id": "great_cto",
|
|
4
4
|
"description": "Engineering process for solo founders and teams up to 50 engineers. Agents do architecture, code review, QA, and security. You make two decisions per feature.",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.12.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Great CTO",
|
|
8
8
|
"url": "https://github.com/avelikiy/great_cto"
|
|
@@ -146,8 +146,17 @@ function readVerdicts(cwd = null, health = null) {
|
|
|
146
146
|
// verdict in that position, and `\S+` accepted it — producing keys like
|
|
147
147
|
// `{"v":1,"ts":"202|qa-engineer` that could never match a verdict.
|
|
148
148
|
// Lines from that era are skipped here instead of being half-parsed.
|
|
149
|
-
const m = line.match(/^(\d{4}-\d{2}-\d{2}T\S+)\s+(\S+)\s+(\d+\.?\d*)(?:\s|$)/);
|
|
149
|
+
const m = line.match(/^(\d{4}-\d{2}-\d{2}T\S+)\s+(\S+)\s+(\d+\.?\d*)(?:\s+turns=(\d+))?(?:\s|$)/);
|
|
150
150
|
if (!m) continue;
|
|
151
|
+
// A cost whose turn count is a whole session is not one agent's cost.
|
|
152
|
+
//
|
|
153
|
+
// The writer records those as `(unattributed)` now, but lines already in
|
|
154
|
+
// this file predate that and carry a real agent name — the board showed
|
|
155
|
+
// $3,385 against four qa-engineer runs under a `measured` label, which is
|
|
156
|
+
// a wrong number wearing the badge of a right one. Skipped here so the
|
|
157
|
+
// history stops asserting it; the line stays on disk because the spend was
|
|
158
|
+
// real and deleting it would understate the total.
|
|
159
|
+
if (m[4] && Number(m[4]) > 400) continue;
|
|
151
160
|
const usd = parseFloat(m[3]);
|
|
152
161
|
// A recorded zero is `log-verdict.sh` writing through whatever the agent
|
|
153
162
|
// reported, which is nothing. Enriching a zero verdict with a zero from
|
|
@@ -140,13 +140,24 @@
|
|
|
140
140
|
Legal 10px: --fs-eyebrow, and only for mono uppercase labels with tracking.
|
|
141
141
|
10px in sans body text is not a size, it is a mistake. */
|
|
142
142
|
:root {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
143
|
+
/* The bottom of the ramp was lifted one step on 2026-08-26, and the top was
|
|
144
|
+
not. Measured on the Inbox before the change: 42% of all rendered text sat
|
|
145
|
+
at 11px or smaller, and 11px alone carried 37% of it across 895 elements.
|
|
146
|
+
A step defined as "metadata, counts, timestamps" was doing the work of body
|
|
147
|
+
text — the role written here and the role in use had come apart, and the
|
|
148
|
+
operator reported exactly that: small text, hard to read.
|
|
149
|
+
|
|
150
|
+
Titles were left where they were on purpose. The same report called the
|
|
151
|
+
screen overloaded, and enlarging headings would have answered one complaint
|
|
152
|
+
by worsening the other. Density is fixed by showing less, not by shrinking
|
|
153
|
+
what is shown. */
|
|
154
|
+
--fs-eyebrow: 11px; /* mono uppercase label, tracking 0.08–0.1em */
|
|
155
|
+
--fs-caption: 12px; /* metadata, counts, timestamps */
|
|
156
|
+
--fs-small: 13px; /* table cells, secondary meta, chips */
|
|
157
|
+
--fs-body: 14px; /* dense body: cards, list rows, form fields */
|
|
158
|
+
--fs-base: 15px; /* document base / longform prose */
|
|
159
|
+
--fs-title-s: 16px; /* card or section heading (h3 role) */
|
|
160
|
+
--fs-title-m: 19px; /* region heading (h2 role) */
|
|
150
161
|
--fs-title-l: 22px; /* page heading (h1 role) */
|
|
151
162
|
|
|
152
163
|
--fs-num-s: 24px; /* inline stat */
|
|
@@ -367,6 +378,14 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
367
378
|
.proj-switch .star { color: var(--accent); font-size: 16px; }
|
|
368
379
|
.proj-switch .name { font-weight: 600; font-size: var(--fs-base); }
|
|
369
380
|
.proj-switch .sw-meta { flex: 1; display: flex; flex-direction: column; gap: 1px; }
|
|
381
|
+
.sw-ancestry[hidden] { display: none; }
|
|
382
|
+
.sw-ancestry { font-size: var(--fs-eyebrow); color: var(--text3);
|
|
383
|
+
line-height: 1.35; margin-top: 2px; word-break: break-word;
|
|
384
|
+
/* Two lines at most: this is context, and context that pushes the navigation
|
|
385
|
+
down has stopped being context. The full wire value is on the title. */
|
|
386
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
387
|
+
overflow: hidden;
|
|
388
|
+
}
|
|
370
389
|
.proj-switch .sw-arch { font-size: var(--fs-eyebrow); color: var(--text3); font-weight: 400; letter-spacing: 0.03em; }
|
|
371
390
|
.proj-switch .chev {
|
|
372
391
|
color: var(--text3); width: 12px; height: 12px;
|
|
@@ -2647,6 +2666,7 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
2647
2666
|
<div class="sw-meta">
|
|
2648
2667
|
<span class="name" id="project-name">—</span>
|
|
2649
2668
|
<span class="sw-arch" id="proj-switch-arch"></span>
|
|
2669
|
+
<span class="sw-ancestry" id="proj-ancestry" hidden></span>
|
|
2650
2670
|
</div>
|
|
2651
2671
|
<svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg>
|
|
2652
2672
|
<div class="proj-menu" id="proj-menu" onclick="event.stopPropagation()">
|
|
@@ -2774,8 +2794,16 @@ h1, h2, h3, h4 { font-weight: 600; font-family: var(--sans); }
|
|
|
2774
2794
|
</div>
|
|
2775
2795
|
</div>
|
|
2776
2796
|
|
|
2777
|
-
<!--
|
|
2778
|
-
|
|
2797
|
+
<!-- Project archetype / compliance / phase used to be a full-width mono
|
|
2798
|
+
row here, between the KPI tiles and the pipeline. On a screen whose
|
|
2799
|
+
title is "what needs your decision" it answered no question the page
|
|
2800
|
+
asks: it is configuration, it does not change day to day, and it was
|
|
2801
|
+
one of three stacked strips competing with the two that ARE
|
|
2802
|
+
actionable. Moved onto the sidebar project block, where the archetype
|
|
2803
|
+
was already shown — same information, one place, and the stack of
|
|
2804
|
+
strips on this page goes from three to two.
|
|
2805
|
+
Not deleted: `PROJECT.md` is not in the Docs list, so compliance and
|
|
2806
|
+
phase would have become unreachable. -->
|
|
2779
2807
|
<!-- Tool failure rate watchdog warning -->
|
|
2780
2808
|
<div id="tool-failure-rate" style="display:none;font-size:var(--fs-small);color:var(--status-blocked,#f87171);background:rgba(248,113,113,0.08);padding:6px 10px;border-radius:6px;margin-bottom:10px;"></div>
|
|
2781
2809
|
|
|
@@ -3501,12 +3529,32 @@ async function refreshHeartbeat() {
|
|
|
3501
3529
|
if (!h) return;
|
|
3502
3530
|
|
|
3503
3531
|
// Goal ancestry banner
|
|
3504
|
-
const bannerEl = document.getElementById('
|
|
3532
|
+
const bannerEl = document.getElementById('proj-ancestry');
|
|
3505
3533
|
if (bannerEl && h.goal_ancestry) {
|
|
3506
|
-
|
|
3507
|
-
|
|
3534
|
+
// `[archetype:x] [compliance:[a, b]] [phase:y]` → `x · a, b · y`.
|
|
3535
|
+
//
|
|
3536
|
+
// Parsed rather than regex-chained. The value NESTS — `compliance:[...]`
|
|
3537
|
+
// sits inside its own brackets — and a first attempt that stripped `[` and
|
|
3538
|
+
// `]` globally produced `developer-tools [openssf, api-stability,
|
|
3539
|
+
// soc2-type-2 implementation`: an unbalanced bracket and a lost separator.
|
|
3540
|
+
// The wire format is how the pipeline passes this between stages; rendering
|
|
3541
|
+
// it verbatim is most of why the row read as debug output.
|
|
3542
|
+
const parts = [];
|
|
3543
|
+
const re = /\[([a-z_]+):((?:[^\[\]]|\[[^\]]*\])*)\]/g;
|
|
3544
|
+
let m;
|
|
3545
|
+
while ((m = re.exec(String(h.goal_ancestry))) !== null) {
|
|
3546
|
+
const v = m[2].replace(/^\[|\]$/g, '').trim();
|
|
3547
|
+
if (v) parts.push(v);
|
|
3548
|
+
}
|
|
3549
|
+
bannerEl.textContent = parts.length ? parts.join(' · ') : String(h.goal_ancestry);
|
|
3550
|
+
bannerEl.title = h.goal_ancestry; // the exact wire value stays one hover away
|
|
3551
|
+
// `''`, not `'block'`: an inline display beats the stylesheet, and the
|
|
3552
|
+
// stylesheet is what applies the two-line clamp. Setting it here silently
|
|
3553
|
+
// disabled the clamp and the block ran to three lines, pushing the
|
|
3554
|
+
// navigation down — the opposite of the reason it was moved here.
|
|
3555
|
+
bannerEl.hidden = false;
|
|
3508
3556
|
} else if (bannerEl) {
|
|
3509
|
-
bannerEl.
|
|
3557
|
+
bannerEl.hidden = true;
|
|
3510
3558
|
}
|
|
3511
3559
|
|
|
3512
3560
|
// Tool failure rate warning
|
package/package.json
CHANGED