Skip to content
Open
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
88 changes: 64 additions & 24 deletions .agents/skills/bearings/assets/board-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,17 @@
.bb-decision__pad { padding: 18px 20px 16px; display: flex; flex-direction: column; gap: 12px; flex: 1; }
.bb-decision__top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.bb-decision__repo { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--text-faint); white-space: nowrap; }
.bb-decision__title { margin: 0; font-size: var(--fs-h4); font-weight: 800; color: var(--text-strong); line-height: 1.25; }
.bb-decision__detail { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.45; }
.bb-decision__title { margin: 0; font-size: var(--fs-h4); font-weight: 800; color: var(--text-strong); line-height: 1.25;
overflow-wrap: anywhere; }
.bb-decision__detail { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.45;
overflow-wrap: anywhere; }
/* about / decide / recommended - three scannable context rows */
.bb-ctx { display: flex; flex-direction: column; gap: 6px; }
.bb-ctx__row { display: grid; grid-template-columns: 78px minmax(0,1fr); gap: 8px; align-items: baseline; }
.bb-ctx__k { font-family: var(--font-mono); font-size: var(--fs-2xs); letter-spacing: 0.04em;
text-transform: uppercase; color: var(--text-faint); white-space: nowrap; }
.bb-ctx__v { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.4; min-width: 0; }
.bb-ctx__v { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.4; min-width: 0;
overflow-wrap: anywhere; }
.bb-decision__link { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ocean-600); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
.bb-decision__link:hover { text-decoration: underline; }
/* One rhythm owner: the answer form is a flex column with the same 12px gap as
Expand All @@ -213,8 +216,10 @@
.bb-opt:hover { border-color: var(--ink-300); }
.bb-opt input { accent-color: var(--rust-500); margin-top: 3px; flex: none; }
.bb-opt__body { min-width: 0; flex: 1 1 auto; }
.bb-opt__label { display: block; font-size: var(--fs-sm); font-weight: 700; color: var(--text-strong); line-height: 1.3; }
.bb-opt__hint { display: block; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.35; margin-top: 1px; }
.bb-opt__label { display: block; font-size: var(--fs-sm); font-weight: 700; color: var(--text-strong); line-height: 1.3;
overflow-wrap: anywhere; }
.bb-opt__hint { display: block; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.35; margin-top: 1px;
overflow-wrap: anywhere; }
.bb-opt__rec { flex: none; align-self: center; font-size: var(--fs-2xs); font-weight: 800; text-transform: uppercase;
letter-spacing: 0.07em; color: var(--navy-700); background: var(--gold-300);
border: 1px solid var(--gold-600); border-radius: var(--radius-xs); padding: 3px 7px 2px; }
Expand Down Expand Up @@ -273,7 +278,7 @@
.bb-foot { display: flex; justify-content: flex-end; border-top: 1px solid var(--border-default); padding-top: 14px; }

@media (max-width: 900px) {
.bb-cols { grid-template-columns: 1fr; }
.bb-cols { grid-template-columns: minmax(0, 1fr); }
}
</style>
</head>
Expand Down Expand Up @@ -434,11 +439,42 @@
if (text != null) n.textContent = text;
return n;
}
/* The styles above deliberately clamp, ellipsize, or hard-wrap captain-facing
text, so any renderer-produced text node CSS can visually cut also carries
its exact full text as a native title tooltip - the visible label stays as
rendered and the complete value stays reachable on hover. Build every such
node with titledEl when its tooltip is exactly its visible text, or with
titledValueEl when the visible label is a deliberate short form of a longer
value (the landed PR link shows "#<number>" and titles the full URL), and
keep plain el for text that is already fully shown; a node that already
exists in the static markup instead sets .title beside its textContent at
the one place that fills it.
The null guard matters because title reflects a DOMString: assigning a
missing value would surface the literal "null" as the tooltip.
tests/fm-bearings-board.test.sh renders a built board and asserts these
exact tooltip values. */
function titledEl(tag, cls, text) {
var n = el(tag, cls, text);
if (text != null) n.title = text;
return n;
}
function titledValueEl(tag, cls, text, fullText) {
var n = el(tag, cls, text);
if (fullText != null) n.title = fullText;
return n;
}
function badge(tone, text) { return el("span", "fm-badge fm-badge--" + tone, text); }
/* Fixed badge literals are short, nowrap, and always fully drawn, so they
stay tooltip-free; payload-derived badge text has no bounded length and
carries its exact full value like every other clampable node. */
function dynamicBadge(tone, text) { return titledEl("span", "fm-badge fm-badge--" + tone, text); }
function utf8ByteLength(text) { return new TextEncoder().encode(text).length; }
var CHECK_SVG = '<svg class="fm-ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>';

document.getElementById("bb-provenance").textContent = data.schema + " · " + data.generated;
var provenance = data.schema + " · " + data.generated;
var provenanceNode = document.getElementById("bb-provenance");
provenanceNode.textContent = provenance;
provenanceNode.title = provenance;

/* stat strip */
var callTotal = data.captains_call.length;
Expand All @@ -463,7 +499,7 @@
function ctxRow(k, v, rec) {
var row = el("div", "bb-ctx__row" + (rec ? " bb-ctx__row--rec" : ""));
row.appendChild(el("span", "bb-ctx__k", k));
row.appendChild(el("span", "bb-ctx__v", v));
row.appendChild(titledEl("span", "bb-ctx__v", v));
return row;
}

