Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion apps/website/qa/agents-spec-contract.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,12 @@ assert.ok(triModule && HUD_VIEWS.includes('tri'), 'TRI (the app inside the game)
assert.equal(triModule.key, 'r', 'TRI opens on r: digits spent, t is TOOLS, p is PROJECT')
assert.ok(triModule.en.hint.includes('(key r)') && triModule.ru.hint.includes('(клавиша r)'), 'TRI names its letter key in both hints')
for (const lang of ['en', 'ru']) assert.ok(triModule[lang].name && triModule[lang].body.length > 40, `tri: ${lang} copy missing`)
assert.equal(HUD_KEYS.slice(0, HUD_VIEWS.length).join(''), '1234567890tpr', 'the rail keys are 1-9, 0, t, p, r in that order')
const lanesModule = MODULES.find((m) => m.tab === 'lanes')
assert.ok(lanesModule && HUD_VIEWS.includes('lanes'), 'LANES (the swarm\'s width) is a module and a view')
assert.equal(lanesModule.key, 'l', 'LANES opens on l: digits spent, t is TOOLS, p is PROJECT, r is TRI')
assert.ok(lanesModule.en.hint.includes('(key l)') && lanesModule.ru.hint.includes('(клавиша l)'), 'LANES names its letter key in both hints')
for (const lang of ['en', 'ru']) assert.ok(lanesModule[lang].name && lanesModule[lang].body.length > 40, `lanes: ${lang} copy missing`)
assert.equal(HUD_KEYS.slice(0, HUD_VIEWS.length).join(''), '1234567890tprl', 'the rail keys are 1-9, 0, t, p, r, l in that order')

// 6. Translations are connected through .t27 contract specs, never hardcoded.
// Every specs/i18n/*.t27 the corpus carries is in both catalogs' i18n lists
Expand Down
7 changes: 6 additions & 1 deletion apps/website/scripts/agents-from-specs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,12 @@ export function buildSpecCatalogs({ skillSpecs, cronSpecs, agentSpecs = [], func
collisions,
// Grouping the navigator shows: tri commands by owning letter (unbound under '-'), MCP servers by repo.
groups: {
triByAgent: Object.fromEntries([...new Set(triTools.flatMap((x) => (x.agents.length ? x.agents.map((a) => a.letter) : ['-'])))].sort().map((l) => [l, triTools.filter((x) => (l === '-' ? x.agents.length === 0 : x.agents.some((a) => a.letter === l))).map((x) => x.id)])),
// '-' is always present, empty when nothing is unbound. It used to appear
// only while some command had no agent, so the day every command gained
// one the bucket vanished and the contract read undefined where it had
// asked for a list. "Nothing is unbound" is a fact worth stating, not an
// absence to infer.
triByAgent: Object.fromEntries([...new Set(['-', ...triTools.flatMap((x) => x.agents.map((a) => a.letter))])].sort().map((l) => [l, triTools.filter((x) => (l === '-' ? x.agents.length === 0 : x.agents.some((a) => a.letter === l))).map((x) => x.id)])),
mcpByRepo: Object.fromEntries(['gHashTag/t27', 'gHashTag/trinity'].map((r) => [r, mcpTools.filter((x) => x.repo === r).map((x) => x.id)])),
triByRepo: Object.fromEntries(TOOL_REPOS.map((r) => [r, triTools.filter((x) => x.repo === r).map((x) => x.id)])),
},
Expand Down
155 changes: 155 additions & 0 deletions apps/website/src/components/QueenLanes.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/* QueenLanes.css - LANES, the view that says how many bees can work at once and
refuses to let utilisation stand in for work. Same panel skin as QueenIntel:
colours come from the --hud-* variables Queen.css defines, with the live
palette as fallback, and the body is the only scroll owner. */

.queen27-lanes {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
min-height: 0;
height: 100%;
border: 1px solid var(--hud-line, rgba(0, 255, 136, 0.22));
background: var(--hud-panel, rgba(2, 8, 6, 0.86));
clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
}

.queen27-lanes-head {
padding: 12px 16px;
border-bottom: 1px solid var(--hud-line, rgba(0, 255, 136, 0.22));
}

.queen27-lanes-head h2 {
margin: 0;
font-size: 0.82rem;
letter-spacing: 0.18em;
color: var(--hud-accent, #00ff88);
}

.queen27-lanes-head p {
margin: 6px 0 0;
font-size: 0.78rem;
line-height: 1.5;
color: var(--hud-dim, rgba(214, 255, 235, 0.68));
}

.queen27-lanes-body {
min-height: 0;
overflow-y: auto;
padding: 14px 16px 20px;
display: grid;
gap: 12px;
align-content: start;
}

/* ---- the four figures ------------------------------------------------- */

.queen27-lanes-figures {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
gap: 10px;
}

.queen27-lanes-figure {
margin: 0;
padding: 10px 12px;
border: 1px solid var(--hud-line, rgba(0, 255, 136, 0.22));
background: rgba(0, 255, 136, 0.04);
display: grid;
gap: 2px;
}

.queen27-lanes-figure figcaption {
font-size: 0.64rem;
letter-spacing: 0.16em;
color: var(--hud-dim, rgba(214, 255, 235, 0.68));
}

.queen27-lanes-figure b {
font-size: 1.6rem;
font-weight: 600;
line-height: 1.1;
color: var(--hud-accent, #00ff88);
font-variant-numeric: tabular-nums;
}

.queen27-lanes-figure small {
font-size: 0.66rem;
color: var(--hud-dim, rgba(214, 255, 235, 0.68));
}

.queen27-lanes-figure-wide {
grid-column: span 2;
}

/* ---- cards ------------------------------------------------------------ */

.queen27-lanes-card {
padding: 12px 14px;
border: 1px solid var(--hud-line, rgba(0, 255, 136, 0.22));
background: rgba(2, 8, 6, 0.5);
}

.queen27-lanes-card h3 {
margin: 0 0 8px;
font-size: 0.72rem;
letter-spacing: 0.16em;
color: var(--hud-accent, #00ff88);
}

.queen27-lanes-card h4 {
margin: 12px 0 4px;
font-size: 0.68rem;
letter-spacing: 0.14em;
color: var(--hud-accent, #00ff88);
}

.queen27-lanes-card p {
margin: 0 0 6px;
font-size: 0.78rem;
line-height: 1.55;
color: var(--hud-text, rgba(233, 255, 244, 0.9));
}

/* The alarm skin is earned, not decorative: it appears only when the last
dispatch was refused in under a second, which is a spent quota. */
.queen27-lanes-card-alarm {
border-color: rgba(255, 77, 94, 0.55);
background: rgba(255, 77, 94, 0.07);
}

.queen27-lanes-alarm {
color: #ff4d5e;
font-weight: 600;
}

.queen27-lanes-warn {
color: #ffc24d;
}

.queen27-lanes-note,
.queen27-lanes-meta {
font-size: 0.72rem;
color: var(--hud-dim, rgba(214, 255, 235, 0.68));
}

.queen27-lanes-meta {
font-variant-numeric: tabular-nums;
}

.queen27-lanes-formula {
display: block;
margin: 6px 0;
padding: 8px 10px;
font-size: 0.72rem;
line-height: 1.5;
overflow-x: auto;
border: 1px dashed var(--hud-line, rgba(0, 255, 136, 0.22));
color: var(--hud-accent, #00ff88);
background: rgba(0, 0, 0, 0.35);
}

.queen27-lanes-error {
margin: 0;
font-size: 0.74rem;
color: #ff4d5e;
}
Loading
Loading