<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="referrer" content="no-referrer">
<meta name="color-scheme" content="dark">
<title>rigswig</title>
<style nonce="__NONCE__">
@font-face { font-family: "Josefin Sans"; font-weight: 100 700; font-display: block; src: url(data:font/ttf;base64,__FONT_JOSEFIN__) format("truetype"); }
@font-face { font-family: "Pixelify Sans"; font-weight: 400 700; font-display: block; src: url(data:font/ttf;base64,__FONT_PIXELIFY__) format("truetype"); }
:root {
color-scheme: dark;
--bg: #0a0a0a; --box: #111111; --soft: #1b1b1b; --fg: #f2f2f2; --muted: #a8a8b0; --line: rgba(255, 255, 255, 0.15);
--green: #39ff00; --cyan: #22d3ee; --warn: #ffc14d;
--k-instruction: #22d3ee; --k-agent: #ff9f43; --k-skill: #39ff00; --k-command: #f472b6;
--k-mcp: #facc15; --k-hook: #b4b4bc; --k-permission: #a78bfa;
--a: #39ff00; --b: #22d3ee;
--pixel: "Pixelify Sans", ui-monospace, monospace;
--body: "Josefin Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--bg); }
body { margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.45 var(--body); }
.wrap { max-width: 1200px; margin: 0 auto; padding: 16px 16px 40px; }
a { color: var(--green); }
:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; border-radius: 4px; }
.approx { font-family: var(--body); font-weight: 400; margin-right: 0.04em; }
.hide-sm { display: none; }
.mono { font-family: var(--mono); font-size: 13px; }
.muted { color: var(--muted); }
.px { font-family: var(--pixel); text-transform: uppercase; letter-spacing: 0.08em; }
header.top { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 24px; padding-bottom: 14px; margin-bottom: 14px; border-bottom: 1px solid var(--line); }
.brand { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mark { font-family: var(--pixel); font-weight: 600; font-size: 34px; line-height: 1; letter-spacing: 0.02em; margin: 0; }
.mark span { color: var(--green); text-shadow: 0 0 6px rgba(57, 255, 0, 0.45); }
.by { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 44px; }
.by small { font-size: 13px; color: var(--muted); letter-spacing: 0.02em; }
.by a { display: inline-flex; align-items: center; min-height: 44px; border-radius: 6px; }
.by svg { width: 196px; height: auto; overflow: visible; display: block; }
.where { color: var(--muted); font-size: 15px; margin: 2px 0 0; }
.where b { color: var(--fg); font-weight: 600; }
.switch { margin-left: auto; display: flex; flex-direction: column; gap: 6px; align-items: flex-end; min-width: 0; max-width: 100%; }
.pick { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; max-width: 100%; }
.pick .slot { display: inline-flex; align-items: stretch; min-width: 0; max-width: 100%; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.tag { display: inline-flex; align-items: center; justify-content: center; min-width: 1.6em; padding: 0 6px; border-radius: 5px; font: 700 13px var(--body); color: #000; background: var(--muted); }
.tag.a { background: var(--a); } .tag.b { background: var(--b); }
.pick .slot .tag { border-radius: 0; padding: 0 10px; font-size: 14px; }
.pick .slot.a { border-color: var(--a); } .pick .slot.b { border-color: var(--b); }
.pick .slot.b.empty { border-color: var(--line); border-style: dashed; } .pick .slot.b.empty .tag { background: transparent; color: var(--muted); border-right: 1px dashed var(--line); }
.pick select { border: 0; border-radius: 0; min-width: 0; max-width: 260px; text-overflow: ellipsis; }
.pick .vs { color: var(--muted); font-size: 14px; }
.iconbtn { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 10px; border: 1px solid var(--line); color: var(--fg); text-decoration: none; font-size: 18px; }
.iconbtn:hover { border-color: var(--green); color: var(--green); }
.chip {
display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px; border-radius: 999px;
border: 1px solid var(--line); color: var(--fg); text-decoration: none; font: 15px var(--body); background: transparent;
}
.chip:hover { border-color: var(--green); }
.badge { font-size: 13px; color: var(--muted); }
.grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.box { position: relative; background: var(--box); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px 14px; min-width: 0; }
.box::before { content: ""; position: absolute; left: 12px; right: 12px; top: -1px; height: 2px; border-radius: 2px; background: var(--edge, var(--green)); }
.head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin: 0 0 10px; padding-bottom: 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.08); }
h2, .h2 { font-family: var(--pixel); font-weight: 500; font-size: 15px; text-transform: uppercase; letter-spacing: 0.1em; margin: 0; color: var(--edge-text, var(--green)); }
.head .aside { margin-left: auto; color: var(--muted); font-size: 14px; }
.hero { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px 24px; }
.big { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: 0; font-weight: 400; }
.big b { font-family: var(--pixel); font-weight: 600; font-size: 48px; line-height: 1; color: var(--green); text-shadow: 0 0 10px rgba(57, 255, 0, 0.35), 0 0 24px rgba(34, 211, 238, 0.18); }
.big span { font-size: 20px; }
.sub { color: var(--muted); margin: 6px 0 0; font-size: 15px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.sub strong { color: var(--fg); font-weight: 600; }
select {
font: 15px var(--body); color: var(--fg); background: var(--soft); border: 1px solid var(--line); border-radius: 8px;
min-height: 44px; padding: 0 10px; cursor: pointer;
}
.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; align-self: start; }
.stat { background: var(--box); padding: 8px 10px; min-width: 0; }
.stat b { display: block; font-family: var(--pixel); font-weight: 500; font-size: 20px; line-height: 1.15; overflow-wrap: anywhere; }
.stat > span { display: block; font-size: 13px; color: var(--muted); }
.stat.warn b { color: var(--warn); }
.bars { margin-top: 14px; }
.barrow { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px 12px; align-items: center; }
.barrow > b { font-size: 14px; font-weight: 600; overflow-wrap: anywhere; }
.bar { position: relative; display: flex; gap: 2px; height: 34px; border-radius: 6px; overflow: hidden; background: var(--soft); border: 1px solid var(--line); }
.barrow .bar { height: 26px; margin-bottom: 6px; }
.bar > i { display: block; height: 100%; min-width: 3px; flex: none; }
.bar > i.winend { position: absolute; top: 0; bottom: 0; width: 2px; min-width: 0; margin-left: -1px; background: var(--fg); opacity: 0.8; }
.modellines { display: grid; gap: 6px; margin-top: 12px; }
.modelline { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; font-size: 15px; }
.modelline .ml-model { min-width: 0; overflow-wrap: anywhere; }
.modelline .ml-model b { font-size: 14px; color: var(--fg); }
.modelline .ml-win { display: inline-flex; align-items: center; gap: 6px; }
.modelline .ml-hint { color: var(--warn); font-size: 14px; }
.bar > i.unmeasured {
min-width: 34px; flex: none; display: flex; align-items: center; justify-content: center; font: 600 14px var(--body); font-style: normal; color: var(--fg);
background: repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0 5px, rgba(255, 255, 255, 0.38) 5px 7px);
border-left: 1px dashed var(--fg);
}
.scale { position: relative; height: 16px; color: var(--muted); font-size: 12px; margin-top: 2px; }
.scale span { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.scale span:first-child { transform: none; }
.scale span:last-child { transform: translateX(-100%); }
.note { margin: 10px 0 0; padding: 8px 12px; border-radius: 8px; background: rgba(255, 193, 77, 0.1); border: 1px solid rgba(255, 193, 77, 0.35); color: var(--warn); font-size: 15px; }
.sw { width: 12px; height: 12px; border-radius: 3px; display: inline-block; flex: none; background: var(--kc, var(--muted)); }
.sw.hatch { background: repeating-linear-gradient(135deg, transparent 0 3px, var(--fg) 3px 4px); border: 1px solid var(--fg); }
.unm { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 8px; font-size: 14px; color: var(--muted); }
.unm span { display: inline-flex; align-items: center; gap: 6px; }
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 8px; margin-top: 14px; }
.tile {
position: relative; text-align: left; min-height: 44px; padding: 10px 10px 9px; border-radius: 10px; cursor: pointer; color: var(--fg);
background: var(--soft); border: 1px solid var(--line); font: 15px var(--body); display: flex; flex-direction: column; gap: 3px; min-width: 0;
}
.tile::before { content: ""; position: absolute; left: 8px; right: 8px; top: -1px; height: 2px; border-radius: 2px; background: var(--kc); }
.tile:hover { border-color: var(--kc); }
.tile[aria-expanded="true"] { border-color: var(--kc); background: #222; }
.tile .t { display: flex; align-items: center; gap: 6px; font-family: var(--pixel); font-size: 14px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--kc); }
.tile .t::after { content: "+"; margin-left: auto; color: var(--muted); font-family: var(--body); font-size: 18px; line-height: 1; }
.tile[aria-expanded="true"] .t::after { content: "\2212"; }
.tile .v { font-family: var(--pixel); font-weight: 500; font-size: 22px; line-height: 1.1; }
.tile .v small { font-family: var(--body); font-size: 14px; color: var(--muted); font-weight: 400; }
.tile .c { font-size: 13px; color: var(--muted); }
.tile .m { height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.1); overflow: hidden; margin-top: 3px; }
.tile .m i { display: block; height: 100%; background: var(--kc); min-width: 1px; }
.panel { grid-column: 1 / -1; background: #151515; border: 1px solid var(--kc); border-radius: 10px; padding: 10px 12px; min-width: 0; }
.panel .head { margin-bottom: 4px; }
.panel h3 { margin: 0; font-family: var(--pixel); font-weight: 500; font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--kc); }
ul.rows { list-style: none; margin: 0; padding: 0; }
ul.rows > li { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 12px; align-items: center; padding: 6px 8px; border-top: 1px solid rgba(255, 255, 255, 0.07); min-height: 40px; }
ul.rows > li:first-child { border-top: 0; }
ul.rows > li:has(> button.act) { grid-template-columns: minmax(0, 1fr) auto auto; }
ul.rows > li > button.act { margin-left: 0; }
ul.rows > li > .fill { position: absolute; left: 0; top: 3px; bottom: 3px; border-radius: 4px; background: var(--kc); opacity: 0.16; pointer-events: none; }
ul.rows > li > .fill::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; border-radius: 2px; background: var(--kc); opacity: 1; }
.rowname { position: relative; min-width: 0; overflow-wrap: anywhere; }
.rowname .meta { display: block; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.rownum { position: relative; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; font-size: 15px; }
.rownum small { display: block; font-size: 13px; color: var(--muted); }
.status { white-space: nowrap; font-size: 14px; }
.status.on { color: var(--green); }
.status.off { color: var(--muted); }
.k { display: inline-flex; align-items: center; gap: 5px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.chip { cursor: pointer; font-size: 14px; padding: 0 12px; }
.chip[aria-pressed="true"] { border-color: var(--green); color: var(--green); background: rgba(57, 255, 0, 0.08); }
.strip { display: flex; gap: 2px; height: 22px; border-radius: 5px; overflow: hidden; background: var(--soft); border: 1px solid var(--line); margin-bottom: 6px; }
.strip i { display: block; height: 100%; min-width: 2px; flex: none; background: var(--kc); }
.strip i.rest { background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.22) 0 2px, transparent 2px 4px); flex: 1 1 auto; }
.lead { margin: 0 0 8px; font-size: 15px; }
.lead b { font-family: var(--pixel); font-weight: 500; color: var(--green); }
.more { margin-top: 8px; }
button.link { font: 15px var(--body); color: var(--green); background: transparent; border: 1px solid var(--line); border-radius: 8px; min-height: 44px; padding: 0 14px; cursor: pointer; }
button.link:hover { border-color: var(--green); }
details.box > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px 12px; min-height: 44px; margin: -6px 0; }
details.box > summary::-webkit-details-marker { display: none; }
details.box > summary::after { content: "+"; margin-left: 8px; color: var(--muted); font-size: 20px; line-height: 1; }
details.box[open] > summary::after { content: "\2212"; }
details.box[open] > summary { margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.08); }
details.box > summary .aside { margin-left: auto; color: var(--muted); font-size: 14px; }
details.sub2 { border-top: 1px solid rgba(255, 255, 255, 0.07); }
details.sub2:first-of-type { border-top: 0; }
details.sub2 > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 2px; }
details.sub2 > summary::-webkit-details-marker { display: none; }
details.sub2 > summary::before { content: "\25B8"; color: var(--muted); width: 1em; }
details.sub2[open] > summary::before { content: "\25BE"; }
details.sub2 > summary .aside { margin-left: auto; color: var(--muted); font-size: 14px; font-variant-numeric: tabular-nums; }
.setting { padding: 8px 0; border-top: 1px solid rgba(255, 255, 255, 0.07); }
.setting:first-child { border-top: 0; padding-top: 0; }
.setting .n { font-family: var(--mono); font-size: 13px; color: var(--muted); }
.setting .val { overflow-wrap: anywhere; }
ol.trail { list-style: none; display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0 0; padding: 0; }
ol.trail li { font-size: 13px; padding: 3px 8px; border-radius: 6px; border: 1px solid var(--line); color: var(--muted); overflow-wrap: anywhere; max-width: 100%; }
ol.trail li:first-child { color: var(--fg); border-color: var(--green); }
ol.trail li + li::before { content: "beats "; }
ul.warn { list-style: none; margin: 0; padding: 0; }
ul.warn li { padding: 5px 0 5px 22px; position: relative; font-size: 15px; overflow-wrap: anywhere; }
ul.warn li::before { content: "\25B2"; position: absolute; left: 2px; top: 6px; color: var(--warn); font-size: 12px; }
ul.plain { margin: 0; padding-left: 18px; font-size: 15px; }
ul.plain li { margin: 3px 0; }
.diffrow { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px 12px; padding: 6px 0; border-top: 1px solid rgba(255, 255, 255, 0.07); align-items: center; }
.diffrow:first-of-type { border-top: 0; }
.dsplit { display: flex; gap: 2px; height: 10px; border-radius: 4px; overflow: hidden; background: var(--soft); }
.dsplit i { display: block; height: 100%; min-width: 3px; }
.d-a { background: var(--a); } .d-b { background: var(--b); }
.d-c { background: repeating-linear-gradient(135deg, var(--warn) 0 3px, transparent 3px 5px); border: 1px solid var(--warn); }
.d-s { background: #555; }
.dnums { display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.dnums b { color: var(--fg); font-weight: 600; }
.dkey { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.dkey span { display: inline-flex; align-items: center; gap: 5px; }
.dkey i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
footer { color: var(--muted); font-size: 14px; margin-top: 20px; }
@media (min-width: 560px) {
.barrow { grid-template-columns: minmax(96px, max-content) minmax(0, 1fr); }
.barrow .bar { margin: 3px 0; }
.hide-sm { display: block; }
.diffrow { grid-template-columns: 130px minmax(0, 1fr); }
.diffrow .dnums { grid-column: 2; }
}
@media (min-width: 760px) {
ul.rows.dense > li { min-height: 36px; padding-top: 4px; padding-bottom: 4px; }
ul.rows.dense .rowname .meta { display: inline; margin-left: 10px; }
ul.rows.dense .rownum small { display: inline-block; min-width: 4.2em; margin-left: 8px; }
.hero { grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); }
.stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1000px) {
.diffrow { grid-template-columns: 130px minmax(0, 1fr) auto; }
.diffrow .dnums { grid-column: 3; justify-content: flex-end; }
.grid.two { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); align-items: start; }
.col { display: grid; gap: 12px; min-width: 0; }
}
@media (max-width: 559px) {
.switch { margin-left: 0; align-items: flex-start; width: 100%; }
.switch { align-items: stretch; }
.pick { display: grid; grid-template-columns: minmax(0, 1fr) 44px; }
.pick .slot { max-width: none; } .pick select { flex: 1; max-width: none; }
.pick .vs { justify-self: center; }
.big b { font-size: 40px; }
.mark { font-size: 30px; }
}
@media (max-width: 399px) {
.tiles { grid-template-columns: minmax(0, 1fr); gap: 6px; }
.tile { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 8px; align-items: baseline; padding: 8px 10px; }
.tile .t { grid-column: 1; grid-row: 1; }
.tile .v { grid-column: 2; grid-row: 1 / span 2; font-size: 18px; text-align: right; align-self: center; }
.tile .c { grid-column: 1; grid-row: 2; }
.tile .m { grid-column: 1 / -1; grid-row: 3; }
}
@media (prefers-reduced-motion: no-preference) {
.tile, .chip, .iconbtn, button.link { transition: border-color 150ms ease, background-color 150ms ease; }
.panel { animation: open 160ms ease-out; }
@keyframes open { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
}
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }
}
.badge.writes { color: var(--warn); font-weight: 700; }
button.act { font: 600 14px/1 var(--body); color: var(--bg); background: var(--green); border: 0; border-radius: 8px; min-height: 44px; padding: 0 14px; cursor: pointer; margin-left: 10px; white-space: nowrap; }
button.act.off { background: transparent; color: var(--fg); box-shadow: inset 0 0 0 1px var(--line); }
.sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; max-height: 75vh; overflow: auto; background: var(--box); border-top: 2px solid var(--warn); box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.6); padding: 16px max(16px, calc((100vw - 1060px) / 2)); }
.sheet h2 { font: 700 16px/1.2 var(--pixel); color: var(--warn); text-transform: uppercase; letter-spacing: 0.06em; margin: 0 0 10px; }
.sheet fieldset { border: 0; padding: 0; margin: 0 0 10px; display: flex; flex-wrap: wrap; gap: 6px 14px; }
.sheet legend { color: var(--muted); font-size: 14px; margin-bottom: 4px; }
.sheet label { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; cursor: pointer; }
.sheet .row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.sheet .err { color: var(--warn); }
.sheet ul.notes { margin: 8px 0 0; padding-left: 18px; color: var(--muted); }
pre.diff { font: 13px/1.5 var(--mono); background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; overflow-x: auto; margin: 8px 0 0; max-height: 40vh; }
pre.diff span { display: block; white-space: pre; }
pre.diff .add { color: var(--green); }
pre.diff .del { color: #ff7a7a; }
.banner { position: sticky; top: 0; z-index: 15; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; background: #1d1a0d; border: 1px solid var(--warn); border-radius: 10px; padding: 8px 14px; margin-bottom: 14px; }
.banner[hidden] { display: none; }
.audit { --sev-high: #ff6b6b; --sev-medium: var(--warn); --sev-low: #9fb3c8; }
.audit .intro { margin: 0 0 10px; color: var(--muted); font-size: 15px; }
.audit .controls { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }
.audit .controls button.act { margin-left: 0; }
.audit .fleetform { display: flex; flex-wrap: wrap; gap: 8px; flex: 1 1 360px; min-width: 0; }
.audit input[type="text"], .audit input[type="search"] {
font: 15px var(--body); color: var(--fg); background: var(--soft); border: 1px solid var(--line); border-radius: 8px;
min-height: 44px; padding: 0 12px; min-width: 0; flex: 1 1 200px;
}
.audit input[type="text"] { font-family: var(--mono); font-size: 14px; }
.audit input::placeholder { color: #7d7d86; }
.audit button:disabled { opacity: 0.5; cursor: progress; }
.audit input:disabled, .audit button:disabled.act.off { opacity: 0.5; cursor: not-allowed; }
.audit .controls.gh { margin-top: 8px; }
.ghlabel { font: 500 13px var(--pixel); text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); min-width: 132px; }
.ghhint { margin: 6px 0 0; font-size: 14px; color: var(--muted); }
.ghhint code { font: 13px var(--mono); color: var(--fg); }
.prog { margin-top: 14px; }
.prog[hidden] { display: none; }
.prog .track { position: relative; height: 16px; border-radius: 8px; background: var(--soft); border: 1px solid var(--line); overflow: hidden; }
.prog .fillbar { height: 100%; width: 0; border-radius: 8px; background: linear-gradient(90deg, var(--green), var(--cyan)); box-shadow: 0 0 12px rgba(57, 255, 0, 0.45); }
.prog.running .fillbar { background-image: repeating-linear-gradient(120deg, rgba(0, 0, 0, 0.22) 0 8px, transparent 8px 16px), linear-gradient(90deg, var(--green), var(--cyan)); background-size: 32px 100%, 100% 100%; }
.prog.failed .fillbar { background: var(--sev-high); box-shadow: none; }
.prog .lbl { display: flex; justify-content: space-between; gap: 4px 12px; flex-wrap: wrap; font-size: 14px; color: var(--muted); margin-top: 6px; }
.prog .lbl b { color: var(--fg); font-weight: 600; overflow-wrap: anywhere; }
.prog .lbl span { font-variant-numeric: tabular-nums; }
.aresult { margin-top: 14px; }
.astats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; margin-bottom: 12px; }
.astats .stat b { font-size: 24px; }
.astats:focus, .aresult h3:focus { outline: none; }
.astats .stat.good b { color: var(--green); }
.afilters { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 10px; }
.afilters select { flex: 0 1 auto; max-width: 100%; }
.chip.sev::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--sc); }
.chip.sev[aria-pressed="true"] { border-color: var(--sc); color: var(--fg); background: rgba(255, 255, 255, 0.06); }
.chip.sev[aria-pressed="false"] { opacity: 0.55; }
.sev-high { --sc: var(--sev-high); }
.sev-medium { --sc: var(--sev-medium); }
.sev-low { --sc: var(--sev-low); }
.findings { display: grid; gap: 8px; }
details.finding { background: var(--soft); border: 1px solid var(--line); border-left: 3px solid var(--sc); border-radius: 10px; min-width: 0; }
details.finding[open] { background: #181818; }
details.finding > summary { list-style: none; cursor: pointer; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 4px 10px; align-items: center; padding: 10px 12px; min-height: 44px; }
details.finding > summary::-webkit-details-marker { display: none; }
details.finding > summary:hover .ftitle { color: #fff; }
.sevbadge { font: 500 12px var(--pixel); text-transform: uppercase; letter-spacing: 0.08em; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--sc); color: var(--sc); white-space: nowrap; }
.ftitle { overflow-wrap: anywhere; }
.fsave { font: 500 14px var(--pixel); color: var(--green); white-space: nowrap; }
.fbody { padding: 0 12px 12px 14px; border-top: 1px solid rgba(255, 255, 255, 0.07); }
.fbody .fcode { margin: 8px 0 6px; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.fbody ul.evid { margin: 6px 0; padding-left: 18px; font-size: 15px; }
.fbody ul.evid li { margin: 2px 0; overflow-wrap: anywhere; }
.fbody .fix { margin: 8px 0 0; padding: 8px 10px; border-radius: 8px; background: rgba(57, 255, 0, 0.06); border: 1px solid rgba(57, 255, 0, 0.25); }
.fbody .fix b { color: var(--green); font-weight: 600; }
.fbody .cmd { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; margin-top: 8px; font-size: 14px; color: var(--muted); }
.fbody .cmd code { font: 13px var(--mono); color: var(--fg); background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; overflow-wrap: anywhere; min-width: 0; }
.fbody .refs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.fbody .refs button.link { min-height: 36px; font-size: 14px; padding: 0 10px; max-width: 100%; overflow-wrap: anywhere; text-align: left; }
button.link.small { min-height: 36px; font-size: 14px; padding: 0 10px; }
.empty { color: var(--muted); padding: 10px 2px; margin: 0; }
.fleetrepos button.link { margin-left: 10px; }
ul.rows > li[hidden] { display: none; }
@media (min-width: 760px) { .astats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
ul.rows > li.drillrow { display: block; padding: 0; border-top: 0; min-height: 0; }
.fleetrepos li.current { background: rgba(57, 255, 0, 0.05); }
.fleetitems .rec { display: block; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.drill { margin: 6px 0 4px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: #141414; }
.drill h3 { margin: 0 0 8px; font-family: var(--pixel); font-weight: 500; font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--cyan); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
ul.rows > li.flash { outline: 2px solid var(--green); outline-offset: -2px; border-radius: 6px; }
@media (prefers-reduced-motion: no-preference) {
.prog .fillbar { transition: width 220ms ease; }
.prog.running .fillbar { animation: stripes 900ms linear infinite; }
@keyframes stripes { from { background-position: 0 0, 0 0; } to { background-position: 32px 0, 0 0; } }
details.finding[open] .fbody { animation: open 160ms ease-out; }
}
@media (max-width: 559px) {
details.finding > summary { grid-template-columns: auto minmax(0, 1fr); }
details.finding > summary .fsave { grid-column: 2; }
}
</style>
</head>
<body>
<main class="wrap" id="app"><p class="muted">Loading…</p></main>
<noscript><p>This page needs JavaScript to draw. The same data is in <code>rigswig status --json</code>.</p></noscript>
<script type="application/json" id="data" nonce="__NONCE__">__DATA__</script>
<script nonce="__NONCE__">
(function () {
"use strict";
var data = JSON.parse(document.getElementById("data").textContent);
var h = data.harness;
var KINDS = ["instruction", "agent", "skill", "command", "mcp", "hook", "permission"];
var TITLE = { instruction: "Instructions", agent: "Agents", skill: "Skills", command: "Commands", mcp: "MCP servers", hook: "Hooks", permission: "Permissions" };
var WINDOWS = [128000, 200000, 272000, 400000, 1000000];
var SVG = "http://www.w3.org/2000/svg";
function el(tag, attrs, kids) {
var n = document.createElement(tag);
if (attrs) for (var key in attrs) {
var v = attrs[key];
if (v == null) continue;
if (key === "text") n.textContent = v;
else if (key === "cls") n.className = v;
else if (key === "style") n.style.cssText = v;
else n.setAttribute(key, v);
}
(kids || []).forEach(function (c) { if (c != null) n.appendChild(typeof c === "string" ? document.createTextNode(c) : c); });
return n;
}
function svg(tag, attrs, kids) {
var n = document.createElementNS(SVG, tag);
for (var key in attrs) n.setAttribute(key, attrs[key]);
(kids || []).forEach(function (c) { n.appendChild(c); });
return n;
}
function fmt(n) { return Math.round(n).toLocaleString("en-US"); }
function k(n) { if (n >= 1000000) return (n / 1000000).toFixed(1).replace(/\.0$/, "") + "M"; return n >= 1000 ? (n / 1000).toFixed(n >= 100000 ? 0 : 1).replace(/\.0$/, "") + "k" : String(n); }
function tok(chars) { return Math.ceil(chars / 4); }
function ap(n) { return [el("span", { cls: "approx", text: "~" }), k(n)]; }
function pct(x) { return x <= 0 ? "0%" : x < 0.1 ? "<0.1%" : (x < 10 ? x.toFixed(1) : Math.round(x)) + "%"; }
function kc(kind) { return "--kc:var(--k-" + kind + ")"; }
function val(x) { return x === null || x === undefined ? "(not set)" : (typeof x === "string" ? x : JSON.stringify(x)); }
function store(key, v) { try { if (v === undefined) return localStorage.getItem(key); localStorage.setItem(key, v); } catch (e) { return null; } return null; }
var token = new URLSearchParams(location.search).get("t") || "";
function href(tool, vs) { return "?t=" + encodeURIComponent(token) + "&tool=" + encodeURIComponent(tool) + (vs ? "&vs=" + encodeURIComponent(vs) : ""); }
var items = h.items;
var byId = {};
items.forEach(function (i) { byId[i.id] = i; });
var startup = items.filter(function (i) { return i.effective && i.load.when === "startup"; });
var total = h.context.chars.value || 1;
function kindsOf(hh) {
var out = {};
hh.items.forEach(function (i) { if (i.effective && i.load.when === "startup") out[i.kind] = (out[i.kind] || 0) + i.load.chars.value; });
return out;
}
var byKind = kindsOf(h);
var other = data.other, cmp = data.comparison;
var ranked = startup.filter(function (i) { return i.load.chars.value > 0; }).sort(function (a, b) { return b.load.chars.value - a.load.chars.value || (a.id < b.id ? -1 : 1); });
var app = document.getElementById("app");
app.textContent = "";
function wordmark(text, uid, glow) {
var spacing = 25, pad = 1, w = Math.max(100, text.length * spacing + 2 * pad), hgt = 60;
var size = Math.min(40, 800 / text.length), cw = (w - 2 * pad) / text.length;
var fillId = "phosphor-" + uid, glowId = "glow-" + uid;
var defs = svg("defs", {}, [
svg("linearGradient", { id: fillId, gradientUnits: "userSpaceOnUse", x1: "0", y1: "0", x2: String(w), y2: "0" }, [
svg("stop", { offset: "0", "stop-color": "#39ff00" }),
svg("stop", { offset: "0.45", "stop-color": "#7dffb0" }),
svg("stop", { offset: "1", "stop-color": "#22d3ee" })
]),
svg("filter", { id: glowId, x: "-10%", y: "-60%", width: "120%", height: "220%", "color-interpolation-filters": "sRGB" }, [
svg("feDropShadow", { dx: "0", dy: "0", stdDeviation: String(0.35 * glow), "flood-color": "#39ff00", "flood-opacity": String(0.55 * glow), result: "tight" }),
svg("feDropShadow", { "in": "tight", dx: "0", dy: "0", stdDeviation: String(2.4 * glow), "flood-color": "#22d3ee", "flood-opacity": String(0.25 * glow) })
])
]);
var g = svg("g", { filter: "url(#" + glowId + ")" });
text.split("").forEach(function (ch, i) {
var t = svg("text", {
x: String(pad + cw * (i + 0.5)), y: String(hgt / 2), "font-family": "Pixelify Sans", "font-size": String(size), "font-weight": "600",
"text-anchor": "middle", "dominant-baseline": "middle", fill: "url(#" + fillId + ")"
});
t.textContent = ch;
g.appendChild(t);
});
return svg("svg", { viewBox: "0 0 " + w + " " + hgt, preserveAspectRatio: "xMidYMid meet", "aria-hidden": "true", focusable: "false" }, [defs, g]);
}
var hereScore = 0;
data.tools.forEach(function (t) { if (t.id === h.tool.id) hereScore = t.score; });
function pickSelect(id, label, current, exclude, blank) {
var s = el("select", { id: id, "aria-label": label });
if (blank) s.appendChild(el("option", { value: "", text: blank }));
[["Configured here", function (t) { return t.score > 0; }], ["Not configured here", function (t) { return !(t.score > 0); }]].forEach(function (g) {
var group = el("optgroup", { label: g[0] });
data.tools.forEach(function (t) {
if (!g[1](t) || t.id === exclude) return;
var o = el("option", { value: t.id, text: t.id, title: t.score > 0 ? "evidence: " + t.evidence.join(", ") : "what " + t.id + " would load here" });
if (t.id === current) o.selected = true;
group.appendChild(o);
});
if (group.childNodes.length) s.appendChild(group);
});
return s;
}
var bId = other ? other.tool.id : "";
var pickA = pickSelect("pick-a", "Harness A: the one to read", h.tool.id, null, null);
var pickB = pickSelect("pick-b", "Harness B: the one to compare with", bId, h.tool.id, other ? null : "compare with…");
pickA.addEventListener("change", function () { location.assign(href(pickA.value, pickA.value === bId ? h.tool.id : bId)); });
pickB.addEventListener("change", function () { location.assign(href(h.tool.id, pickB.value)); });
var picker = el("div", { cls: "pick", role: "group", "aria-label": "Harnesses" }, [
el("label", { cls: "slot a" }, [el("span", { cls: "tag a", text: "A" }), pickA]),
other ? el("a", { cls: "iconbtn", href: href(bId, h.tool.id), title: "Swap A and B", "aria-label": "Swap A and B", text: "⇄" }) : el("span", { cls: "vs", "aria-hidden": "true", text: "vs" }),
el("label", { cls: "slot b" + (other ? "" : " empty") }, [el("span", { cls: "tag" + (other ? " b" : ""), text: "B" }), pickB]),
other ? el("a", { cls: "iconbtn", href: href(h.tool.id), title: "Stop comparing", "aria-label": "Stop comparing", text: "✕" }) : null
]);
app.appendChild(el("header", { cls: "top" }, [
el("div", { cls: "brand" }, [
el("h1", { cls: "mark", "aria-label": "rigswig" }, ["rig", el("span", { text: "swig" })]),
el("div", { cls: "by" }, [
el("small", { text: "brought to you by" }),
el("a", { href: "https://kevinferron.com", rel: "noopener noreferrer", "aria-label": "kevinferron.com" }, [wordmark("kevinferron.com", "rw-kf", 0.5)])
]),
el("p", { cls: "where" }, ["What a ", el("b", { text: h.tool.id }), " session in ", el("b", { text: h.target.repo }), " loads", other ? ", next to " : null, other ? el("b", { text: other.tool.id }) : null, " ", hereScore === 0 ? el("span", { cls: "badge", text: "· not configured here " }) : null, data.writes ? el("span", { cls: "badge writes", text: "· write mode · local" }) : el("span", { cls: "badge", text: "· read-only · local" })])
]),
el("div", { cls: "switch" }, [picker])
]));
var WINDOW_SETTINGS = ["model_context_window", "contextLength"];
function windowForModel(model) {
var m = String(model).toLowerCase().trim();
if (/\[1m\]$/.test(m)) return 1000000;
if (/^(opus|sonnet|haiku|fable|opusplan|best)$/.test(m)) return 1000000;
if (/claude|opus|sonnet|haiku|fable|mythos/.test(m)) {
if (/fable|mythos|(opus|sonnet|haiku)-5|(opus|sonnet)-4-[6-9]/.test(m)) return 1000000;
return 200000;
}
if (/^(openai\/)?gpt-5/.test(m)) return 272000;
if (/gemini-(2\.5|3)/.test(m)) return 1000000;
return null;
}
function layerWhere(hh, id) {
var l = hh.layers.filter(function (x) { return x.id === id; })[0];
return l ? (l.path || l.label) : id;
}
function windowOf(hh) {
var d = hh.settings.model, model = d && typeof d.value === "string" && d.value ? d.value : null;
var r = { model: model, modelFrom: d && d.source ? layerWhere(hh, d.source) : null, auto: 200000, autoFrom: "unknown" };
for (var i = 0; i < WINDOW_SETTINGS.length; i++) {
var s = hh.settings[WINDOW_SETTINGS[i]], n = s ? Number(s.value) : NaN;
if (n > 0) { r.auto = n; r.autoFrom = "setting"; r.setting = WINDOW_SETTINGS[i]; r.settingFrom = s.source ? layerWhere(hh, s.source) : null; break; }
}
if (r.autoFrom === "unknown" && model && windowForModel(model)) { r.auto = windowForModel(model); r.autoFrom = "model"; }
var own = Number(store("rigswig.window." + hh.tool.id));
r.pick = own > 0 ? own : null;
r.value = r.pick || r.auto;
return r;
}
var winA = windowOf(h), winB = other ? windowOf(other) : null;
var budget = el("section", { cls: "box", "aria-labelledby": "budget-h" });
var openKind = null;
function modelLine(hh, w, tag) {
var autoText = w.autoFrom === "setting" ? k(w.auto) + " (" + w.setting + ")" : w.autoFrom === "model" ? k(w.auto) + " (from the model)" : "unknown";
var select = el("select", { "aria-label": "Context window for " + hh.tool.id });
select.appendChild(el("option", { value: "", text: "auto: " + autoText }));
var sizes = WINDOWS.slice();
if (w.pick && sizes.indexOf(w.pick) < 0) sizes.push(w.pick);
sizes.forEach(function (n) { var o = el("option", { value: String(n), text: k(n) }); if (n === w.pick) o.selected = true; select.appendChild(o); });
select.addEventListener("change", function () {
var id = select.id;
store("rigswig.window." + hh.tool.id, select.value);
w.pick = Number(select.value) || null;
w.value = w.pick || w.auto;
drawBudget();
var again = document.getElementById(id); if (again) again.focus();
});
select.id = "win-" + (tag || "a").toLowerCase();
var model = w.model
? [el("b", { cls: "mono", text: w.model }), w.modelFrom ? el("span", { cls: "muted", text: " set in " + w.modelFrom }) : null]
: [el("span", { cls: "muted", text: "no model set here (the tool's default)" })];
return el("div", { cls: "modelline" }, [
tag ? el("span", { cls: "tag " + tag.toLowerCase(), text: tag }) : null,
el("span", { cls: "ml-model" }, [el("span", { cls: "muted", text: "model " })].concat(model)),
el("label", { cls: "ml-win" }, [el("span", { cls: "muted", text: "window" }), select]),
!w.pick && w.autoFrom === "unknown" ? el("span", { cls: "ml-hint", text: w.model ? "▲ rigswig does not know this model's window: pick it" : "▲ pick the window your model has" }) : null
]);
}
function barFor(hh, label, w, axis) {
var kinds = kindsOf(hh);
var present = KINDS.filter(function (x) { return kinds[x]; });
var bar = el("div", { cls: "bar", role: "img", "aria-label": label + ": " + present.map(function (x) { return TITLE[x] + " about " + k(tok(kinds[x])) + " tokens"; }).join(", ") + (hh.context.notMeasured.length ? "; plus parts not measured" : "") + ", on a " + k(w) + " token window" });
present.forEach(function (x) {
var pc = Math.min(100, tok(kinds[x]) / axis * 100);
bar.appendChild(el("i", { style: "width:" + pc + "%;background:var(--k-" + x + ")", title: TITLE[x] + ": ~" + k(tok(kinds[x])) + " tokens" }));
});
if (hh.context.notMeasured.length) bar.appendChild(el("i", { cls: "unmeasured", text: "?", title: "Not measured: " + hh.context.notMeasured.map(function (n) { return n.what; }).join("; ") }));
if (w < axis) bar.appendChild(el("i", { cls: "winend", style: "left:" + (w / axis * 100) + "%", title: hh.tool.id + "'s window ends here (" + k(w) + ")" }));
return bar;
}
function scaleRow(axis) {
var scale = el("div", { cls: "scale", "aria-hidden": "true" });
[0, 0.25, 0.5, 0.75, 1].forEach(function (f) { scale.appendChild(el("span", { text: f === 0 ? "0" : k(axis * f), style: "left:" + f * 100 + "%" })); });
return scale;
}
function drawBudget() {
budget.textContent = "";
var t = h.context.tokens;
var win = winA.value;
var share = t.value / win * 100;
var biggest = ranked[0];
var top3 = ranked.slice(0, 3).reduce(function (s, i) { return s + i.load.chars.value; }, 0);
var effective = items.filter(function (i) { return i.effective; }).length;
var pkOn = h.packages.filter(function (p) { return p.enabled; }).length;
var stats = el("div", { cls: "stats", role: "list", "aria-label": "Summary" }, [
el("div", { cls: "stat", role: "listitem" }, [el("b", { text: String(startup.length) }), el("span", { text: "load at startup" })]),
el("div", { cls: "stat", role: "listitem" }, [el("b", { text: effective + "/" + items.length }), el("span", { text: "found are in effect" })]),
el("div", { cls: "stat", role: "listitem" }, [el("b", { text: pct(top3 / total * 100) }), el("span", { text: "of it is the 3 biggest pieces" })]),
el("div", { cls: "stat", role: "listitem" }, [el("b", null, biggest ? ap(tok(biggest.load.chars.value)) : ["–"]), el("span", { text: biggest ? "biggest: " + biggest.name : "nothing measured" })]),
el("div", { cls: "stat", role: "listitem" }, [el("b", { text: h.packages.length ? pkOn + "/" + h.packages.length : "0" }), el("span", { text: "plugins on" })]),
el("div", { cls: "stat" + (h.warnings.length ? " warn" : ""), role: "listitem" }, [el("b", { text: (h.warnings.length ? "▲ " : "") + h.warnings.length }), el("span", { text: h.warnings.length === 1 ? "warning" : "warnings" })])
]);
budget.appendChild(el("div", { cls: "hero" }, [
el("div", null, [
el("h2", { id: "budget-h", text: "File-provided context" }),
el("p", { cls: "big" }, [el("b", null, ap(t.value)), el("span", { text: "estimated tokens from startup files" })]),
el("p", { cls: "sub" }, [el("strong", { text: pct(share) }), " of a " + k(win) + " window" + (winA.pick || winA.autoFrom !== "unknown" ? "" : " (a stand-in: the model's window is unknown)")]),
el("p", { cls: "sub", text: "Between " + k(t.low) + " and " + k(t.high) + ", estimated from " + fmt(h.context.chars.value) + " characters (" + t.method + ")." }),
el("div", { cls: "modellines" }, [modelLine(h, winA, other ? "A" : null), other ? modelLine(other, winB, "B") : null])
]),
stats
]));
var bars = el("div", { cls: "bars" });
if (other) {
var axis = Math.max(winA.value, winB.value), tb = other.context.tokens.value;
bars.appendChild(el("div", { cls: "barrow" }, [
el("b", null, [el("span", { cls: "tag a", text: "A" }), " " + h.tool.id + " ~" + k(t.value) + " · " + pct(share)]), barFor(h, "A " + h.tool.id, win, axis),
el("b", null, [el("span", { cls: "tag b", text: "B" }), " " + other.tool.id + " ~" + k(tb) + " · " + pct(tb / winB.value * 100)]), barFor(other, "B " + other.tool.id, winB.value, axis),
el("span", { cls: "hide-sm", "aria-hidden": "true" }), scaleRow(axis)
]));
} else { bars.appendChild(barFor(h, h.tool.id, win, win)); bars.appendChild(scaleRow(win)); }
budget.appendChild(bars);
if (h.context.notMeasured.length) {
budget.appendChild(el("div", { cls: "unm" }, h.context.notMeasured.map(function (n) {
return el("span", { title: n.why }, [el("i", { cls: "sw hatch", "aria-hidden": "true" }), "? not measured: " + n.what]);
})));
}
if (t.value > win) budget.appendChild(el("p", { cls: "note", text: "▲ " + (other ? "A's" : "The") + " measured part alone is larger than its window." }));
if (other && other.context.tokens.value > winB.value) budget.appendChild(el("p", { cls: "note", text: "▲ B's measured part alone is larger than its window." }));
budget.appendChild(tiles);
placePanel();
}
function status(i) {
if (i.effective) return el("span", { cls: "status on", text: "● in effect" + (i.kind === "mcp" && i.attrs.state && i.attrs.state !== "active" ? " · " + i.attrs.state : "") });
if (i.shadowedBy) {
var w = byId[i.shadowedBy];
return el("span", { cls: "status off", text: "◇ overridden by " + (w ? w.origin.layer : "another") });
}
if (i.kind === "mcp" && i.attrs.state) return el("span", { cls: "status off", text: "○ " + i.attrs.state });
return el("span", { cls: "status off", text: "○ off" });
}
function extraOf(i) {
var x = i.kind, a = i.attrs || {};
if (x === "agent") return a.tools === "all" ? "every tool" : "tools: " + ((a.tools && a.tools.only) || []).join(", ");
if (x === "hook") return a.event + (a.matcher ? " · " + a.matcher : "") + (a.script ? " · " + a.script : "");
if (x === "mcp") return a.transport + (a.target ? " · " + a.target : "");
if (x === "instruction" && a.appliesTo && a.appliesTo.length) return "when touching " + a.appliesTo.join(", ");
if (x === "permission") return a.effect;
return "";
}
var tiles = el("div", { cls: "tiles", role: "group", "aria-label": "Kinds: open one to see everything found" });
var tileBtns = {};
var panel = el("div", { cls: "panel", id: "kind-panel", role: "region" });
var panelShowAll = false;
KINDS.forEach(function (x) {
var all = items.filter(function (i) { return i.kind === x; });
if (!all.length) return;
var on = all.filter(function (i) { return i.effective; }).length;
var chars = byKind[x] || 0;
var runtime = !chars && all.every(function (i) { return i.load.when !== "startup"; });
var b = el("button", { type: "button", cls: "tile", style: kc(x), "aria-expanded": "false", "aria-controls": "kind-panel", id: "tile-" + x }, [
el("span", { cls: "t" }, [x === "mcp" ? "MCP" : TITLE[x]]),
el("span", { cls: "v" }, chars ? ap(tok(chars)).concat([el("small", { text: " " + pct(chars / total * 100) })]) : [el("small", { text: runtime ? "not in context" : "? not measured" })]),
el("span", { cls: "c", text: on + "/" + all.length + " in effect" }),
el("span", { cls: "m", "aria-hidden": "true" }, [el("i", { style: "width:" + (chars / total * 100) + "%" })])
]);
b.addEventListener("click", function () { openKind = openKind === x ? null : x; panelShowAll = false; drawPanel(); });
tileBtns[x] = b;
tiles.appendChild(b);
});
if (h.packages.length) {
var pkOn = h.packages.filter(function (p) { return p.enabled; }).length;
var pkChars = 0;
h.packages.forEach(function (p) { p.contributes.forEach(function (id) { var i = byId[id]; if (i && i.effective && i.load.when === "startup") pkChars += i.load.chars.value; }); });
var pb = el("button", { type: "button", cls: "tile", style: "--kc:#e8e8e8", "aria-expanded": "false", "aria-controls": "kind-panel", id: "tile-plugins" }, [
el("span", { cls: "t" }, ["Plugins"]),
el("span", { cls: "v" }, ap(tok(pkChars)).concat([el("small", { text: " " + pct(pkChars / total * 100) })])),
el("span", { cls: "c", text: pkOn + "/" + h.packages.length + " on" }),
el("span", { cls: "m", "aria-hidden": "true" }, [el("i", { style: "width:" + (pkChars / total * 100) + "%" })])
]);
pb.addEventListener("click", function () { openKind = openKind === "plugins" ? null : "plugins"; panelShowAll = false; drawPanel(); });
tileBtns.plugins = pb;
tiles.appendChild(pb);
}
function placePanel() {
if (!openKind || !tileBtns[openKind]) { if (panel.parentNode) panel.parentNode.removeChild(panel); return; }
var hadFocus = panel.contains(document.activeElement) ? document.activeElement : null;
if (panel.parentNode) panel.parentNode.removeChild(panel);
var me = tileBtns[openKind], row = me.offsetTop, after = me;
Object.keys(tileBtns).forEach(function (x) { var b = tileBtns[x]; if (b.offsetTop === row && b.compareDocumentPosition(after) & Node.DOCUMENT_POSITION_PRECEDING) after = b; });
tiles.insertBefore(panel, after.nextSibling);
if (hadFocus) hadFocus.focus();
}
function drawPanel() {
Object.keys(tileBtns).forEach(function (x) { tileBtns[x].setAttribute("aria-expanded", String(openKind === x)); });
panel.textContent = "";
if (!openKind) { placePanel(); return; }
var LIMIT = 25, rows = el("ul", { cls: "rows dense" }), list, count;
if (openKind === "plugins") {
panel.style.cssText = "--kc:#e8e8e8";
list = h.packages.map(function (p) {
var c = 0;
p.contributes.forEach(function (id) { var i = byId[id]; if (i && i.effective && i.load.when === "startup") c += i.load.chars.value; });
return { p: p, chars: c };
}).sort(function (a, b) { return b.chars - a.chars; });
var pmax = list.length ? Math.max(1, list[0].chars) : 1;
count = list.length;
(panelShowAll ? list : list.slice(0, LIMIT)).forEach(function (r) {
var p = r.p;
rows.appendChild(el("li", { "data-id": p.id }, [
el("i", { cls: "fill", style: "width:" + Math.max(0.5, r.chars / pmax * 100) + "%", "aria-hidden": "true" }),
el("span", { cls: "rowname" }, [el("span", { cls: "mono", text: p.id }), el("span", { cls: "meta" }, [el("span", { cls: "status " + (p.enabled ? "on" : "off"), text: p.enabled ? "● on" : "○ off" }), p.decidedBy ? " · decided by " + p.decidedBy : "", " · " + p.contributes.length + " items"])]),
el("span", { cls: "rownum" }, [r.chars ? "~" + k(tok(r.chars)) : "–", el("small", { text: r.chars ? pct(r.chars / total * 100) : "at startup" })]),
data.writes ? actButton(p.enabled ? "Turn off" : "Turn on", p.enabled, function () { openChange({ kind: "plugin", id: p.id, on: !p.enabled }, (p.enabled ? "Turn off " : "Turn on ") + p.id); }) : null
]));
});
panel.appendChild(el("div", { cls: "head" }, [el("h3", { id: "panel-h", text: "Plugins" }), el("span", { cls: "aside", text: "what each adds at startup" })]));
} else {
var x = openKind;
panel.style.cssText = kc(x);
list = items.filter(function (i) { return i.kind === x; });
count = list.length;
var kmax = Math.max.apply(null, list.map(function (i) { return i.load.chars.value; }).concat([1]));
(panelShowAll ? list : list.slice(0, LIMIT)).forEach(function (i) {
var extra = extraOf(i);
var c = i.load.chars;
var live = i.effective && i.load.when === "startup";
rows.appendChild(el("li", { "data-id": i.id }, [
live && c.value ? el("i", { cls: "fill", style: "width:" + Math.max(0.5, c.value / kmax * 100) + "%", "aria-hidden": "true" }) : null,
el("span", { cls: "rowname" }, [
i.name,
el("span", { cls: "meta" }, [status(i), " · " + i.origin.layer + (i.load.when !== "startup" ? " · loads " + i.load.when : "")]),
extra ? el("span", { cls: "meta", text: extra }) : null,
i.origin.file ? el("span", { cls: "meta mono", text: i.origin.file }) : null
]),
el("span", { cls: "rownum", text: c.confidence === "unknown" ? "?" : (c.value ? "~" + k(tok(c.value)) : "–") }),
data.writes && h.tool.id === "claude-code" && i.kind === "mcp" && i.origin.layer === "project" && !i.shadowedBy
? (function (active) {
return actButton(active ? "Disable" : "Approve", active, function () { openChange({ kind: "mcpJson", name: i.name, on: !active }, (active ? "Disable " : "Approve ") + i.name); });
})(i.attrs.state === "active")
: null
]));
});
var on = list.filter(function (i) { return i.effective; }).length;
panel.appendChild(el("div", { cls: "head" }, [el("h3", { id: "panel-h", text: TITLE[x] }), el("span", { cls: "aside", text: on + " in effect / " + list.length + " found · tokens" })]));
}
panel.setAttribute("aria-labelledby", "panel-h");
panel.appendChild(rows);
if (count > LIMIT && !panelShowAll) {
var more = el("button", { type: "button", cls: "link", text: "Show all " + count });
more.addEventListener("click", function () { panelShowAll = true; drawPanel(); var r = panel.querySelectorAll("ul.rows > li")[LIMIT]; if (r) { r.setAttribute("tabindex", "-1"); r.focus(); } });
panel.appendChild(el("div", { cls: "more" }, [more]));
}
placePanel();
}
var resizeQueued = false;
window.addEventListener("resize", function () { if (resizeQueued) return; resizeQueued = true; requestAnimationFrame(function () { resizeQueued = false; placePanel(); }); });
app.appendChild(el("div", { cls: "grid" }, [budget]));
drawBudget();
var SEV = { high: "High", medium: "Medium", low: "Low" };
var CODE = {
"heavy-user-scope": "User scope nothing here references",
"plugin-fit": "Plugin this repo doesn't call for",
"instruction-budget": "Instruction file over budget",
"repeated-text": "Repeated text",
"dead-reference": "Dead reference",
"permission-broad": "Risky permission",
"permission-one-off": "One-off permission",
"permission-covered": "Covered permission",
"agents-md-not-imported": "AGENTS.md never loaded"
};
function codeLabel(c) { return CODE[c] || (c.indexOf("warning:") === 0 ? "Warning: " + c.slice(8) : c); }
var REC = { archive: "Archive", "move-to-project": "Move to project scope", unknown: "No signal", keep: "Keep at user scope" };
var auditBox = el("section", { cls: "box audit", style: "--edge:linear-gradient(90deg,var(--green),var(--cyan));--edge-text:var(--green)", "aria-labelledby": "audit-h" });
auditBox.appendChild(el("div", { cls: "head" }, [el("h2", { id: "audit-h", text: "Audit" }), el("span", { cls: "aside", text: "from files only · usage is never read" })]));
auditBox.appendChild(el("p", { cls: "intro", text: "Finds what costs context and nothing here references, plugins this repo doesn't need, instruction files over budget, repeated text, dead references and risky permission rules, each with a saving and a fix." }));
var runBtn = el("button", { type: "button", cls: "act", text: "Audit this repo" });
var fleetIn = el("input", { type: "text", id: "fleet-in", placeholder: "~/code/* ~/work/app", "aria-label": "Folders to audit together, separated by spaces; * matches any folder name", autocomplete: "off", spellcheck: "false" });
fleetIn.value = store("rigswig.fleet") || "";
var fleetBtn = el("button", { type: "button", cls: "act off", text: "Audit many repos" });
auditBox.appendChild(el("div", { cls: "controls" }, [runBtn, el("div", { cls: "fleetform" }, [fleetIn, fleetBtn])]));
var ghIn = el("input", { type: "text", id: "gh-in", placeholder: "owner/repo or a github.com link", "aria-label": "A public GitHub repo to audit: owner/repo, owner/repo@branch, or its github.com address", "aria-describedby": "gh-hint", autocomplete: "off", spellcheck: "false" });
ghIn.value = store("rigswig.github") || "";
var ghBtn = el("button", { type: "button", cls: "act off", text: "Audit on GitHub" });
var ghHint = el("p", { cls: "ghhint", id: "gh-hint" }, data.github
? ["Downloads the repo's archive from codeload.github.com into memory: nothing is written, nothing from it runs, and your own setup is not part of the result."]
: ["GitHub audits are off. Start the page with ", el("code", { text: "rigswig ui --allow-github" }), " to audit public repos; each audit downloads one archive from codeload.github.com."]);
if (!data.github) { ghIn.disabled = true; ghBtn.disabled = true; }
auditBox.appendChild(el("div", { cls: "controls gh" }, [el("span", { cls: "ghlabel", text: "GitHub" }), el("div", { cls: "fleetform" }, [ghIn, ghBtn])]));
auditBox.appendChild(ghHint);
var fill = el("div", { cls: "fillbar" });
var track = el("div", { cls: "track", role: "progressbar", "aria-labelledby": "audit-h", "aria-valuemin": "0", "aria-valuemax": "100", "aria-valuenow": "0" }, [fill]);
var stageEl = el("b", { text: "" }), pctEl = el("span", { text: "" });
var prog = el("div", { cls: "prog", hidden: "" }, [track, el("div", { cls: "lbl" }, [stageEl, pctEl])]);
var said = el("p", { cls: "sr", role: "status", "aria-live": "polite" });
var results = el("div", { cls: "aresult" });
auditBox.appendChild(prog);
auditBox.appendChild(said);
auditBox.appendChild(results);
app.appendChild(el("div", { style: "height:12px" }));
app.appendChild(auditBox);
var auditing = false;
function busy(on) { auditing = on; runBtn.disabled = on; fleetBtn.disabled = on; ghBtn.disabled = on || !data.github; }
function showProg(fraction, stage, ms, state) {
prog.removeAttribute("hidden");
prog.className = "prog " + (state || "running");
var p = Math.round(Math.max(0, Math.min(1, fraction)) * 100);
fill.style.width = Math.max(p, 2) + "%";
track.setAttribute("aria-valuenow", String(p));
track.setAttribute("aria-valuetext", p + "%: " + stage);
stageEl.textContent = stage;
pctEl.textContent = p + "%" + (ms ? " · " + (ms / 1000).toFixed(1) + " s" : "");
}
function startAudit(body, label) {
if (auditing) return;
busy(true);
results.textContent = "";
showProg(0, "Starting " + label, 0);
said.textContent = "Audit started: " + label + ".";
call("/api/audit/start", body).then(function (job) { poll(job.id); }).catch(failed);
}
function poll(id) {
call("/api/audit/poll", { id: id }).then(function (j) {
if (j.state === "running") {
showProg(j.fraction, j.stage, j.elapsedMs);
setTimeout(function () { poll(id); }, 150);
return;
}
if (j.state === "failed") return failed(new Error(j.error || "the audit failed"));
showProg(1, "Done", j.elapsedMs, "done");
busy(false);
if (j.mode === "fleet") drawFleet(j.result, results);
else if (j.mode === "github") drawAudit(j.result, results, false, " --github " + j.result.repo);
else drawAudit(j.result, results, true);
var n = j.mode === "fleet" ? j.result.fleet.items.length + " user-scope items across " + j.result.fleet.repos.length + " repos" : j.result.findings.length + " findings";
said.textContent = "Audit done: " + n + ".";
var first = results.querySelector("h3, .astats");
if (first) { first.setAttribute("tabindex", "-1"); first.focus({ preventScroll: true }); }
}).catch(failed);
}
function failed(e) {
busy(false);
showProg(1, "Failed: " + e.message, 0, "failed");
said.textContent = "Audit failed: " + e.message;
}
runBtn.addEventListener("click", function () { startAudit({ mode: "repo" }, h.target.repo); });
function runFleet() {
var repos = fleetIn.value.trim().split(/\s+/).filter(Boolean);
if (!repos.length) { fleetIn.focus(); said.textContent = "Type the folders to audit first, like ~/code/*"; return; }
store("rigswig.fleet", fleetIn.value.trim());
startAudit({ mode: "fleet", repos: repos }, repos.join(" "));
}
fleetBtn.addEventListener("click", runFleet);
fleetIn.addEventListener("keydown", function (e) { if (e.key === "Enter") runFleet(); });
function runGithub() {
var v = ghIn.value.trim();
if (!v) { ghIn.focus(); said.textContent = "Type a GitHub repo first, like owner/repo"; return; }
store("rigswig.github", v);
startAudit({ mode: "github", repo: v }, v + " from GitHub");
}
ghBtn.addEventListener("click", runGithub);
ghIn.addEventListener("keydown", function (e) { if (e.key === "Enter" && data.github) runGithub(); });
function reveal(id) {
var i = byId[id];
var kind = i ? i.kind : (h.packages.some(function (p) { return p.id === id; }) ? "plugins" : null);
if (!kind || !tileBtns[kind]) return;
openKind = kind; panelShowAll = true; drawPanel();
var rows = panel.querySelectorAll("ul.rows > li");
for (var n = 0; n < rows.length; n++) {
if (rows[n].getAttribute("data-id") === id) {
var r = rows[n];
r.classList.add("flash");
r.setAttribute("tabindex", "-1");
r.scrollIntoView({ block: "center", behavior: "instant" });
r.focus({ preventScroll: true });
setTimeout(function () { r.classList.remove("flash"); }, 2400);
return;
}
}
}
function copyButton(text) {
var b = el("button", { type: "button", cls: "link small", text: "Copy" });
b.addEventListener("click", function () {
var done = function () { b.textContent = "Copied"; setTimeout(function () { b.textContent = "Copy"; }, 1500); };
if (navigator.clipboard) navigator.clipboard.writeText(text).then(done, function () { b.textContent = "Select and copy"; });
});
return b;
}
function card(f, here, repoArg) {
var d = el("details", { cls: "finding sev-" + f.severity });
d.appendChild(el("summary", null, [
el("span", { cls: "sevbadge", text: SEV[f.severity] || f.severity }),
el("span", { cls: "ftitle", text: f.title }),
f.saving ? el("span", { cls: "fsave", text: "saves ~" + k(f.saving.tokens) }) : null
]));
var body = el("div", { cls: "fbody" });
body.appendChild(el("p", { cls: "fcode", text: codeLabel(f.code) + " · " + f.code + (f.file ? " · " + f.file : "") }));
if (f.evidence.length) body.appendChild(el("ul", { cls: "evid" }, f.evidence.map(function (e) { return el("li", { text: e }); })));
if (f.saving) {
var est = "Saves ~" + fmt(f.saving.tokens) + " tokens a session (an estimate).";
if (f.saving.without.length <= 3) {
var cmd = "rigswig status" + repoArg + " --without " + f.saving.without.map(function (w) { return /[\s'"]/.test(w) ? "'" + w.replace(/'/g, "'\\''") + "'" : w; }).join(",");
body.appendChild(el("div", { cls: "cmd" }, [est + " Check it:", el("code", { text: cmd }), copyButton(cmd)]));
} else {
body.appendChild(el("div", { cls: "cmd", text: est + " rigswig audit --json lists the " + f.saving.without.length + " items behind it, to check with rigswig status --without." }));
}
}
body.appendChild(el("p", { cls: "fix" }, [el("b", { text: "Fix: " }), f.proposal]));
if (here && f.items && f.items.length) {
var shown = f.items.filter(function (id) { return byId[id] || h.packages.some(function (p) { return p.id === id; }); });
if (shown.length) {
var refs = el("div", { cls: "refs", "aria-label": "Show in the inventory" });
shown.slice(0, 30).forEach(function (id) {
var b = el("button", { type: "button", cls: "link", text: "Show " + (byId[id] ? byId[id].name : id) });
b.addEventListener("click", function () { reveal(id); });
refs.appendChild(b);
});
if (shown.length > 30) refs.appendChild(el("span", { cls: "muted", text: "and " + (shown.length - 30) + " more" }));
body.appendChild(refs);
}
}
d.appendChild(body);
return d;
}
function drawAudit(a, into, here, repoArgGiven) {
into.textContent = "";
var bySev = { high: 0, medium: 0, low: 0 };
a.findings.forEach(function (f) { bySev[f.severity] = (bySev[f.severity] || 0) + 1; });
var saving = a.findings.reduce(function (s, f) { return s + (f.saving ? f.saving.tokens : 0); }, 0);
into.appendChild(el("div", { cls: "astats" }, [
el("div", { cls: "stat" }, [el("b", { text: String(a.findings.length) }), el("span", { text: "findings in " + a.repo })]),
el("div", { cls: "stat" + (bySev.high ? " warn" : "") }, [el("b", { text: String(bySev.high) }), el("span", { text: "high severity" })]),
el("div", { cls: "stat good" }, [el("b", null, ap(Math.max(0, saving))), el("span", { text: "tokens a session they could save" })]),
el("div", { cls: "stat" }, [el("b", null, ap(a.tokens)), el("span", { text: "estimated tokens from startup files now" })])
]));
if (!a.findings.length) {
into.appendChild(el("p", { cls: "empty", text: "No findings: nothing here to fix." }));
} else {
var state = { sev: { high: true, medium: true, low: true }, code: "", q: "" };
var filters = el("div", { cls: "afilters", role: "group", "aria-label": "Filter findings" });
["high", "medium", "low"].forEach(function (s) {
if (!bySev[s]) return;
var b = el("button", { type: "button", cls: "chip sev sev-" + s, "aria-pressed": "true", text: SEV[s] + " " + bySev[s] });
b.addEventListener("click", function () { state.sev[s] = !state.sev[s]; b.setAttribute("aria-pressed", String(state.sev[s])); list(); });
filters.appendChild(b);
});
var codes = [];
a.findings.forEach(function (f) { if (codes.indexOf(f.code) < 0) codes.push(f.code); });
if (codes.length > 1) {
var sel = el("select", { "aria-label": "Kind of finding" }, [el("option", { value: "", text: "Every kind (" + a.findings.length + ")" })].concat(codes.map(function (c) {
var n = a.findings.filter(function (f) { return f.code === c; }).length;
return el("option", { value: c, text: codeLabel(c) + " (" + n + ")" });
})));
sel.addEventListener("change", function () { state.code = sel.value; list(); });
filters.appendChild(sel);
}
var q = el("input", { type: "search", placeholder: "Search findings", "aria-label": "Search findings" });
q.addEventListener("input", function () { state.q = q.value.trim().toLowerCase(); list(); });
filters.appendChild(q);
var expand = el("button", { type: "button", cls: "link small", text: "Open all" });
filters.appendChild(expand);
into.appendChild(filters);
var box = el("div", { cls: "findings" });
var count = el("p", { cls: "muted sr", role: "status", "aria-live": "polite" });
into.appendChild(count);
into.appendChild(box);
var repoArg = repoArgGiven !== undefined ? repoArgGiven : here ? "" : " --repo " + a.repo;
var list = function () {
box.textContent = "";
var shown = a.findings.filter(function (f) {
if (!state.sev[f.severity]) return false;
if (state.code && f.code !== state.code) return false;
if (state.q) {
var hay = (f.title + " " + f.evidence.join(" ") + " " + f.proposal + " " + f.code + " " + (f.file || "")).toLowerCase();
if (hay.indexOf(state.q) < 0) return false;
}
return true;
});
shown.forEach(function (f) { box.appendChild(card(f, here, repoArg)); });
if (!shown.length) box.appendChild(el("p", { cls: "empty", text: "No findings match these filters." }));
count.textContent = shown.length + " of " + a.findings.length + " findings shown";
expand.textContent = "Open all";
};
expand.addEventListener("click", function () {
var ds = box.querySelectorAll("details.finding");
var open = expand.textContent === "Open all";
for (var n = 0; n < ds.length; n++) ds[n].open = open;
expand.textContent = open ? "Close all" : "Open all";
});
list();
var firstHigh = box.querySelector("details.finding.sev-high");
if (firstHigh) firstHigh.open = true;
}
if (a.notes.length) into.appendChild(el("ul", { cls: "plain muted", style: "margin-top:10px" }, a.notes.map(function (n) { return el("li", { text: n }); })));
}
function drawFleet(run, into) {
into.textContent = "";
var f = run.fleet;
var movable = f.items.filter(function (i) { return i.recommendation === "archive" || i.recommendation === "move-to-project"; });
var save = movable.reduce(function (s, i) { return s + i.tokens; }, 0);
into.appendChild(el("div", { cls: "astats" }, [
el("div", { cls: "stat" }, [el("b", { text: String(f.repos.length) }), el("span", { text: "repos audited" })]),
el("div", { cls: "stat" }, [el("b", { text: String(f.items.length) }), el("span", { text: "user-scope items" })]),
el("div", { cls: "stat" + (movable.length ? " warn" : "") }, [el("b", { text: String(movable.length) }), el("span", { text: "to archive or move" })]),
el("div", { cls: "stat good" }, [el("b", null, ap(save)), el("span", { text: "tokens a session, where none is needed" })])
]));
var extra = [];
if (run.skipped.length) extra.push("Skipped, no harness found: " + run.skipped.join(", "));
if (run.privateSkipped) extra.push("Skipped " + run.privateSkipped + " private folder(s) (~/.rigswig/private.json)");
run.errors.forEach(function (e) { extra.push("Could not read " + e); });
into.appendChild(el("h3", { cls: "h2", style: "margin:4px 0 8px", text: "Repos" }));
var reposUl = el("ul", { cls: "rows fleetrepos" });
var tmax = Math.max.apply(null, f.repos.map(function (r) { return r.tokens; }).concat([1]));
f.repos.forEach(function (r, n) {
var a = run.audits[n];
var here = a && a.repo === h.target.repo && a.tool === h.tool.id;
var drill = el("li", { cls: "drillrow", hidden: "" });
var btn = el("button", { type: "button", cls: "link small", "aria-expanded": "false", text: r.findings + " findings" });
btn.addEventListener("click", function () {
var open = btn.getAttribute("aria-expanded") !== "true";
btn.setAttribute("aria-expanded", String(open));
if (open) {
drill.removeAttribute("hidden");
drill.textContent = "";
var inner = el("div", { cls: "drill" }, [el("h3", { text: r.repo + " · " + r.tool })]);
var res = el("div");
inner.appendChild(res);
drill.appendChild(inner);
drawAudit(a, res, here);
} else drill.setAttribute("hidden", "");
});
reposUl.appendChild(el("li", { cls: here ? "current" : null, style: "--kc:var(--cyan)" }, [
el("i", { cls: "fill", style: "width:" + Math.max(0.5, r.tokens / tmax * 100) + "%", "aria-hidden": "true" }),
el("span", { cls: "rowname" }, [r.repo, el("span", { cls: "meta", text: r.tool + (here ? " · this page" : "") })]),
el("span", { cls: "rownum" }, ["~" + k(r.tokens), btn])
]));
reposUl.appendChild(drill);
});
into.appendChild(reposUl);
var counts = {};
f.items.forEach(function (i) { counts[i.recommendation] = (counts[i.recommendation] || 0) + 1; });
var on = { archive: true, "move-to-project": true, unknown: true, keep: false };
into.appendChild(el("h3", { cls: "h2", style: "margin:16px 0 8px", text: "User-scope items across the repos" }));
var chips = el("div", { cls: "afilters", role: "group", "aria-label": "Filter by recommendation" });
var itemsUl = el("ul", { cls: "rows fleetitems" });
var allItems = false;
var moreBox = el("div", { cls: "more" });
var drawItems = function () {
itemsUl.textContent = "";
moreBox.textContent = "";
var matching = f.items.filter(function (i) { return on[i.recommendation]; });
var shown = allItems ? matching : matching.slice(0, 12);
if (matching.length > shown.length) {
var more = el("button", { type: "button", cls: "link", text: "Show all " + matching.length });
more.addEventListener("click", function () { allItems = true; drawItems(); var r = itemsUl.children[12]; if (r) { r.setAttribute("tabindex", "-1"); r.focus(); } });
moreBox.appendChild(more);
}
var max = Math.max.apply(null, shown.map(function (i) { return i.tokens; }).concat([1]));
shown.forEach(function (i) {
var colour = i.kind === "plugin" ? "--kc:#e8e8e8" : kc(i.kind);
var sentence = i.recommendation === "keep" ? "needed in " + i.neededIn.length + " of " + i.judged
: i.recommendation === "archive" ? (i.kind === "plugin" ? "none of " + i.judged + " repos has the files it is for" : "nothing in " + i.judged + " repos references it")
: i.recommendation === "unknown" ? "no signal to judge it by"
: "needed in " + i.neededIn.length + " of " + i.judged + ": " + i.neededIn.join(", ");
itemsUl.appendChild(el("li", { style: colour }, [
el("i", { cls: "fill", style: "width:" + Math.max(0.5, i.tokens / max * 100) + "%", "aria-hidden": "true" }),
el("span", { cls: "rowname" }, [i.name, el("span", { cls: "meta", text: i.kind + " · " + REC[i.recommendation] }), el("span", { cls: "rec", text: sentence })]),
el("span", { cls: "rownum", text: "~" + k(i.tokens) })
]));
});
if (!shown.length) itemsUl.appendChild(el("li", null, [el("span", { cls: "empty", text: "Nothing to show with these filters." })]));
};
["archive", "move-to-project", "unknown", "keep"].forEach(function (r) {
if (!counts[r]) return;
var b = el("button", { type: "button", cls: "chip", "aria-pressed": String(on[r]), text: REC[r] + " " + counts[r] });
b.addEventListener("click", function () { on[r] = !on[r]; b.setAttribute("aria-pressed", String(on[r])); drawItems(); });
chips.appendChild(b);
});
into.appendChild(chips);
into.appendChild(itemsUl);
into.appendChild(moreBox);
drawItems();
var notes = f.notes.concat(extra);
if (notes.length) into.appendChild(el("ul", { cls: "plain muted", style: "margin-top:10px" }, notes.map(function (n) { return el("li", { text: n }); })));
}
var main = el("div", { cls: "grid two" });
var left = el("div", { cls: "col" }), right = el("div", { cls: "col" });
main.appendChild(left); main.appendChild(right);
app.appendChild(el("div", { style: "height:12px" }));
app.appendChild(main);
if (cmp) {
var dsec = el("section", { cls: "box", style: "--edge:linear-gradient(90deg,var(--a),var(--b));--edge-text:var(--cyan)", "aria-labelledby": "diff-h" });
var delta = cmp.b.tokens - cmp.a.tokens;
dsec.appendChild(el("div", { cls: "head" }, [el("h2", { id: "diff-h", text: "What differs" }), el("span", { cls: "aside", text: "A " + cmp.a.tool + " · B " + cmp.b.tool })]));
dsec.appendChild(el("p", { cls: "lead" }, ["A ~" + k(cmp.a.tokens) + " and B ~" + k(cmp.b.tokens) + " estimated tokens from startup files: ", el("b", { text: delta === 0 ? "the same" : "B has " + k(Math.abs(delta)) + (delta > 0 ? " more" : " fewer") }), "."]));
dsec.appendChild(el("div", { cls: "dkey", "aria-hidden": "true" }, [
el("span", null, [el("i", { cls: "d-a" }), "only A"]), el("span", null, [el("i", { cls: "d-c" }), "changed"]),
el("span", null, [el("i", { cls: "d-s" }), "same"]), el("span", null, [el("i", { cls: "d-b" }), "only B"])
]));
KINDS.forEach(function (x) {
var c = cmp.kinds[x];
if (!c) return;
var sum = c.onlyA + c.changed + c.same + c.onlyB || 1;
var split = el("div", { cls: "dsplit", "aria-hidden": "true" });
[["d-a", c.onlyA], ["d-c", c.changed], ["d-s", c.same], ["d-b", c.onlyB]].forEach(function (p) { if (p[1]) split.appendChild(el("i", { cls: p[0], style: "width:" + p[1] / sum * 100 + "%" })); });
dsec.appendChild(el("div", { cls: "diffrow" }, [
el("span", { cls: "k" }, [el("i", { cls: "sw", style: kc(x), "aria-hidden": "true" }), TITLE[x]]),
split,
el("div", { cls: "dnums" }, [
el("span", null, ["only A ", el("b", { text: String(c.onlyA) })]), el("span", null, ["changed ", el("b", { text: String(c.changed) })]),
el("span", null, ["same ", el("b", { text: String(c.same) })]), el("span", null, ["only B ", el("b", { text: String(c.onlyB) })])
])
]));
});
function list(title, rows, cells) {
if (!rows.length) return;
var ul = el("ul", { cls: "rows" });
rows.slice(0, 15).forEach(function (r) { ul.appendChild(cells(r)); });
dsec.appendChild(el("details", { cls: "sub2" }, [
el("summary", null, [title, el("span", { cls: "aside", text: String(rows.length) })]),
ul,
rows.length > 15 ? el("p", { cls: "muted", text: "The " + (rows.length - 15) + " smallest are left out; rigswig compare --json lists them all." }) : null
]));
}
var one = function (e) { return el("li", null, [el("span", { cls: "rowname" }, [e.name, el("span", { cls: "meta", text: e.kind + " · " + e.layer })]), el("span", { cls: "rownum", text: e.chars ? "~" + k(tok(e.chars)) : "–" })]); };
var wrapDiffs = el("div", { style: "margin-top:8px" });
dsec.appendChild(wrapDiffs);
var dlist = dsec;
dsec = wrapDiffs;
list("Only in A (" + cmp.a.tool + ")", cmp.onlyA, one);
list("Only in B (" + cmp.b.tool + ")", cmp.onlyB, one);
list("In both, but different", cmp.changed, function (c) { return el("li", null, [el("span", { cls: "rowname" }, [c.name, el("span", { cls: "meta", text: c.kind })]), el("span", { cls: "rownum", text: "A ~" + k(tok(c.a.chars)) + " · B ~" + k(tok(c.b.chars)) })]); });
list("Settings that differ", cmp.settings, function (d) { return el("li", null, [el("span", { cls: "rowname mono", text: d.name }), el("span", { cls: "rownum", text: "A " + val(d.a) + " · B " + val(d.b) })]); });
left.appendChild(dlist);
}
var top = el("section", { cls: "box", "aria-labelledby": "top-h" });
top.appendChild(el("div", { cls: "head" }, [el("h2", { id: "top-h", text: "What costs the most" }), el("span", { cls: "aside", text: "at startup, by tokens" })]));
var filter = null, showAll = false;
var chips = el("div", { cls: "chips", role: "group", "aria-label": "Filter by kind" });
var body = el("div");
function drawTop(focusKind) {
chips.textContent = "";
[null].concat(KINDS.filter(function (x) { return byKind[x]; })).forEach(function (x) {
var b = el("button", { type: "button", cls: "chip", style: x ? kc(x) : null, "aria-pressed": String(filter === x), "data-k": x || "all" }, [x ? el("i", { cls: "sw", "aria-hidden": "true" }) : null, x ? TITLE[x] : "All"]);
b.addEventListener("click", function () { filter = x; showAll = false; drawTop(x || "all"); });
chips.appendChild(b);
});
if (focusKind) { var f = chips.querySelector('[data-k="' + focusKind + '"]'); if (f) f.focus(); }
body.textContent = "";
var rows = ranked.filter(function (i) { return !filter || i.kind === filter; });
var sum = rows.reduce(function (s, i) { return s + i.load.chars.value; }, 0);
var n = Math.min(3, rows.length);
var topN = rows.slice(0, n).reduce(function (s, i) { return s + i.load.chars.value; }, 0);
if (rows.length) {
body.appendChild(el("p", { cls: "lead" }, [
rows.length + " " + (filter ? TITLE[filter].toLowerCase() : "pieces") + " cost ~" + k(tok(sum)) + (filter ? " (" + pct(sum / total * 100) + " of what is measured)" : "") + "; the " + (n === 1 ? "biggest" : n + " biggest") + " are ",
el("b", { text: pct(topN / total * 100) }), "."
]));
}
var strip = el("div", { cls: "strip", "aria-hidden": "true" });
rows.slice(0, 40).forEach(function (i) { strip.appendChild(el("i", { style: kc(i.kind) + ";width:" + i.load.chars.value / total * 100 + "%", title: i.name + ": ~" + k(tok(i.load.chars.value)) })); });
strip.appendChild(el("i", { cls: "rest", title: "everything else measured" }));
body.appendChild(strip);
var shown = showAll ? rows : rows.slice(0, 12);
var max = rows.length ? rows[0].load.chars.value : 1;
var ul = el("ul", { cls: "rows dense" });
shown.forEach(function (i) {
ul.appendChild(el("li", { style: kc(i.kind) }, [
el("i", { cls: "fill", style: "width:" + Math.max(0.5, i.load.chars.value / max * 100) + "%", "aria-hidden": "true" }),
el("span", { cls: "rowname" }, [i.name, el("span", { cls: "meta" }, [el("span", { cls: "k" }, [el("i", { cls: "sw", "aria-hidden": "true" }), i.kind]), " · " + i.origin.layer])]),
el("span", { cls: "rownum" }, ["~" + k(tok(i.load.chars.value)), el("small", { text: pct(i.load.chars.value / total * 100) })])
]));
});
body.appendChild(ul);
if (rows.length > shown.length) {
var more = el("button", { type: "button", cls: "link", text: "Show all " + rows.length });
more.addEventListener("click", function () { showAll = true; drawTop(); var r = body.querySelectorAll("ul.rows > li")[12]; if (r) { r.setAttribute("tabindex", "-1"); r.focus(); } });
body.appendChild(el("div", { cls: "more" }, [more]));
}
}
drawTop();
top.appendChild(chips);
top.appendChild(body);
left.appendChild(top);
function side(id, title, aside, edge, kids, open) {
var d = el("details", { cls: "box", style: edge ? "--edge:" + edge + ";--edge-text:" + edge : null }, [
el("summary", null, [el("span", { cls: "h2", id: id, text: title }), aside ? el("span", { cls: "aside", text: aside }) : null])
].concat(kids));
if (open) d.open = true;
return d;
}
if (h.warnings.length) {
var groups = {}, order = [];
h.warnings.forEach(function (w) { if (!groups[w.code]) { groups[w.code] = []; order.push(w.code); } groups[w.code].push(w); });
var wl = el("ul", { cls: "warn" });
order.forEach(function (code) {
groups[code].forEach(function (w) { wl.appendChild(el("li", null, [w.message, w.file ? el("span", { cls: "meta mono muted", text: " " + w.file }) : null])); });
});
right.appendChild(side("warn-h", "▲ Warnings", h.warnings.length + " · " + order.join(", "), "var(--warn)", [wl], h.warnings.length <= 3));
}
var names = Object.keys(h.settings);
if (names.length) {
var sl = el("div");
names.forEach(function (name) {
var d = h.settings[name];
var v = d.value === null ? "the tool's default" : val(d.value);
var row = el("div", { cls: "setting" }, [
el("div", { cls: "n", text: name }),
el("div", { cls: "val" }, [v, d.source ? el("span", { cls: "muted", text: " · set by " + d.source }) : null])
]);
if (d.trail.length > 1) row.appendChild(el("ol", { cls: "trail", "aria-label": "Decision trail, the winner first" }, d.trail.map(function (s) {
return el("li", { text: s.layer + ": " + val(s.value) + (s.note ? " (" + s.note + ")" : "") });
})));
sl.appendChild(row);
});
right.appendChild(side("set-h", "Settings", names.length + " · where each came from", "var(--cyan)", [sl], false));
}
right.appendChild(side("cov-h", "Not modelled", String(h.coverage.notModelled.length), "#b4b4bc", [
el("ul", { cls: "plain" }, h.coverage.notModelled.map(function (n) { return el("li", { text: n }); }))
], false));
app.appendChild(el("footer", { text: "rigswig " + data.version + " · " + h.tool.id + " adapter " + h.tool.adapterVersion + " · read from files on this machine; nothing was sent or written. Reload to read again." }));
function actButton(label, on, onClick) {
var b = el("button", { type: "button", cls: "act" + (on ? " off" : ""), text: label });
b.addEventListener("click", onClick);
return b;
}
function call(route, body) {
return fetch(route + "?tool=" + encodeURIComponent(h.tool.id), {
method: "POST",
headers: { "Content-Type": "application/json", "X-Rigswig-Token": token },
body: JSON.stringify(body),
credentials: "same-origin"
}).then(function (r) { return r.json().then(function (j) { if (!r.ok) throw new Error(j.error || ("HTTP " + r.status)); return j; }); });
}
var banner = el("div", { cls: "banner", hidden: "", role: "status", "aria-live": "polite" });
if (data.writes) app.insertBefore(banner, app.children[1] || null);
function say(parts) {
banner.textContent = "";
parts.forEach(function (x) { if (x) banner.appendChild(typeof x === "string" ? document.createTextNode(x) : x); });
banner.removeAttribute("hidden");
}
var sheet = null, opener = null;
function closeSheet() {
if (sheet) { sheet.remove(); sheet = null; }
if (opener) { opener.focus(); opener = null; }
}
document.addEventListener("keydown", function (e) { if (e.key === "Escape" && sheet) closeSheet(); });
function openChange(base, title) {
closeSheet();
opener = document.activeElement;
var scope = "local";
sheet = el("section", { cls: "sheet", role: "dialog", "aria-modal": "false", "aria-labelledby": "sheet-h" });
var body = el("div");
var fs = el("fieldset", null, [el("legend", { text: "Where to write it" })]);
[["local", "This repo, just me"], ["project", "This repo, everyone (committed)"], ["user", "Every repo, just me"]].forEach(function (o) {
var input = el("input", { type: "radio", name: "scope", value: o[0] });
if (o[0] === scope) input.checked = true;
input.addEventListener("change", function () { scope = o[0]; preview(); });
fs.appendChild(el("label", null, [input, o[1]]));
});
sheet.appendChild(el("h2", { id: "sheet-h", text: title }));
sheet.appendChild(fs);
sheet.appendChild(body);
document.body.appendChild(sheet);
fs.querySelector("input").focus();
function change() { var c = JSON.parse(JSON.stringify(base)); c.scope = scope; return c; }
function preview() {
body.textContent = "Planning…";
call("/api/plan", change()).then(function (plan) {
body.textContent = "";
body.appendChild(el("p", null, [
(plan.createsFile ? "Creates " : "Changes ") , el("b", { cls: "mono", text: plan.file }),
" · budget ", el("b", { text: "~" + k(plan.tokensBefore) + " → ~" + k(plan.tokensAfter) }), " tokens"
]));
var pre = el("pre", { cls: "diff", "aria-label": "The change to the file" });
plan.diff.forEach(function (l) { pre.appendChild(el("span", { cls: l.op === "+" ? "add" : l.op === "-" ? "del" : "", text: l.op + " " + l.text })); });
body.appendChild(pre);
body.appendChild(el("ul", { cls: "notes" }, plan.notes.map(function (n) { return el("li", { text: n }); })));
var apply = el("button", { type: "button", cls: "act", text: plan.takesEffect ? "Apply" : "Apply anyway" });
var cancel = el("button", { type: "button", cls: "act off", text: "Cancel" });
cancel.addEventListener("click", closeSheet);
apply.addEventListener("click", function () {
apply.disabled = true;
call("/api/apply", { change: change(), beforeHash: plan.beforeHash }).then(function (done) {
closeSheet();
var undo = actButton("Undo", true, function () {
undo.disabled = true;
call("/api/undo", {}).then(function (u) { say(["Undone: ", el("b", { cls: "mono", text: u.undone }), " is back as it was. ", reload()]); })
.catch(function (e) { say(["Undo failed: " + e.message]); });
});
say(["Applied to ", el("b", { cls: "mono", text: done.applied }), done.backup ? " · backup saved" : " · new file", " · takes effect in the next session. ", undo, reload()]);
undo.focus();
}).catch(function (e) { apply.disabled = false; body.appendChild(el("p", { cls: "err", text: e.message })); });
});
body.appendChild(el("div", { cls: "row" }, [apply, cancel]));
}).catch(function (e) {
body.textContent = "";
body.appendChild(el("p", { cls: "err", text: e.message }));
var cancel = el("button", { type: "button", cls: "act off", text: "Close" });
cancel.addEventListener("click", closeSheet);
body.appendChild(el("div", { cls: "row" }, [cancel]));
});
}
preview();
}
function reload() {
var b = actButton("Reload to read again", false, function () { location.reload(); });
return b;
}
})();
</script>
</body>
</html>