tickmarkr 2.6.5 → 2.6.7
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/README.md +7 -3
- package/dist/adapters/claude-code.js +8 -2
- package/dist/adapters/codex-commit-check.d.ts +16 -4
- package/dist/adapters/codex-commit-check.js +150 -26
- package/dist/adapters/codex.d.ts +1 -0
- package/dist/adapters/codex.js +20 -8
- package/dist/adapters/types.d.ts +4 -1
- package/dist/cli/commands/beat.d.ts +6 -1
- package/dist/cli/commands/beat.js +123 -76
- package/dist/cli/commands/doctor.js +3 -1
- package/dist/cli/commands/fleet.js +368 -85
- package/dist/cli/commands/init.js +23 -9
- package/dist/cli/commands/plan.js +12 -1
- package/dist/cli/commands/verify.js +37 -9
- package/dist/cli/help.d.ts +1 -0
- package/dist/cli/help.js +10 -5
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/config/fleet-overlay.d.ts +14 -0
- package/dist/config/fleet-overlay.js +154 -25
- package/dist/drivers/orca.d.ts +17 -3
- package/dist/drivers/orca.js +64 -20
- package/dist/gates/baseline.d.ts +9 -0
- package/dist/gates/baseline.js +14 -3
- package/dist/gates/cache.js +1 -1
- package/dist/gates/review.js +15 -0
- package/dist/gates/run-gates.d.ts +20 -7
- package/dist/gates/run-gates.js +345 -210
- package/dist/gates/test-manifest.d.ts +11 -0
- package/dist/gates/test-manifest.js +151 -111
- package/dist/gates/timeout-shaped.d.ts +3 -0
- package/dist/gates/timeout-shaped.js +10 -0
- package/dist/run/beat-lifecycle.d.ts +154 -0
- package/dist/run/beat-lifecycle.js +825 -0
- package/dist/run/daemon.js +202 -126
- package/dist/run/git-trust.d.ts +27 -0
- package/dist/run/git-trust.js +178 -0
- package/dist/run/git.js +34 -14
- package/dist/run/journal.js +15 -3
- package/dist/run/lease.d.ts +23 -0
- package/dist/run/lease.js +232 -38
- package/dist/run/merge.js +2 -2
- package/dist/run/stall.js +20 -1
- package/dist/run/supervision.d.ts +8 -0
- package/dist/run/supervision.js +24 -4
- package/dist/run/verification-job.d.ts +51 -0
- package/dist/run/verification-job.js +137 -0
- package/dist/tui/ink/fleet-app.d.ts +35 -5
- package/dist/tui/ink/fleet-app.js +244 -124
- package/package.json +1 -1
- package/skills/tickmarkr-auto/SKILL.md +19 -10
- package/skills/tickmarkr-loop/SKILL.md +19 -10
- package/skills/tickmarkr-overseer/SKILL.md +25 -16
- package/skills/tickmarkr-overseer/scripts/classify-vitest-log.sh +58 -16
- package/skills/tickmarkr-overseer/scripts/grade-ci.sh +19 -6
- package/skills/tickmarkr-overseer/scripts/watch-parks.sh +121 -64
package/dist/drivers/orca.js
CHANGED
|
@@ -44,7 +44,7 @@ export const ORCA_RESPONSE_FAMILIES = [
|
|
|
44
44
|
"status", "create", "list", "read", "send", "wait", "show", "close",
|
|
45
45
|
"worktree-current", "worktree-set", "hooks-status", "split",
|
|
46
46
|
];
|
|
47
|
-
export const ORCA_FIXTURE_VERSION = "1.4.
|
|
47
|
+
export const ORCA_FIXTURE_VERSION = "1.4.218";
|
|
48
48
|
export const ORCA_CLI_COMMAND_ENV = "ORCA_CLI_COMMAND";
|
|
49
49
|
export const STALE_HANDLE_CODE = "terminal_handle_stale";
|
|
50
50
|
export const TERMINAL_GONE_CODE = "terminal_gone";
|
|
@@ -608,6 +608,31 @@ export function isBlindStreamPage(term) {
|
|
|
608
608
|
&& Array.isArray(term.tail) && term.tail.length === 0
|
|
609
609
|
&& (term.returnedLineCount === undefined || term.returnedLineCount === 0);
|
|
610
610
|
}
|
|
611
|
+
/**
|
|
612
|
+
* F (D-832): what one proof page's OWN metadata says about the scrollback it was read from — the closed
|
|
613
|
+
* seam checkoutProven decides paging and absence by. `complete`: explicit `limited:false` and
|
|
614
|
+
* `truncated:false` with cursors that agree — nothing lies past this page. `partial`: explicit booleans,
|
|
615
|
+
* one of them true, cursors that agree — more scrollback exists. `unread`: everything else — a flag
|
|
616
|
+
* missing or not a boolean, a cursor that is not a string, `limited:false` with a next cursor short of
|
|
617
|
+
* the latest one (the contradictory "last" page), a blind stream page
|
|
618
|
+
* (isBlindStreamPage), or a source that is not the stream (`screen-unavailable`). Missing metadata is
|
|
619
|
+
* never inferred complete: its page's bytes still count as read evidence, but no absence rests on it.
|
|
620
|
+
*/
|
|
621
|
+
export function classifyProofPage(term) {
|
|
622
|
+
const { limited, truncated } = term;
|
|
623
|
+
if (typeof limited !== "boolean" || typeof truncated !== "boolean")
|
|
624
|
+
return "unread";
|
|
625
|
+
if (isBlindStreamPage(term) || (term.source !== undefined && term.source !== "stream"))
|
|
626
|
+
return "unread";
|
|
627
|
+
const next = str(term.nextCursor), latest = str(term.latestCursor);
|
|
628
|
+
if ((term.nextCursor !== undefined && next === undefined) || (term.latestCursor !== undefined && latest === undefined))
|
|
629
|
+
return "unread";
|
|
630
|
+
// a page that says it is the last while its next cursor stops short of the latest one contradicts itself.
|
|
631
|
+
// (A limited page whose next cursor IS the latest is not: the read from that cursor settles it.)
|
|
632
|
+
if (!limited && next !== undefined && latest !== undefined && next !== latest)
|
|
633
|
+
return "unread";
|
|
634
|
+
return limited || truncated ? "partial" : "complete";
|
|
635
|
+
}
|
|
611
636
|
export class OrcaDriver {
|
|
612
637
|
id = "orca";
|
|
613
638
|
interactive = true; // a visible terminal the operator can watch and answer
|
|
@@ -1021,12 +1046,17 @@ export class OrcaDriver {
|
|
|
1021
1046
|
* and none carries a trace of the mark; `unread` — every other exit: PROOF_PAGES reached, a limited
|
|
1022
1047
|
* read with no (or the same) next cursor or a truncated anchor without one, a read that threw, a read
|
|
1023
1048
|
* the ceiling cut off or never let start (the anchor included), or a page that landed late (even one
|
|
1024
|
-
* carrying the right proof), a malformed page (its tail
|
|
1025
|
-
*
|
|
1049
|
+
* carrying the right proof), a malformed page (its tail or cursors), a blind stream page
|
|
1050
|
+
* (isBlindStreamPage), or — F (D-832) — any page read whose paging metadata classifyProofPage cannot
|
|
1051
|
+
* call complete or partial (flags missing, not boolean or contradicted; even when they were omitted,
|
|
1052
|
+
* that page's bytes stay evidence and its matching proof still proves). Unread output is unknown —
|
|
1053
|
+
* never an empty page, never absence.
|
|
1026
1054
|
* Without a deadline (reconcile, recovery) only `proven` is consumed.
|
|
1027
1055
|
*/
|
|
1028
1056
|
async checkoutProven(handle, checkout, from, runtimeId, deadline) {
|
|
1029
|
-
|
|
1057
|
+
// F (D-832): a page read whose own metadata does not say how complete it is (classifyProofPage):
|
|
1058
|
+
// its bytes are evidence, but the scrollback it came from is not known to be read whole.
|
|
1059
|
+
let late = false, unknown = false;
|
|
1030
1060
|
const page = async (cursor) => {
|
|
1031
1061
|
const budget = deadline === undefined ? undefined : deadline - this.time.now();
|
|
1032
1062
|
if (budget !== undefined && budget <= 0)
|
|
@@ -1052,23 +1082,24 @@ export class OrcaDriver {
|
|
|
1052
1082
|
throw new OrcaError("read", `proof page names terminal ${str(term.handle) ?? "none"}, not the candidate ${handle}`, env.raw);
|
|
1053
1083
|
}
|
|
1054
1084
|
// E1: only a well-formed page is read text. A tail that is missing, not an array or carries a
|
|
1055
|
-
// non-string row (tailText), a cursor that is not a non-empty string
|
|
1056
|
-
//
|
|
1057
|
-
// page that would read as an absent proof.
|
|
1085
|
+
// non-string row (tailText), or a cursor that is not a non-empty string is a malformed page: it
|
|
1086
|
+
// throws, so it is unread output — never filtered to an empty page that would read as an absent proof.
|
|
1058
1087
|
for (const key of ["oldestCursor", "nextCursor"]) {
|
|
1059
1088
|
if (term[key] !== undefined && str(term[key]) === undefined)
|
|
1060
1089
|
throw new OrcaError("read", `proof page ${key} is not a cursor`, env.raw);
|
|
1061
1090
|
}
|
|
1062
|
-
for (const key of ["limited", "truncated"]) {
|
|
1063
|
-
if (term[key] !== undefined && typeof term[key] !== "boolean")
|
|
1064
|
-
throw new OrcaError("read", `proof page ${key} is not a boolean`, env.raw);
|
|
1065
|
-
}
|
|
1066
1091
|
// E1: the OBS-1011 add.1 blind stream (exited, empty tail, zero lines returned) is the shape a
|
|
1067
1092
|
// live terminal's stream answers while its screen still paints — and a dead terminal's too. The
|
|
1068
1093
|
// stream alone cannot tell them apart, so its empty tail is unread scrollback, never absence.
|
|
1069
1094
|
if (isBlindStreamPage(term))
|
|
1070
1095
|
throw new OrcaError("read", "proof page is a blind stream page (status exited, empty tail): its scrollback is unread", env.raw);
|
|
1071
|
-
|
|
1096
|
+
const text = this.tailText("read", term, env.raw);
|
|
1097
|
+
// F: paging flags missing, not boolean or contradicted by the cursors leave the page's bytes read
|
|
1098
|
+
// but its completeness unknown — it ends paging, and the poll can never read as absent.
|
|
1099
|
+
const kind = classifyProofPage(term);
|
|
1100
|
+
if (kind === "unread")
|
|
1101
|
+
unknown = true;
|
|
1102
|
+
return { term, text, kind };
|
|
1072
1103
|
};
|
|
1073
1104
|
// Every validated read is evidence, whatever stops the next one: the anchor's tail and the pages
|
|
1074
1105
|
// read from the oldest cursor are inspected even when paging hits PROOF_PAGES or a read throws.
|
|
@@ -1093,12 +1124,13 @@ export class OrcaDriver {
|
|
|
1093
1124
|
tail = first.text;
|
|
1094
1125
|
let cursor = str(anchor.oldestCursor);
|
|
1095
1126
|
// why paging ended with scrollback still unread. Every exit is one of: complete (an anchor that
|
|
1096
|
-
// is the whole scrollback, or a page
|
|
1127
|
+
// is the whole scrollback, or a page whose metadata says it is the last), whole frames found, a
|
|
1128
|
+
// page whose completeness is unknown (`unknown`, classifyProofPage), or one of these.
|
|
1097
1129
|
let stop;
|
|
1098
1130
|
if (cursor === undefined) {
|
|
1099
1131
|
text = tail;
|
|
1100
1132
|
// A cursorless anchor that says it holds less than the scrollback leaves the rest unreadable.
|
|
1101
|
-
if (
|
|
1133
|
+
if (first.kind === "partial")
|
|
1102
1134
|
stop = "stalled";
|
|
1103
1135
|
}
|
|
1104
1136
|
for (let n = 0; cursor !== undefined; n++) {
|
|
@@ -1116,12 +1148,23 @@ export class OrcaDriver {
|
|
|
1116
1148
|
const frames = checkoutFrames(text);
|
|
1117
1149
|
if (frames.complete.length > 0 && !frames.incomplete)
|
|
1118
1150
|
break; // whole frames, nothing dangling
|
|
1119
|
-
if (
|
|
1151
|
+
if (got.kind === "complete")
|
|
1120
1152
|
break; // the last page: the scrollback was read to its end
|
|
1121
1153
|
const next = str(term.nextCursor);
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1154
|
+
const advancing = next !== undefined && next !== cursor;
|
|
1155
|
+
if (got.kind === "unread") {
|
|
1156
|
+
// F: no absence rests on this page (`unknown`), but a cursor that still advances toward more
|
|
1157
|
+
// scrollback — the page says limited, or its next cursor is short of the latest one — is
|
|
1158
|
+
// followed for positive proof, inside PROOF_PAGES and the ceiling.
|
|
1159
|
+
if (advancing && (term.limited === true || next !== str(term.latestCursor))) {
|
|
1160
|
+
cursor = next;
|
|
1161
|
+
continue;
|
|
1162
|
+
}
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
1165
|
+
// A partial page that is not limited, or a limited one with no next cursor or the same one, says
|
|
1166
|
+
// more scrollback exists that no read can reach: unread, never absent.
|
|
1167
|
+
if (term.limited !== true || !advancing) {
|
|
1125
1168
|
stop = "stalled";
|
|
1126
1169
|
break;
|
|
1127
1170
|
}
|
|
@@ -1139,9 +1182,10 @@ export class OrcaDriver {
|
|
|
1139
1182
|
return { proven: true, reason: "" };
|
|
1140
1183
|
const why = `${late ? "read past the ceiling, " : ""}${stop === "cut" ? "the ceiling cut off paging, "
|
|
1141
1184
|
: stop === "exhausted" ? `paging stopped at ${PROOF_PAGES} pages with scrollback unread, `
|
|
1142
|
-
: stop === "stalled" ? "a limited read gave no next cursor with scrollback unread, " : ""}`;
|
|
1185
|
+
: stop === "stalled" ? "a limited read gave no next cursor with scrollback unread, " : ""}${unknown ? "a page carried missing, non-boolean or contradictory paging metadata, " : ""}`;
|
|
1143
1186
|
const read = described(why);
|
|
1144
|
-
|
|
1187
|
+
// F: absent only when every page read said, explicitly and consistently, how complete it was.
|
|
1188
|
+
return { ...read, seen: read.seen ?? (stop || late || unknown ? "unread" : "absent") };
|
|
1145
1189
|
}
|
|
1146
1190
|
catch (error) {
|
|
1147
1191
|
// A read that failed midway keeps what was already read as evidence; what it could not read is
|
package/dist/gates/baseline.d.ts
CHANGED
|
@@ -125,6 +125,9 @@ export interface BaselineCommand {
|
|
|
125
125
|
/** VL-1: every per-file duration the runner named, so a later per-file hang budget (test-manifest.ts)
|
|
126
126
|
* can be derived per file rather than from one slowest-file number; null when unavailable. */
|
|
127
127
|
fileDurations?: BaselineFileDuration[] | null;
|
|
128
|
+
/** v2.6.7 close: set when fileTiming classified each duration's outcome (`failed` on a red file). A red capture
|
|
129
|
+
* without it (an older binary, a cached or hand-supplied baseline) never says which files were red. */
|
|
130
|
+
fileOutcomes?: true;
|
|
128
131
|
/** The ceiling that measurement implies, persisted so every later battery uses the same number. */
|
|
129
132
|
ceilingMs?: number;
|
|
130
133
|
/**
|
|
@@ -145,6 +148,8 @@ export interface BaselineCommand {
|
|
|
145
148
|
export interface BaselineFileDuration {
|
|
146
149
|
file: string;
|
|
147
150
|
durationMs: number;
|
|
151
|
+
/** The file was RED in this capture (× or ❯): its duration ended early and is no measure of its green runtime. */
|
|
152
|
+
failed?: true;
|
|
148
153
|
}
|
|
149
154
|
/**
|
|
150
155
|
* OBS-1123: WHICH capture a forgiveness rests on — the commit it measured and when it was published.
|
|
@@ -175,6 +180,10 @@ export type FailureClassification = "regression" | "infra";
|
|
|
175
180
|
* unreadable-runner case the existing fail-closed path already owns.
|
|
176
181
|
*/
|
|
177
182
|
export declare function classifyFailureOutput(output: string): FailureClassification | undefined;
|
|
183
|
+
/** The per-file timings a consumer may read as green runtimes. A red capture that never classified its files
|
|
184
|
+
* (no fileOutcomes) marks every file failed, so each is budgeted and costed as untimed — never as the early-ending
|
|
185
|
+
* time of a run that may have been red for it. */
|
|
186
|
+
export declare function classifiedFileDurations(entry: BaselineCommand | undefined): BaselineFileDuration[] | null | undefined;
|
|
178
187
|
export declare const UNRECOGNIZED_FAILURE = "<unrecognized failure output>";
|
|
179
188
|
export declare function fingerprint(output: string): string[];
|
|
180
189
|
/**
|
package/dist/gates/baseline.js
CHANGED
|
@@ -430,7 +430,7 @@ const normalizeLine = (l) => l.replace(/\d+/g, "#").replace(/\s+/g, " ").trim();
|
|
|
430
430
|
// turbo-prefixed, but a test-name timing has no parenthesized file tally and therefore cannot enter
|
|
431
431
|
// this measurement. These are observations of runner output, not a promise that every runner exposes
|
|
432
432
|
// them — callers record null, never zero, when no line matches.
|
|
433
|
-
const FILE_DURATION_RE = /^\s*(?:(?:[\w@./-]+:\s*)*)[✓✔×❯]\s+(?:\|[^|\r\n]+\|\s+)?(\S+)\s+\([^\r\n)]*\)\s+(\d+(?:\.\d+)?)\s*(ms|s|m)\b/;
|
|
433
|
+
const FILE_DURATION_RE = /^\s*(?:(?:[\w@./-]+:\s*)*)([✓✔×❯])\s+(?:\|[^|\r\n]+\|\s+)?(\S+)\s+\([^\r\n)]*\)\s+(\d+(?:\.\d+)?)\s*(ms|s|m)\b/;
|
|
434
434
|
const durationUnitMs = (unit) => unit === "m" ? 60_000 : unit === "s" ? 1_000 : 1;
|
|
435
435
|
function fileTiming(output, wallClockMs) {
|
|
436
436
|
const files = [];
|
|
@@ -438,9 +438,10 @@ function fileTiming(output, wallClockMs) {
|
|
|
438
438
|
const match = FILE_DURATION_RE.exec(line.replace(ANSI_RE, ""));
|
|
439
439
|
if (!match)
|
|
440
440
|
continue;
|
|
441
|
-
const durationMs = Number(match[
|
|
441
|
+
const durationMs = Number(match[3]) * durationUnitMs(match[4]);
|
|
442
|
+
// vitest marks a red file ❯ (suiteFail) and a red test × (taskFail)
|
|
442
443
|
if (Number.isFinite(durationMs))
|
|
443
|
-
files.push({ file: match[
|
|
444
|
+
files.push({ file: match[2], durationMs, ...(match[1] === "×" || match[1] === "❯" ? { failed: true } : {}) });
|
|
444
445
|
}
|
|
445
446
|
if (!files.length)
|
|
446
447
|
return { fileDurationSumMs: null, impliedParallelism: null, longestFile: null, fileDurations: null };
|
|
@@ -451,8 +452,18 @@ function fileTiming(output, wallClockMs) {
|
|
|
451
452
|
impliedParallelism: wallClockMs > 0 ? fileDurationSumMs / wallClockMs : null,
|
|
452
453
|
longestFile,
|
|
453
454
|
fileDurations: files,
|
|
455
|
+
fileOutcomes: true,
|
|
454
456
|
};
|
|
455
457
|
}
|
|
458
|
+
/** The per-file timings a consumer may read as green runtimes. A red capture that never classified its files
|
|
459
|
+
* (no fileOutcomes) marks every file failed, so each is budgeted and costed as untimed — never as the early-ending
|
|
460
|
+
* time of a run that may have been red for it. */
|
|
461
|
+
export function classifiedFileDurations(entry) {
|
|
462
|
+
const files = entry?.fileDurations;
|
|
463
|
+
if (!Array.isArray(files) || entry?.fileOutcomes || entry?.exitCode === 0)
|
|
464
|
+
return files;
|
|
465
|
+
return files.map((f) => ({ ...f, failed: true }));
|
|
466
|
+
}
|
|
456
467
|
// A failing command whose output holds no shape any runner here names. The marker is content-free and
|
|
457
468
|
// constant: downstream consumers (tip verify journals fingerprint counts) still see that the command
|
|
458
469
|
// failed, while no line of the output — narration, status strip, stack trace — can enter the set. Being
|
package/dist/gates/cache.js
CHANGED
|
@@ -53,7 +53,7 @@ export function baselineIdentity(baseline) {
|
|
|
53
53
|
return "none";
|
|
54
54
|
// Measurements control execution budgets, not which failures the baseline forgives.
|
|
55
55
|
const commands = Object.fromEntries(Object.entries(baseline.commands).map(([gate, entry]) => {
|
|
56
|
-
const { durationMs: _duration, fileDurationSumMs: _sum, impliedParallelism: _parallelism, longestFile: _longest, fileDurations: _files, ceilingMs: _ceiling, ...evidence } = entry;
|
|
56
|
+
const { durationMs: _duration, fileDurationSumMs: _sum, impliedParallelism: _parallelism, longestFile: _longest, fileDurations: _files, fileOutcomes: _outcomes, ceilingMs: _ceiling, ...evidence } = entry;
|
|
57
57
|
return [gate, evidence];
|
|
58
58
|
}));
|
|
59
59
|
return createHash("sha256").update(canonicalJson(commands)).digest("hex").slice(0, 16);
|
package/dist/gates/review.js
CHANGED
|
@@ -535,6 +535,13 @@ carriedAuthors = [], operatorContext) {
|
|
|
535
535
|
? `You may run at most the task's own test files explicitly named in files[]; these are the only suites you may run: ${ownTestFiles.map((file) => `\`${file}\``).join(", ")}.`
|
|
536
536
|
: "No suite may be run: files[] names no explicit test file owned by this task.";
|
|
537
537
|
const responseRequirement = reviewResponseRequirement(nonce);
|
|
538
|
+
// D-966 (T3 E): a reviewer that stopped at the first example of a class drip-fed it one round at a
|
|
539
|
+
// time — T5's rounds carried 2→1→1→1→2→1 findings and T10's 3→2→1→1→1, each round's repair fixing
|
|
540
|
+
// the case it was shown while its same-class siblings waited for the next review. The closed note
|
|
541
|
+
// tuple asks for every counterexample ACTUALLY FOUND in scope at once, plus the boundary searched and
|
|
542
|
+
// what stays uncertain, so the repair sees the class and the next round knows what was covered. It
|
|
543
|
+
// rides the existing note text (details → repair brief unchanged) and never asks for an exhaustive
|
|
544
|
+
// search the reviewer cannot honestly make; uncertainty alone stays out of the material bar.
|
|
538
545
|
const prompt = `TICKMARKR-REVIEW
|
|
539
546
|
${responseRequirement}
|
|
540
547
|
|
|
@@ -580,6 +587,14 @@ acceptance criterion it violates (or to the regression this diff introduces), st
|
|
|
580
587
|
and marks its evidence executed (you ran the reproducer), static (you traced it by reading) or blocked (it
|
|
581
588
|
could not run here). Blocked evidence never turns a finding into a pass, and a worker's own case table or
|
|
582
589
|
enumeration never resolves a finding: judge the diff itself.
|
|
590
|
+
Report the whole class in this one review, never only its first example. Each material finding's "note" is one
|
|
591
|
+
line carrying the closed tuple "rule: <the goal clause, criterion or regressed behaviour violated> | found:
|
|
592
|
+
<every counterexample you ACTUALLY FOUND inside the declared scope, each as path:line input → consequence,
|
|
593
|
+
joined by "; "> | searched: <the boundary you actually searched: files, symbols, call sites> | uncertain:
|
|
594
|
+
<what lies outside that boundary or could not be established inside it>". Found one counterexample, list one;
|
|
595
|
+
found several, list every one in the same finding. Never list a case you did not find. Your search is bounded:
|
|
596
|
+
never claim it covered every input, caller or path beyond the boundary you name, and remaining uncertainty
|
|
597
|
+
alone is never a material finding — record it under uncertain, or as a deferred minor with its rationale.
|
|
583
598
|
|
|
584
599
|
Respond with ONLY this JSON:
|
|
585
600
|
{"nonce": "${nonce}", "approve": true|false, "resolved": [], "reraised": [], "findings": [{"note": "...", "severity": "material"|"minor", "defer": false, "rationale": ""}], "comments": [{"path": "path/to/file", "line": 42, "body": "actionable feedback", "finding": 1}]}
|
|
@@ -98,18 +98,31 @@ export interface GateContext {
|
|
|
98
98
|
* a command that already has `--` takes them directly. Every path is quoted — config flows into a shell.
|
|
99
99
|
*/
|
|
100
100
|
export declare function testCommandForFiles(testCmd: string, files: string[]): string;
|
|
101
|
-
/**
|
|
102
|
-
export declare const
|
|
101
|
+
/** v2.6.7 T1 (closed order table): an attributed test-red diagnostic is admitted only when BOTH hold. */
|
|
102
|
+
export declare const DIAGNOSTIC_MAX_RATIO = 0.15;
|
|
103
|
+
export declare const DIAGNOSTIC_MAX_ESTIMATE_MS = 60000;
|
|
104
|
+
export interface DiagnosticAdmission {
|
|
105
|
+
admitted: boolean;
|
|
106
|
+
reason: "diagnostic-admitted" | "diagnostic-unknown-cost" | "diagnostic-capacity-mismatch" | "diagnostic-cost-ratio" | "diagnostic-cost-estimate";
|
|
107
|
+
costRatio?: number;
|
|
108
|
+
estimatedMs?: number;
|
|
109
|
+
}
|
|
103
110
|
/**
|
|
104
|
-
* The
|
|
105
|
-
*
|
|
106
|
-
*
|
|
111
|
+
* The diagnostic's admission evidence, from the per-file durations the harness measured at baseline
|
|
112
|
+
* capture — never a worker's timing. Unknown (any selected file unmeasured, any measurement that is not a
|
|
113
|
+
* finite number > 0 ms, an infra baseline, or no positive total) skips: an expensive or unknown screen must
|
|
114
|
+
* never become a full suite before semantics.
|
|
115
|
+
* So does timing recorded under a malformed or different capacity (git.ts sameCapacity): it divided the
|
|
116
|
+
* machine by another number, so it is not comparable evidence about this one.
|
|
117
|
+
* `estimatedMs` is the serial sum of those files: admission evidence, not a kill ceiling and not a
|
|
118
|
+
* claim about the parallel-plus-serial wall time the runner will actually take.
|
|
107
119
|
*/
|
|
108
|
-
export declare function
|
|
120
|
+
export declare function diagnosticAdmission(baseline: Baseline, selected: readonly string[]): DiagnosticAdmission;
|
|
109
121
|
/** A retry base no runner invocation parses. evaluateManifestedTest builds its stranded single-fork
|
|
110
122
|
* retry from the base it is handed, and one it cannot parse throws before any spawn — so this base
|
|
111
123
|
* disables that inner recovery: a worker-RPC-stranded re-observation comes back infra (the caller
|
|
112
|
-
* parks it as ambiguous) instead of launching a second execution.
|
|
124
|
+
* parks it as ambiguous) instead of launching a second execution. runVitestManifestGate reads it as
|
|
125
|
+
* the mark of a diagnostic subset, which never buys the outer timeout-shaped remeasurement either. */
|
|
113
126
|
export declare const REOBSERVATION_RETRY_BASE = "tickmarkr-reobservation-refuses-stranded-retry";
|
|
114
127
|
/** OBS-1106 residual: ONE isolated re-observation of a timeout-shaped red's attributed failing files on
|
|
115
128
|
* the same checkout, narrowed exactly as a screen is. Never cached and never a verdict: the caller
|