Expand All @@ -474,19 +510,19 @@
var top = el("div", "bb-decision__top");
if (item.type === "merge") {
top.appendChild(badge("online", "checks green"));
top.appendChild(badge(item.risk === "low" ? "neutral" : "warn", "risk " + item.risk));
top.appendChild(dynamicBadge(item.risk === "low" ? "neutral" : "warn", "risk " + item.risk));
} else {
top.appendChild(badge("solid", "decision"));
top.appendChild(el("span", "bb-decision__repo", item.repo));
top.appendChild(titledEl("span", "bb-decision__repo", item.repo));
}
pad.appendChild(top);

pad.appendChild(el("h3", "bb-decision__title", item.title));
pad.appendChild(titledEl("h3", "bb-decision__title", item.title));

if (item.type === "merge") {
if (item.detail) pad.appendChild(el("p", "bb-decision__detail", item.detail));
if (item.detail) pad.appendChild(titledEl("p", "bb-decision__detail", item.detail));
if (item.pr_url) {
var pr = el("a", "bb-decision__link", item.pr_url);
var pr = titledEl("a", "bb-decision__link", item.pr_url);
pr.href = item.pr_url; pr.target = "_blank"; pr.rel = "noopener";
pad.appendChild(pr);
}
Expand All @@ -507,8 +543,8 @@
input.type = "radio"; input.name = "answer"; input.value = o.value;
lab.appendChild(input);
var body = el("span", "bb-opt__body");
body.appendChild(el("span", "bb-opt__label", o.label));
if (o.hint) body.appendChild(el("span", "bb-opt__hint", o.hint));
body.appendChild(titledEl("span", "bb-opt__label", o.label));
if (o.hint) body.appendChild(titledEl("span", "bb-opt__hint", o.hint));
lab.appendChild(body);
if (item.recommend_value && o.value === item.recommend_value) {
lab.appendChild(el("span", "bb-opt__rec", "rec"));
Expand All @@ -521,6 +557,10 @@
var ff = document.createElement("input");
ff.type = "text"; ff.name = "note"; ff.className = "bb-freeform";
ff.placeholder = item.freeform_hint || "or answer in your own words…";
/* a single-line field hard-clips its placeholder at the field edge, and
freeform_hint is unbounded payload text, so the supplied hint stays
reachable in full; the short built-in fallback needs no tooltip */
if (item.freeform_hint) ff.title = item.freeform_hint;
form.appendChild(ff);
}

Expand Down Expand Up @@ -605,12 +645,12 @@
if (!data.underway.length) uw.appendChild(el("div", "bb-empty", "Nothing is underway."));
data.underway.forEach(function (t) {
var row = el("div", "bb-row");
row.appendChild(badge(t.state === "working" ? "online" : "info", t.state));
row.appendChild(dynamicBadge(t.state === "working" ? "online" : "info", t.state));
var main = el("div", "bb-row__main");
main.appendChild(el("div", "bb-row__title", t.doing));
main.appendChild(titledEl("div", "bb-row__title", t.doing));
/* captain-facing rows name the repo; the internal task id shows only when
no repo is known */
main.appendChild(el("div", "bb-row__sub", t.kind + " · " + (t.repo || t.id)));
main.appendChild(titledEl("div", "bb-row__sub", t.kind + " · " + (t.repo || t.id)));
row.appendChild(main);
uw.appendChild(row);
});
Expand All @@ -624,12 +664,12 @@
chk.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>';
row.appendChild(chk);
var main = el("div", "bb-row__main");
main.appendChild(el("div", "bb-row__title", t.what));
main.appendChild(el("div", "bb-row__sub", (t.repo || t.id) + " · " + t.owner));
main.appendChild(titledEl("div", "bb-row__title", t.what));
main.appendChild(titledEl("div", "bb-row__sub", (t.repo || t.id) + " · " + t.owner));
row.appendChild(main);
if (t.pr_url) {
var a = el("a", "bb-row__pr", "#" + t.pr_url.split("/").pop());
a.href = t.pr_url; a.title = t.pr_url; a.target = "_blank"; a.rel = "noopener";
var a = titledValueEl("a", "bb-row__pr", "#" + t.pr_url.split("/").pop(), t.pr_url);
a.href = t.pr_url; a.target = "_blank"; a.rel = "noopener";
row.appendChild(a);
}
ld.appendChild(row);
Expand Down Expand Up @@ -672,10 +712,10 @@
row.appendChild(el("span", "bb-pick-spacer"));
}
var main = el("div", "bb-row__main");
main.appendChild(el("div", "bb-row__title", t.title));
main.appendChild(titledEl("div", "bb-row__title", t.title));
/* second line keeps the title uncrowded in the half-width column */
var chSub = t.repo || t.id;
main.appendChild(el("div", "bb-row__sub", t.reason ? t.reason + " · " + chSub : chSub));
main.appendChild(titledEl("div", "bb-row__sub", t.reason ? t.reason + " · " + chSub : chSub));
row.appendChild(main);
if (t.reason) row.appendChild(badge("warn", "waiting"));
ch.appendChild(row);
Expand Down
Loading