fix(yardstick): use counts new work from the loesningsvalg marker, from 2026-09-28 (green)
`<!-- loesningsvalg: plan|prove -->` on its own line = new work, `ikke-nytt` = not new; a mention in prose or an unknown value is no marker. The window starts at the later of --cutoff and MARKER_SINCE (2026-09-28). Orders before it and unmarked orders are reported as "not measured", never in the denominator. `work-class` decides nothing any more. The detail shows numerator, denominator and the not-measured count. Real queue 2026-10-03: 6 of 690 orders carry the marker (2 prove, 4 ikke-nytt, 0 plan), 684 not measured (all before 2026-09-28), identical to a grep census. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e2186bf64f
commit
5d272af937
1 changed files with 32 additions and 12 deletions
|
|
@ -3,9 +3,12 @@
|
||||||
// The yardstick - Voyage's three numbers, each with a denominator read from its SOURCE:
|
// The yardstick - Voyage's three numbers, each with a denominator read from its SOURCE:
|
||||||
//
|
//
|
||||||
// use new work that went through Voyage (the order queue: orders dated on or after
|
// use new work that went through Voyage (the order queue: orders dated on or after
|
||||||
// the cutoff that carry `work-class: new`;
|
// the later of the cutoff and MARKER_SINCE
|
||||||
// counted = those with a Voyage run whose
|
// whose `<!-- loesningsvalg: plan|prove -->`
|
||||||
// slug equals the order's `slug:`)
|
// marker says new work; counted = those with
|
||||||
|
// a Voyage run whose slug equals the order's
|
||||||
|
// `slug:`. Unmarked or earlier orders are
|
||||||
|
// not measured, never a no)
|
||||||
// trust reviews in a row with nothing that (trekreview-stats.jsonl, read as JSON and
|
// trust reviews in a row with nothing that (trekreview-stats.jsonl, read as JSON and
|
||||||
// stops a release ordered by `ts` - file order is not
|
// stops a release ordered by `ts` - file order is not
|
||||||
// chronological; value = the current ALLOW streak)
|
// chronological; value = the current ALLOW streak)
|
||||||
|
|
@ -41,6 +44,8 @@ import { evaluateCheck, loadRegistry, TEST_TIMEOUT_MS } from './end-state-gate.m
|
||||||
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
||||||
|
|
||||||
export const DEFAULT_CUTOFF = '2026-09-21';
|
export const DEFAULT_CUTOFF = '2026-09-21';
|
||||||
|
// The day pre-order-loesningsvalg.sh began refusing an order without the marker (PM 02.10).
|
||||||
|
export const MARKER_SINCE = '2026-09-28';
|
||||||
export const DEFAULT_COORD = join(homedir(), '.claude', 'coord');
|
export const DEFAULT_COORD = join(homedir(), '.claude', 'coord');
|
||||||
export const DEFAULT_DATA = process.env.CLAUDE_PLUGIN_DATA
|
export const DEFAULT_DATA = process.env.CLAUDE_PLUGIN_DATA
|
||||||
|| join(homedir(), '.claude', 'plugins', 'data', 'voyage-ktg-plugin-marketplace');
|
|| join(homedir(), '.claude', 'plugins', 'data', 'voyage-ktg-plugin-marketplace');
|
||||||
|
|
@ -162,6 +167,12 @@ function frontmatter(text) {
|
||||||
return fm;
|
return fm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The solution-choice marker dispatch writes on its own line in the order body. A mention
|
||||||
|
// inside prose (mid-line, in backticks) is not a marker.
|
||||||
|
const MARKER = /^<!--\s*loesningsvalg:\s*([^;\s>]+)/m;
|
||||||
|
const NEW_WORK = new Set(['plan', 'prove']);
|
||||||
|
const NOT_NEW = new Set(['ikke-nytt']);
|
||||||
|
|
||||||
/** Every order file under `<coord>/<repo>/orders/` - pending, `archive/` and `claimed/`. */
|
/** Every order file under `<coord>/<repo>/orders/` - pending, `archive/` and `claimed/`. */
|
||||||
export function readOrders(coordDir) {
|
export function readOrders(coordDir) {
|
||||||
const orders = [];
|
const orders = [];
|
||||||
|
|
@ -173,8 +184,9 @@ export function readOrders(coordDir) {
|
||||||
if (!existsSync(dir) || !statSync(dir).isDirectory()) continue;
|
if (!existsSync(dir) || !statSync(dir).isDirectory()) continue;
|
||||||
for (const path of walk(dir).filter((p) => p.endsWith('.md')).sort()) {
|
for (const path of walk(dir).filter((p) => p.endsWith('.md')).sort()) {
|
||||||
files++;
|
files++;
|
||||||
const fm = frontmatter(readFileSync(path, 'utf8'));
|
const text = readFileSync(path, 'utf8');
|
||||||
if (fm && fm['order-id']) orders.push({ path, repo, fm });
|
const fm = frontmatter(text);
|
||||||
|
if (fm && fm['order-id']) orders.push({ path, repo, fm, marker: text.match(MARKER)?.[1] });
|
||||||
else unreadable.push(path);
|
else unreadable.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -183,32 +195,40 @@ export function readOrders(coordDir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function measureUse({ queue, slugs, cutoff }) {
|
export function measureUse({ queue, slugs, cutoff }) {
|
||||||
|
const from = cutoff > MARKER_SINCE ? cutoff : MARKER_SINCE;
|
||||||
const base = {
|
const base = {
|
||||||
id: 'use', label: 'new work that went through Voyage',
|
id: 'use', label: 'new work that went through Voyage',
|
||||||
source: `${join(queue.dir, '*', 'orders')}/**/*.md (cutoff ${cutoff})`,
|
source: `${join(queue.dir, '*', 'orders')}/**/*.md (loesningsvalg marker, from ${from})`,
|
||||||
};
|
};
|
||||||
const withClass = queue.orders.filter((o) => o.fm['work-class'] !== undefined);
|
const withMarker = queue.orders.filter((o) => o.marker !== undefined);
|
||||||
const newWork = withClass.filter((o) => o.fm['work-class'] === 'new' && String(o.fm.date ?? '').slice(0, 10) >= cutoff);
|
const inWindow = queue.orders.filter((o) => String(o.fm.date ?? '').slice(0, 10) >= from);
|
||||||
|
const newWork = inWindow.filter((o) => NEW_WORK.has(o.marker));
|
||||||
|
const notNew = inWindow.filter((o) => NOT_NEW.has(o.marker));
|
||||||
|
const unmarked = inWindow.length - newWork.length - notNew.length;
|
||||||
|
const beforeMarker = queue.orders.length - inWindow.length;
|
||||||
const through = newWork.filter((o) => o.fm.slug && slugs.has(o.fm.slug));
|
const through = newWork.filter((o) => o.fm.slug && slugs.has(o.fm.slug));
|
||||||
const facts = {
|
const facts = {
|
||||||
scanned: queue.orders.length, files: queue.files, unreadable: queue.unreadable.length,
|
scanned: queue.orders.length, files: queue.files, unreadable: queue.unreadable.length,
|
||||||
withWorkClass: withClass.length, newSinceCutoff: newWork.length, withVoyageRun: through.length,
|
withMarker: withMarker.length, newWork: newWork.length, notNew: notNew.length,
|
||||||
|
unmarked, beforeMarker, notMeasured: unmarked + beforeMarker, withVoyageRun: through.length,
|
||||||
};
|
};
|
||||||
const perMailbox = {};
|
const perMailbox = {};
|
||||||
for (const o of queue.orders) perMailbox[o.repo] = (perMailbox[o.repo] ?? 0) + 1;
|
for (const o of queue.orders) perMailbox[o.repo] = (perMailbox[o.repo] ?? 0) + 1;
|
||||||
const dot = Object.entries(perMailbox).filter(([k]) => k.startsWith('.'));
|
const dot = Object.entries(perMailbox).filter(([k]) => k.startsWith('.'));
|
||||||
const census = `${queue.files} order files in ${Object.keys(perMailbox).length} mailboxes`
|
const census = `${queue.files} order files in ${Object.keys(perMailbox).length} mailboxes`
|
||||||
+ (dot.length ? ` (dot-mailboxes ${dot.map(([k, v]) => `${k} ${v}`).join(' · ')} - a shell \`*\` skips them)` : '')
|
+ (dot.length ? ` (dot-mailboxes ${dot.map(([k, v]) => `${k} ${v}`).join(' · ')} - a shell \`*\` skips them)` : '')
|
||||||
+ `; ${withClass.length} of ${queue.orders.length} orders carry work-class`
|
+ `; ${withMarker.length} of ${queue.orders.length} orders carry a loesningsvalg marker`
|
||||||
|
+ `; from ${from}: ${newWork.length} new (plan|prove) · ${notNew.length} not new (ikke-nytt)`
|
||||||
|
+ `; ${facts.notMeasured} not measured (${beforeMarker} before ${from} · ${unmarked} unmarked or unknown value)`
|
||||||
+ (queue.unreadable.length ? `; ${queue.unreadable.length} order file(s) without frontmatter` : '');
|
+ (queue.unreadable.length ? `; ${queue.unreadable.length} order file(s) without frontmatter` : '');
|
||||||
if (newWork.length === 0) {
|
if (newWork.length === 0) {
|
||||||
return { ...base, denominator: 0, facts, ...notCountable(
|
return { ...base, denominator: 0, facts, ...notCountable(
|
||||||
`${census}; 0 orders dated >= ${cutoff} with work-class: new - the denominator is empty`) };
|
`${census}; 0 new-work orders dated >= ${from} - the denominator is empty`) };
|
||||||
}
|
}
|
||||||
const unmatched = newWork.filter((o) => !o.fm.slug).length;
|
const unmatched = newWork.filter((o) => !o.fm.slug).length;
|
||||||
return {
|
return {
|
||||||
...base, countable: true, value: through.length, denominator: newWork.length, facts,
|
...base, countable: true, value: through.length, denominator: newWork.length, facts,
|
||||||
detail: `${census}; counted = a Voyage run in the stats with the order's slug`
|
detail: `${census}; ${through.length} of ${newWork.length} new-work orders have a Voyage run in the stats with the order's slug`
|
||||||
+ (unmatched ? `; ${unmatched} new-work order(s) carry no slug and cannot match` : ''),
|
+ (unmatched ? `; ${unmatched} new-work order(s) carry no slug and cannot match` : ''),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue