@basou/cli 0.71.2 → 0.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +275 -48
- package/dist/index.js.map +1 -1
- package/dist/program.js +275 -48
- package/dist/program.js.map +1 -1
- package/package.json +2 -2
package/dist/program.js
CHANGED
|
@@ -840,11 +840,13 @@ import {
|
|
|
840
840
|
assertBasouRootSafe as assertBasouRootSafe3,
|
|
841
841
|
BOARD_INIT_SAVE,
|
|
842
842
|
basouPaths as basouPaths4,
|
|
843
|
+
boardDeclarationSnapshot,
|
|
843
844
|
boardGuide,
|
|
844
845
|
boardInitText,
|
|
845
846
|
buildRecord,
|
|
846
847
|
byCodePoint,
|
|
847
848
|
diffCells,
|
|
849
|
+
diffDeclarations,
|
|
848
850
|
diffObserved,
|
|
849
851
|
displayPath as displayPath3,
|
|
850
852
|
effortStartOf,
|
|
@@ -2343,9 +2345,10 @@ async function doRunBoardMeasure(options, ctx) {
|
|
|
2343
2345
|
throw new Error("--model must name a model.");
|
|
2344
2346
|
}
|
|
2345
2347
|
const loaded = await loadBoard(options, ctx, "board measure");
|
|
2346
|
-
const
|
|
2348
|
+
const previous = await previousOf(loaded);
|
|
2349
|
+
const measurement = await measureLoaded(loaded, ctx, options.model, previous);
|
|
2347
2350
|
if (options.json === true) console.log(JSON.stringify(measurement, null, 2));
|
|
2348
|
-
else printMeasurementText(measurement, hasRecords(loaded));
|
|
2351
|
+
else printMeasurementText(measurement, hasRecords(loaded), declarationChanges(loaded, previous));
|
|
2349
2352
|
if (!measurement.complete) process.exitCode = 1;
|
|
2350
2353
|
return measurement;
|
|
2351
2354
|
}
|
|
@@ -2360,16 +2363,17 @@ async function runBoardRecord(options, ctx = {}) {
|
|
|
2360
2363
|
var RecordRefusal = class extends Error {
|
|
2361
2364
|
};
|
|
2362
2365
|
async function doRunBoardRecord(options, ctx) {
|
|
2363
|
-
let
|
|
2366
|
+
let checked;
|
|
2364
2367
|
try {
|
|
2365
|
-
|
|
2368
|
+
checked = await checkAndRecord(options, ctx);
|
|
2366
2369
|
} catch (error) {
|
|
2367
2370
|
if (error instanceof RecordRefusal || !(error instanceof Error)) throw error;
|
|
2368
2371
|
throw new RecordRefusal(`${error.message}
|
|
2369
2372
|
Nothing was written.`, { cause: error.cause });
|
|
2370
2373
|
}
|
|
2374
|
+
const { result, declared } = checked;
|
|
2371
2375
|
if (options.json === true) console.log(JSON.stringify(result, null, 2));
|
|
2372
|
-
else printRecordText(result);
|
|
2376
|
+
else printRecordText(result, declared ?? null);
|
|
2373
2377
|
return result;
|
|
2374
2378
|
}
|
|
2375
2379
|
async function checkAndRecord(options, ctx) {
|
|
@@ -2410,6 +2414,7 @@ ${parsed.errors.map((e) => ` - ${displayPath3(e)}`).join("\n")}`
|
|
|
2410
2414
|
recordedAt,
|
|
2411
2415
|
recordedWith: { basou: BASOU_CLI_VERSION, build: BASOU_BUILD?.commit ?? null }
|
|
2412
2416
|
});
|
|
2417
|
+
const declared = options.json === true ? void 0 : declarationChanges(loaded, previous);
|
|
2413
2418
|
let written = null;
|
|
2414
2419
|
if (options.dryRun !== true) {
|
|
2415
2420
|
let name;
|
|
@@ -2436,14 +2441,22 @@ ${parsed.errors.map((e) => ` - ${displayPath3(e)}`).join("\n")}`
|
|
|
2436
2441
|
};
|
|
2437
2442
|
}
|
|
2438
2443
|
return {
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2444
|
+
result: {
|
|
2445
|
+
record: written,
|
|
2446
|
+
dry_run: options.dryRun === true,
|
|
2447
|
+
complete: measurement.complete,
|
|
2448
|
+
not_found: measurement.not_found,
|
|
2449
|
+
order_anomalies: record.order_anomalies,
|
|
2450
|
+
diff
|
|
2451
|
+
},
|
|
2452
|
+
...declared === void 0 ? {} : { declared }
|
|
2445
2453
|
};
|
|
2446
2454
|
}
|
|
2455
|
+
function declarationChanges(loaded, previous) {
|
|
2456
|
+
const { last } = previous;
|
|
2457
|
+
if (last.status !== "found") return null;
|
|
2458
|
+
return diffDeclarations(last.record.declaration, boardDeclarationSnapshot(loaded.declaration));
|
|
2459
|
+
}
|
|
2447
2460
|
var INPUT_KEYS = /* @__PURE__ */ new Set([
|
|
2448
2461
|
"measure_digest",
|
|
2449
2462
|
"observed",
|
|
@@ -2593,7 +2606,7 @@ async function checkRecordsPlace(loaded, recordsDir, shown, notPrivate) {
|
|
|
2593
2606
|
}
|
|
2594
2607
|
}
|
|
2595
2608
|
}
|
|
2596
|
-
function printRecordText(result) {
|
|
2609
|
+
function printRecordText(result, declared) {
|
|
2597
2610
|
const lines = [
|
|
2598
2611
|
result.record === null ? "Dry run: the record checked out (nothing was written)." : `Recorded ${displayPath3(result.record)}`
|
|
2599
2612
|
];
|
|
@@ -2614,7 +2627,11 @@ function printRecordText(result) {
|
|
|
2614
2627
|
` observed ${displayPath3(o.name)}: ${observation(o.before)} -> ${observation(o.after)}`
|
|
2615
2628
|
);
|
|
2616
2629
|
}
|
|
2617
|
-
|
|
2630
|
+
const declaration = declarationLines(declared);
|
|
2631
|
+
lines.push(
|
|
2632
|
+
...diffLines(result.diff.measure, cells.length + observed.length + declaration.length > 0),
|
|
2633
|
+
...declaration
|
|
2634
|
+
);
|
|
2618
2635
|
}
|
|
2619
2636
|
if (!result.complete) {
|
|
2620
2637
|
lines.push(`The measurement recorded is not complete (${result.not_found.length}):`);
|
|
@@ -2800,6 +2817,16 @@ function diffLines(diff, more) {
|
|
|
2800
2817
|
if (lines.length === 0 && !more) lines.push(" nothing moved");
|
|
2801
2818
|
return lines;
|
|
2802
2819
|
}
|
|
2820
|
+
function declarationLines(changes) {
|
|
2821
|
+
if (changes === null) {
|
|
2822
|
+
return [
|
|
2823
|
+
" declaration: not compared (the previous record holds no declaration basou can compare with)"
|
|
2824
|
+
];
|
|
2825
|
+
}
|
|
2826
|
+
return changes.map(
|
|
2827
|
+
(c) => ` declaration ${displayPath3(c.at)}: ${c.change === "reordered" ? "the order changed" : c.change}`
|
|
2828
|
+
);
|
|
2829
|
+
}
|
|
2803
2830
|
function shownValue(value) {
|
|
2804
2831
|
if (value === null) return "not measured";
|
|
2805
2832
|
if (typeof value === "number") return String(Math.round(value * 1e4) / 1e4);
|
|
@@ -2931,12 +2958,18 @@ function axisLines(m) {
|
|
|
2931
2958
|
for (const u of a.unjudged) lines.push(` (${u.trigger}) not judged: ${u.why}`);
|
|
2932
2959
|
return lines;
|
|
2933
2960
|
}
|
|
2934
|
-
function printMeasurementText(m, hasRecords2) {
|
|
2961
|
+
function printMeasurementText(m, hasRecords2, declared) {
|
|
2935
2962
|
const lines = [displayPath3(m.title)];
|
|
2936
2963
|
const build = m.measured_with.build === null ? "" : ` (build ${m.measured_with.build})`;
|
|
2937
2964
|
lines.push(`Measured ${m.measured_at} with basou ${m.measured_with.basou}${build}`);
|
|
2938
2965
|
if (m.diff !== null) {
|
|
2939
|
-
|
|
2966
|
+
const declaration = declarationLines(declared);
|
|
2967
|
+
lines.push(
|
|
2968
|
+
"",
|
|
2969
|
+
`Since the previous record ${m.diff.against}:`,
|
|
2970
|
+
...diffLines(m.diff, declaration.length > 0),
|
|
2971
|
+
...declaration
|
|
2972
|
+
);
|
|
2940
2973
|
} else if (m.not_found.some((n) => n.at === "diff")) {
|
|
2941
2974
|
lines.push("", "The previous record could not be read (see Not measured).");
|
|
2942
2975
|
} else {
|
|
@@ -13936,6 +13969,17 @@ var BOARD_HTML = `<!doctype html>
|
|
|
13936
13969
|
table.matrix th.stage { font-weight: 400; font-size: 12px; text-align: center; min-width: 64px; }
|
|
13937
13970
|
table.matrix th.stage b { display: block; font-size: 13px; }
|
|
13938
13971
|
table.matrix td.cell { text-align: center; font-size: 18px; line-height: 1; }
|
|
13972
|
+
.stage-meanings { display: none; list-style: none; padding: 0; margin: 6px 0 0; font-size: 12px; color: var(--fg-2); }
|
|
13973
|
+
/* Six stages do not fit beside their meanings below about 600px: each is
|
|
13974
|
+
drawn by its id, the meanings are listed under the matrix, and a lane
|
|
13975
|
+
name wraps. After the rules above, which it overrides. */
|
|
13976
|
+
@media (max-width: 600px) {
|
|
13977
|
+
table.matrix th.stage { min-width: 0; padding: 4px 2px; }
|
|
13978
|
+
table.matrix th.stage .meaning { display: none; }
|
|
13979
|
+
table.matrix td.cell { font-size: 16px; padding: 4px 2px; }
|
|
13980
|
+
table.matrix th:first-child { max-width: 10em; overflow-wrap: anywhere; }
|
|
13981
|
+
.stage-meanings { display: block; }
|
|
13982
|
+
}
|
|
13939
13983
|
.st::before { display: inline-block; width: 1.2em; }
|
|
13940
13984
|
.st.done::before { content: "\\25CF"; color: var(--done); }
|
|
13941
13985
|
.st.part::before { content: "\\25D0"; color: var(--done); }
|
|
@@ -13956,6 +14000,11 @@ var BOARD_HTML = `<!doctype html>
|
|
|
13956
14000
|
.chip.blocked { background: var(--chip-blocked); }
|
|
13957
14001
|
.chip.unverified { background: var(--chip-unverified); }
|
|
13958
14002
|
.muted { color: var(--fg-2); }
|
|
14003
|
+
.sub { font-size: 12px; color: var(--fg-2); overflow-wrap: anywhere; }
|
|
14004
|
+
ul.sub { margin: 0; padding-left: 18px; }
|
|
14005
|
+
td.wrap { overflow-wrap: anywhere; min-width: 10em; }
|
|
14006
|
+
tr.notes td { padding-top: 0; }
|
|
14007
|
+
.chip.changed { margin-left: 0; margin-right: 6px; background: var(--chip-unverified); }
|
|
13959
14008
|
.bar { height: 10px; background: var(--fill); border-radius: 5px; min-width: 120px; position: relative; overflow: hidden; }
|
|
13960
14009
|
.bar span { position: absolute; left: 0; top: 0; bottom: 0; background: var(--s1); }
|
|
13961
14010
|
figure { margin: 16px 0; }
|
|
@@ -14085,6 +14134,60 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14085
14134
|
return JSON.stringify(k) + ':' + v;
|
|
14086
14135
|
}).join(',') + '}';
|
|
14087
14136
|
}
|
|
14137
|
+
// The parts of a value drawn on one line, and what an http value says of each word.
|
|
14138
|
+
var DOT = ' ' + String.fromCharCode(183) + ' ';
|
|
14139
|
+
var FOUND = String.fromCharCode(10003);
|
|
14140
|
+
var NOT_FOUND = String.fromCharCode(10007);
|
|
14141
|
+
// An http value read as its parts: the status, the redirects, where it
|
|
14142
|
+
// landed, and what it read off the body (when the status is 2xx) or that it
|
|
14143
|
+
// did not. Numbers and strings are drawn as they are.
|
|
14144
|
+
function httpText(h) {
|
|
14145
|
+
var parts = [String(h.status), fill(S.observed.redirects, { n: h.redirects }), h.final_url];
|
|
14146
|
+
if (h.body === null) parts.push(S.observed.bodyNotRead);
|
|
14147
|
+
else if (h.body) {
|
|
14148
|
+
if (h.body.words) {
|
|
14149
|
+
parts.push(h.body.words.map(function (w) { return w.word + ' ' + (w.found ? FOUND : NOT_FOUND); }).join(' '));
|
|
14150
|
+
}
|
|
14151
|
+
if (h.body.count !== undefined) parts.push(fill(S.observed.count, { n: h.body.count }));
|
|
14152
|
+
if (h.body.capture !== undefined) {
|
|
14153
|
+
parts.push(h.body.capture === null ? S.observed.captureNone : fill(S.observed.capture, { value: JSON.stringify(h.body.capture) }));
|
|
14154
|
+
}
|
|
14155
|
+
}
|
|
14156
|
+
return parts.join(DOT);
|
|
14157
|
+
}
|
|
14158
|
+
// A value of an observation as the page draws it: an http value in its
|
|
14159
|
+
// shape read as its parts, one with words beside what it says of each, and
|
|
14160
|
+
// any other as it is (a string) or as JSON. A test lifts this function.
|
|
14161
|
+
function observedText(value, words, http) {
|
|
14162
|
+
if (http) return httpText(http);
|
|
14163
|
+
if (words) return withWords(value, words);
|
|
14164
|
+
return shown(value);
|
|
14165
|
+
}
|
|
14166
|
+
// The value of an observation that moved, and what the previous record
|
|
14167
|
+
// held: a value whose type alone moved ("12" and 12) is drawn as JSON, so
|
|
14168
|
+
// that the two do not read the same. A test lifts this function.
|
|
14169
|
+
function movedText(o) {
|
|
14170
|
+
var m = o.moved;
|
|
14171
|
+
var now = observedText(o.value, o.words, o.http);
|
|
14172
|
+
if (m.status === 'none') return { now: now, then: S.observed.beforeNone };
|
|
14173
|
+
if (m.value === null) {
|
|
14174
|
+
return { now: now, then: S.observed.beforeNotObserved + (m.error ? ' (' + m.error + ')' : '') };
|
|
14175
|
+
}
|
|
14176
|
+
var then = observedText(m.value, m.words, m.http);
|
|
14177
|
+
if ((typeof m.value === 'string') !== (typeof o.value === 'string')) {
|
|
14178
|
+
then = JSON.stringify(m.value);
|
|
14179
|
+
if (then === now) now = JSON.stringify(o.value);
|
|
14180
|
+
}
|
|
14181
|
+
return { now: now, then: fill(S.observed.before, { value: then }) + (m.error ? ' (' + m.error + ')' : '') };
|
|
14182
|
+
}
|
|
14183
|
+
// A measure's value: the paths of a file_paths by how many, a number with
|
|
14184
|
+
// its unit, and a string (a file's name, a capture), which is no amount,
|
|
14185
|
+
// without it.
|
|
14186
|
+
function measureText(m) {
|
|
14187
|
+
if (Array.isArray(m.value)) return num(m.value.length) + ' ' + m.unit;
|
|
14188
|
+
return num(m.value) + (typeof m.value === 'number' ? ' ' + m.unit : '');
|
|
14189
|
+
}
|
|
14190
|
+
function signed(n) { return (n > 0 ? '+' : '') + num(n); }
|
|
14088
14191
|
function stateName(state) { return S.states[state] || state; }
|
|
14089
14192
|
function setStatus(message, isErr) {
|
|
14090
14193
|
var s = $('status');
|
|
@@ -14165,21 +14268,47 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14165
14268
|
k, el('div', { class: 'v', text: num(t.value) }), sub === null ? null : el('div', { class: 's', text: sub })
|
|
14166
14269
|
]));
|
|
14167
14270
|
});
|
|
14271
|
+
return section(S.sections.summary, false, [el('div', null, [prose(s.text), reported()]), tiles]);
|
|
14272
|
+
}
|
|
14273
|
+
|
|
14274
|
+
// The observations outside, which the record holds in its summary, in a
|
|
14275
|
+
// section of their own after the lanes.
|
|
14276
|
+
function observations(b) {
|
|
14277
|
+
var s = b.summary;
|
|
14168
14278
|
var observed;
|
|
14169
14279
|
if (s.observed.length === 0) {
|
|
14170
14280
|
observed = el('p', { class: 'muted', text: S.observed.none });
|
|
14171
14281
|
} else {
|
|
14172
|
-
var rows =
|
|
14282
|
+
var rows = [];
|
|
14283
|
+
s.observed.forEach(function (o) {
|
|
14284
|
+
var cell = el('td', { class: 'wrap' });
|
|
14173
14285
|
var value;
|
|
14174
|
-
if (o.value !== null
|
|
14175
|
-
|
|
14176
|
-
|
|
14177
|
-
|
|
14178
|
-
|
|
14179
|
-
|
|
14180
|
-
|
|
14181
|
-
|
|
14182
|
-
|
|
14286
|
+
if (o.value !== null && o.moved) {
|
|
14287
|
+
var pair = movedText(o);
|
|
14288
|
+
cell.appendChild(el('span', { class: 'chip changed', text: S.observed.changed }));
|
|
14289
|
+
value = pair.now;
|
|
14290
|
+
cell.appendChild(el('span', { text: value + (o.error ? ' (' + o.error + ')' : '') }));
|
|
14291
|
+
cell.appendChild(el('div', { class: 'sub', text: pair.then }));
|
|
14292
|
+
} else {
|
|
14293
|
+
if (o.value !== null) value = observedText(o.value, o.words, o.http);
|
|
14294
|
+
else if (o.previous && o.previous.status === 'value') value = fill(S.observed.missing, { value: shown(o.previous.value) });
|
|
14295
|
+
else if (o.previous && o.previous.status === 'unreadable') value = S.observed.missingPreviousUnreadable;
|
|
14296
|
+
else value = S.observed.missingNoPrevious;
|
|
14297
|
+
if (o.error) value += ' (' + o.error + ')';
|
|
14298
|
+
cell.appendChild(el('span', { text: value }));
|
|
14299
|
+
}
|
|
14300
|
+
// What the record's declaration says it is and looks at, under its name.
|
|
14301
|
+
var what = o.kind ? [o.kind].concat(o.looks_at || []).join(DOT) : null;
|
|
14302
|
+
rows.push(el('tr', null, [
|
|
14303
|
+
el('td', null, [el('div', { text: o.name }), what === null ? null : el('div', { class: 'sub', text: what })]),
|
|
14304
|
+
cell,
|
|
14305
|
+
el('td', { text: o.observed_at }), el('td', { class: 'wrap', text: o.source })
|
|
14306
|
+
]));
|
|
14307
|
+
if (o.notes && o.notes.length > 0) {
|
|
14308
|
+
rows.push(el('tr', { class: 'notes' }, [el('td', { colspan: '4' }, [
|
|
14309
|
+
el('ul', { class: 'sub' }, o.notes.map(function (n) { return el('li', null, [prose(n, 'span')]); }))
|
|
14310
|
+
])]));
|
|
14311
|
+
}
|
|
14183
14312
|
});
|
|
14184
14313
|
observed = el('div', { class: 'scroll' }, [el('table', { class: 'grid' }, [
|
|
14185
14314
|
el('tr', null, [
|
|
@@ -14188,13 +14317,11 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14188
14317
|
])
|
|
14189
14318
|
].concat(rows))]);
|
|
14190
14319
|
}
|
|
14191
|
-
var
|
|
14192
|
-
|
|
14193
|
-
el('
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
observed
|
|
14197
|
-
]);
|
|
14320
|
+
var children = [observed];
|
|
14321
|
+
if (s.previous_record === 'unreadable' && s.observed.length > 0) {
|
|
14322
|
+
children.push(el('p', { class: 'muted', text: S.observed.previousUnreadable }));
|
|
14323
|
+
}
|
|
14324
|
+
return section(S.observed.heading, true, children);
|
|
14198
14325
|
}
|
|
14199
14326
|
|
|
14200
14327
|
var SVGNS = 'http://www.w3.org/2000/svg';
|
|
@@ -14426,16 +14553,24 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14426
14553
|
]);
|
|
14427
14554
|
};
|
|
14428
14555
|
var union = e.active_ms.union;
|
|
14556
|
+
// Over the daily rows, today's included (one more than the days elapsed),
|
|
14557
|
+
// so that the first day is a day; the sub-text names the divisor.
|
|
14429
14558
|
var perDay = union === null || !e.period_days ? null : union / e.period_days;
|
|
14430
14559
|
var perWorked = union === null || !e.active_days ? null : union / e.active_days;
|
|
14560
|
+
var perDaySub = [
|
|
14561
|
+
perDay === null ? null : fill(S.effort.perDayOver, { days: num(e.period_days) }),
|
|
14562
|
+
perWorked === null ? null : fill(S.effort.perDayWorked, { time: hm(perWorked) })
|
|
14563
|
+
].filter(function (part) { return part !== null; }).join(DOT);
|
|
14431
14564
|
var tokens = e.sessions_without_tokens ? fill(S.effort.withoutTokens, { n: e.sessions_without_tokens }) : null;
|
|
14565
|
+
// Each tool's time is the union of its sessions' intervals, as Active is.
|
|
14566
|
+
var unionOf = function (ms) { return ms === null ? null : S.effort.toolUnion; };
|
|
14432
14567
|
var tiles = el('div', { class: 'tiles' }, [
|
|
14433
14568
|
tile(S.effort.elapsed, e.elapsed_days === null ? S.effort.notMeasured : fill(S.effort.days, { days: e.elapsed_days }),
|
|
14434
14569
|
e.time_zone === null ? fill(S.effort.from, { date: e.start }) : fill(S.effort.fromZone, { date: e.start, zone: e.time_zone })),
|
|
14435
14570
|
tile(S.effort.active, hm(union), e.active_days === null ? null : fill(S.effort.daysWorked, { n: e.active_days })),
|
|
14436
|
-
tile(S.effort.claude, hm(e.active_ms.claude),
|
|
14437
|
-
tile(S.effort.codex, e.active_ms.codex === null && union !== null ? S.effort.noCodex : hm(e.active_ms.codex),
|
|
14438
|
-
tile(S.effort.perDay, hm(perDay),
|
|
14571
|
+
tile(S.effort.claude, hm(e.active_ms.claude), unionOf(e.active_ms.claude)),
|
|
14572
|
+
tile(S.effort.codex, e.active_ms.codex === null && union !== null ? S.effort.noCodex : hm(e.active_ms.codex), unionOf(e.active_ms.codex)),
|
|
14573
|
+
tile(S.effort.perDay, hm(perDay), perDaySub),
|
|
14439
14574
|
tile(S.effort.outputTokens, num(e.output_tokens), tokens)
|
|
14440
14575
|
]);
|
|
14441
14576
|
var commits = e.commits === null ? S.effort.notMeasured : e.commits.map(function (c) {
|
|
@@ -14473,8 +14608,13 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14473
14608
|
})
|
|
14474
14609
|
)));
|
|
14475
14610
|
}
|
|
14611
|
+
// The meaning is the head's title too, as a screen reader reads it and a
|
|
14612
|
+
// pointer that hovers shows it, and the text beside the id is left out of
|
|
14613
|
+
// what a screen reader reads, so that it is read once.
|
|
14476
14614
|
var head = el('tr', null, [el('th', { text: S.matrix.lane })].concat(x.stages.map(function (s) {
|
|
14477
|
-
return el('th', { class: 'stage'
|
|
14615
|
+
return el('th', { class: 'stage', title: s.meaning }, [
|
|
14616
|
+
el('b', { text: s.id }), el('span', { class: 'meaning', 'aria-hidden': 'true', text: s.meaning })
|
|
14617
|
+
]);
|
|
14478
14618
|
})));
|
|
14479
14619
|
var rows = x.lanes.map(function (lane) {
|
|
14480
14620
|
return el('tr', null, [el('th', { text: lane.name })].concat(lane.cells.map(function (c) {
|
|
@@ -14486,6 +14626,11 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14486
14626
|
})));
|
|
14487
14627
|
});
|
|
14488
14628
|
children.push(el('div', { class: 'scroll' }, [el('table', { class: 'matrix' }, [head].concat(rows))]));
|
|
14629
|
+
// What each stage means, drawn where a narrow screen gives a stage its id
|
|
14630
|
+
// alone (and hidden where the heads say it).
|
|
14631
|
+
children.push(el('ul', { class: 'stage-meanings' }, x.stages.map(function (s) {
|
|
14632
|
+
return el('li', null, [el('b', { text: s.id }), ' ' + s.meaning]);
|
|
14633
|
+
})));
|
|
14489
14634
|
var legend = el('div', { class: 'legend' });
|
|
14490
14635
|
['done', 'part', 'blocked', 'shelved', 'none', 'unverified'].forEach(function (s) {
|
|
14491
14636
|
legend.appendChild(el('span', null, [el('span', { class: 'st ' + s }), stateName(s)]));
|
|
@@ -14533,6 +14678,27 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14533
14678
|
}));
|
|
14534
14679
|
}
|
|
14535
14680
|
|
|
14681
|
+
// Every measure of the record, with the lanes it is drawn in and how much a
|
|
14682
|
+
// number moved since the previous record.
|
|
14683
|
+
function measures(b) {
|
|
14684
|
+
if (b.measures.length === 0) {
|
|
14685
|
+
return section(S.sections.measures, false, [el('p', { class: 'muted', text: S.measures.none })]);
|
|
14686
|
+
}
|
|
14687
|
+
var head = el('tr', null, [
|
|
14688
|
+
el('th', { text: S.measures.id }), el('th', { text: S.measures.value }),
|
|
14689
|
+
el('th', { text: S.measures.lanes }), el('th', { class: 'n', text: S.measures.delta })
|
|
14690
|
+
]);
|
|
14691
|
+
var rows = b.measures.map(function (m) {
|
|
14692
|
+
return el('tr', { 'data-measure': m.id }, [
|
|
14693
|
+
el('td', null, [el('code', { text: m.id })]),
|
|
14694
|
+
el('td', { class: 'wrap', text: measureText(m) }),
|
|
14695
|
+
el('td', { text: m.lanes.length === 0 ? '-' : m.lanes.join(', ') }),
|
|
14696
|
+
el('td', { class: 'n', text: m.delta === null || m.delta === undefined ? '' : signed(m.delta) })
|
|
14697
|
+
]);
|
|
14698
|
+
});
|
|
14699
|
+
return section(S.sections.measures, false, [el('div', { class: 'scroll' }, [el('table', { class: 'grid' }, [head].concat(rows))])]);
|
|
14700
|
+
}
|
|
14701
|
+
|
|
14536
14702
|
function composition(b) {
|
|
14537
14703
|
if (b.composition.length === 0) {
|
|
14538
14704
|
return section(S.sections.composition, false, [el('p', { class: 'muted', text: S.composition.none })]);
|
|
@@ -14620,7 +14786,10 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14620
14786
|
var b = page.board;
|
|
14621
14787
|
// The board's own title, so that boards open in other tabs can be told apart.
|
|
14622
14788
|
document.title = b.heading.title;
|
|
14623
|
-
|
|
14789
|
+
// Where each lane stops, right under the summary's tiles, and the lanes,
|
|
14790
|
+
// before the observations and the charts of the effort.
|
|
14791
|
+
[heading(b), summary(b), matrix(b), lanes(b), observations(b), effort(b, false), measures(b), composition(b),
|
|
14792
|
+
turns(b), recordRepos(b), recordComponents(b), footnotes(b)]
|
|
14624
14793
|
.forEach(function (node) { root.appendChild(node); });
|
|
14625
14794
|
}
|
|
14626
14795
|
|
|
@@ -14646,12 +14815,14 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14646
14815
|
function missingIn(l) {
|
|
14647
14816
|
return function (at) { return l.footnotes.not_found.some(function (n) { return n.at === at; }); };
|
|
14648
14817
|
}
|
|
14649
|
-
|
|
14650
|
-
|
|
14651
|
-
|
|
14652
|
-
|
|
14818
|
+
// The repositories as a table. older: a record of version 1 or 2, which
|
|
14819
|
+
// measured no base, ahead or fetch time (drawn as '-') and held the
|
|
14820
|
+
// commits behind as behind_main.
|
|
14821
|
+
function reposTable(list, missing, older) {
|
|
14822
|
+
var labels = [S.live.repo, S.live.branch, S.live.head, S.live.lastCommit, S.live.commits, S.live.files, S.live.uncommitted, S.live.base, S.live.behind, S.live.ahead, S.live.fetchedAt];
|
|
14823
|
+
var numeric = [4, 5, 6, 8, 9];
|
|
14653
14824
|
var head = el('tr', null, labels.map(function (label, i) { return el('th', { class: numeric.indexOf(i) !== -1 ? 'n' : '', text: label }); }));
|
|
14654
|
-
var rows =
|
|
14825
|
+
var rows = list.map(function (r) {
|
|
14655
14826
|
var at = 'repos[' + r.path + ']';
|
|
14656
14827
|
// A null the measurement says it could not measure, or one that means
|
|
14657
14828
|
// so (a detached HEAD, no commit yet, no base, no fetch of it on
|
|
@@ -14660,20 +14831,76 @@ var BOARD_HTML = `<!doctype html>
|
|
|
14660
14831
|
if (v !== null) return show(v);
|
|
14661
14832
|
return missing(at) || missing(at + '.' + field) ? S.tiles.notMeasured : '-';
|
|
14662
14833
|
};
|
|
14834
|
+
var unmeasured = function (field, v, show) { return older ? '-' : value(field, v, show); };
|
|
14663
14835
|
return el('tr', null, [
|
|
14664
14836
|
el('td', { text: r.name === null ? r.path : r.name }),
|
|
14665
14837
|
el('td', { text: value('branch', r.branch, String) }),
|
|
14666
14838
|
el('td', { text: value('head', r.head, function (h) { return h.slice(0, 7); }) }),
|
|
14667
14839
|
el('td', { text: value('last_commit', r.last_commit, when) }),
|
|
14668
14840
|
el('td', { class: 'n', text: num(r.commits) }),
|
|
14841
|
+
el('td', { class: 'n', text: num(r.files) }),
|
|
14669
14842
|
el('td', { class: 'n', text: num(r.uncommitted) }),
|
|
14670
|
-
el('td', { text:
|
|
14671
|
-
el('td', { class: 'n', text: value('behind', r.behind, num) }),
|
|
14672
|
-
el('td', { class: 'n', text:
|
|
14673
|
-
el('td', { text:
|
|
14843
|
+
el('td', { text: unmeasured('base', r.base, String) }),
|
|
14844
|
+
el('td', { class: 'n', text: value(older ? 'behind_main' : 'behind', r.behind, num) }),
|
|
14845
|
+
el('td', { class: 'n', text: unmeasured('ahead', r.ahead, num) }),
|
|
14846
|
+
el('td', { text: unmeasured('fetched_at', r.fetched_at, when) })
|
|
14674
14847
|
]);
|
|
14675
14848
|
});
|
|
14676
|
-
return
|
|
14849
|
+
return el('div', { class: 'scroll' }, [el('table', { class: 'grid' }, [head].concat(rows))]);
|
|
14850
|
+
}
|
|
14851
|
+
function liveRepos(l) {
|
|
14852
|
+
return section(S.live.repos, false, [reposTable(l.repos, missingIn(l), false)]);
|
|
14853
|
+
}
|
|
14854
|
+
// The repositories as the record measured them, by its version.
|
|
14855
|
+
function recordRepos(b) {
|
|
14856
|
+
var r = b.repos;
|
|
14857
|
+
if (!r) return section(S.live.repos, false, [el('p', { class: 'muted', text: S.record.reposUnread })]);
|
|
14858
|
+
var children = [reposTable(r.list, missingIn(b), !r.base_measured)];
|
|
14859
|
+
if (!r.base_measured) children.push(el('p', { class: 'muted', text: fill(S.record.notMeasuredByVersion, { version: r.record_version }) }));
|
|
14860
|
+
return section(S.live.repos, false, children);
|
|
14861
|
+
}
|
|
14862
|
+
// The components the record found, by the lanes its registry counts them
|
|
14863
|
+
// in, then those in no lane (folded), those not registered, and those gone.
|
|
14864
|
+
function recordComponents(b) {
|
|
14865
|
+
var c = b.components;
|
|
14866
|
+
if (!c) return section(S.live.components, false, [el('p', { class: 'muted', text: S.record.componentsUnread })]);
|
|
14867
|
+
if (!c.measured) {
|
|
14868
|
+
return section(S.live.components, false, [
|
|
14869
|
+
el('p', { class: 'muted', text: S.record.componentsNotMeasured }),
|
|
14870
|
+
el('ul', null, c.reasons.map(function (reason) { return el('li', { text: reason }); }))
|
|
14871
|
+
]);
|
|
14872
|
+
}
|
|
14873
|
+
var item = function (x) {
|
|
14874
|
+
var kinds = x.kinds === null ? S.record.notFound : x.kinds.join(', ');
|
|
14875
|
+
var parts = [el('code', { text: x.key }), el('span', { class: 'muted', text: ' ' + kinds })];
|
|
14876
|
+
if (x.kind_changed) {
|
|
14877
|
+
parts.push(el('span', { class: 'chip changed', text: fill(S.record.kindChanged, { before: x.kind_changed.before.join(', ') }) }));
|
|
14878
|
+
}
|
|
14879
|
+
if (x.note) parts.push(el('div', { class: 'sub', text: x.note }));
|
|
14880
|
+
return el('li', { 'data-component': x.key }, parts);
|
|
14881
|
+
};
|
|
14882
|
+
var group = function (title, list, empty) {
|
|
14883
|
+
return [el('h3', { text: title }), list.length === 0 ? el('p', { class: 'muted', text: empty }) : el('ul', null, list.map(item))];
|
|
14884
|
+
};
|
|
14885
|
+
var children = [];
|
|
14886
|
+
c.lanes.forEach(function (lane) {
|
|
14887
|
+
children = children.concat(group(lane.name, lane.components, S.record.noComponentInLane));
|
|
14888
|
+
});
|
|
14889
|
+
// Those in no lane can be most of them: folded under how many they are.
|
|
14890
|
+
if (c.uncounted.length > 0) {
|
|
14891
|
+
children.push(el('details', null, [
|
|
14892
|
+
el('summary', { text: fill(S.record.uncountedFolded, { n: num(c.uncounted.length) }) }),
|
|
14893
|
+
el('ul', null, c.uncounted.map(item))
|
|
14894
|
+
]));
|
|
14895
|
+
} else {
|
|
14896
|
+
children = children.concat(group(S.record.uncounted, c.uncounted, S.record.none));
|
|
14897
|
+
}
|
|
14898
|
+
children = children.concat(group(S.record.unacknowledged, c.unacknowledged, S.record.none));
|
|
14899
|
+
children.push(el('h3', { text: S.record.gone }));
|
|
14900
|
+
children.push(c.gone === null ? el('p', { class: 'muted', text: S.record.goneUnknown })
|
|
14901
|
+
: c.gone.length === 0 ? el('p', { class: 'muted', text: S.record.none })
|
|
14902
|
+
: el('ul', null, c.gone.map(function (key) { return el('li', null, [el('code', { text: key })]); })));
|
|
14903
|
+
return section(S.live.components, false, children);
|
|
14677
14904
|
}
|
|
14678
14905
|
function liveTrail(l) {
|
|
14679
14906
|
var t = l.trail;
|
|
@@ -16334,7 +16561,7 @@ function installExperimentalNotice(program, names = EXPERIMENTAL_COMMANDS, write
|
|
|
16334
16561
|
function readBuildStamp() {
|
|
16335
16562
|
if (false) return void 0;
|
|
16336
16563
|
try {
|
|
16337
|
-
return JSON.parse('{"version":"0.
|
|
16564
|
+
return JSON.parse('{"version":"0.73.0","commit":"fdfa3a5","committedAt":"2026-10-20T20:30:59+09:00"}');
|
|
16338
16565
|
} catch {
|
|
16339
16566
|
return void 0;
|
|
16340
16567
|
}
|