tickmarkr 2.6.2 → 2.6.4
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 +12 -2
- package/dist/adapters/codex.d.ts +2 -1
- package/dist/adapters/codex.js +26 -5
- package/dist/adapters/model-lints.d.ts +1 -0
- package/dist/adapters/model-lints.js +48 -1
- package/dist/adapters/model-windows.d.ts +2 -1
- package/dist/adapters/model-windows.js +18 -7
- package/dist/adapters/types.d.ts +6 -0
- package/dist/cli/commands/approve.d.ts +6 -3
- package/dist/cli/commands/approve.js +43 -6
- package/dist/cli/commands/doctor.d.ts +8 -2
- package/dist/cli/commands/doctor.js +6 -1
- package/dist/cli/commands/fleet.js +264 -59
- package/dist/cli/commands/init.js +5 -3
- package/dist/cli/commands/plan.js +13 -8
- package/dist/cli/commands/report.d.ts +40 -2
- package/dist/cli/commands/report.js +278 -11
- package/dist/cli/commands/resume.js +2 -4
- package/dist/cli/commands/run.d.ts +11 -0
- package/dist/cli/commands/run.js +33 -5
- package/dist/cli/commands/status.js +49 -4
- package/dist/cli/commands/verify.js +332 -121
- package/dist/compile/native.js +137 -0
- package/dist/config/config.d.ts +40 -9
- package/dist/config/config.js +133 -15
- package/dist/config/fleet-overlay.d.ts +13 -3
- package/dist/config/fleet-overlay.js +12 -8
- package/dist/drivers/herdr.d.ts +12 -0
- package/dist/drivers/herdr.js +51 -0
- package/dist/drivers/orca.d.ts +9 -1
- package/dist/drivers/orca.js +29 -7
- package/dist/drivers/types.d.ts +2 -0
- package/dist/drivers/types.js +2 -2
- package/dist/gates/acceptance.d.ts +7 -0
- package/dist/gates/acceptance.js +27 -5
- package/dist/gates/baseline.d.ts +20 -1
- package/dist/gates/baseline.js +100 -20
- package/dist/gates/cache.d.ts +8 -0
- package/dist/gates/cache.js +12 -2
- package/dist/gates/llm.d.ts +6 -0
- package/dist/gates/llm.js +27 -8
- package/dist/gates/review.d.ts +6 -1
- package/dist/gates/review.js +122 -32
- package/dist/gates/run-gates.d.ts +54 -3
- package/dist/gates/run-gates.js +331 -45
- package/dist/gates/test-manifest.d.ts +42 -0
- package/dist/gates/test-manifest.js +69 -10
- package/dist/route/router.d.ts +23 -1
- package/dist/route/router.js +54 -16
- package/dist/run/consult.d.ts +3 -1
- package/dist/run/consult.js +4 -2
- package/dist/run/daemon.d.ts +2 -1
- package/dist/run/daemon.js +349 -79
- package/dist/run/interactive-seed.d.ts +4 -0
- package/dist/run/interactive-seed.js +35 -9
- package/dist/run/journal.d.ts +123 -1
- package/dist/run/journal.js +480 -17
- package/dist/run/lease.d.ts +13 -0
- package/dist/run/lease.js +45 -0
- package/dist/run/protocol.d.ts +15 -0
- package/dist/run/protocol.js +11 -1
- package/dist/run/receipt-resolver.d.ts +22 -0
- package/dist/run/receipt-resolver.js +40 -1
- package/dist/run/repair-selection.d.ts +11 -1
- package/dist/run/repair-selection.js +17 -9
- package/dist/run/wall-budget.d.ts +48 -0
- package/dist/run/wall-budget.js +280 -0
- package/dist/tui/cockpit/live-store.d.ts +6 -0
- package/dist/tui/cockpit/live-store.js +36 -11
- package/dist/tui/cockpit/run-cockpit.js +2 -2
- package/dist/tui/cockpit/run-view.d.ts +2 -1
- package/dist/tui/cockpit/run-view.js +13 -9
- package/dist/tui/cockpit/setup-cockpit.d.ts +2 -0
- package/dist/tui/cockpit/setup-cockpit.js +4 -0
- package/package.json +2 -1
- package/schema/config.schema.json +8 -1
- package/skills/tickmarkr-auto/SKILL.md +2 -2
- package/skills/tickmarkr-loop/SKILL.md +17 -5
- package/skills/tickmarkr-overseer/scripts/classify-vitest-log.sh +4 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Assignment, type WorkerAdapter } from "../adapters/types.js";
|
|
2
|
+
import { DeliveryReadinessError } from "../drivers/herdr.js";
|
|
2
3
|
import type { ExecutorDriver, Slot } from "../drivers/types.js";
|
|
3
4
|
export interface InteractiveSeedResult {
|
|
4
5
|
output: string;
|
|
@@ -8,6 +9,9 @@ export interface InteractiveSeedResult {
|
|
|
8
9
|
trustAnswered: boolean;
|
|
9
10
|
}
|
|
10
11
|
type SeedDriver = Pick<ExecutorDriver, "run" | "waitOutput" | "read" | "sendKey">;
|
|
12
|
+
export declare class SeedReadinessError extends DeliveryReadinessError {
|
|
13
|
+
constructor(waitedMs: number, transcript: string, readinessMatch: string);
|
|
14
|
+
}
|
|
11
15
|
export declare function runInteractiveSeed(opts: {
|
|
12
16
|
driver: SeedDriver;
|
|
13
17
|
slot: Slot;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchesTrustDialog } from "../adapters/types.js";
|
|
2
|
+
import { DeliveryReadinessError } from "../drivers/herdr.js";
|
|
2
3
|
// The workspace-trust prompt is a STARTUP gate: it renders before the readiness banner and blocks
|
|
3
4
|
// it, so this wait is the only window in which anything can answer it. Observation therefore runs
|
|
4
5
|
// for the WHOLE readiness budget. Review round 7 (material): a 60-second cutoff here was a window
|
|
@@ -9,6 +10,18 @@ import { matchesTrustDialog } from "../adapters/types.js";
|
|
|
9
10
|
// blocked anyway, and it ends at the first of readiness, a modal, or the deadline.
|
|
10
11
|
const TRUST_POLL_MS = 1_000;
|
|
11
12
|
const TRUST_PANE_ROWS = 80;
|
|
13
|
+
// OBS-1205 add.1: a launch whose readiness never appeared never received the brief, so its deadline is
|
|
14
|
+
// the delivery-readiness class (OBS-142: the interface never became interactive), not a launched
|
|
15
|
+
// worker. Thrown as that class, the daemon's existing catch journals `delivery-readiness-failed`,
|
|
16
|
+
// closes the slot and walks the escalation ladder to a failover — with no `worker-launch` row, which is
|
|
17
|
+
// where a funded repair's findings expire, so the repair the seed never delivered stays owed.
|
|
18
|
+
export class SeedReadinessError extends DeliveryReadinessError {
|
|
19
|
+
constructor(waitedMs, transcript, readinessMatch) {
|
|
20
|
+
super(waitedMs, transcript);
|
|
21
|
+
this.name = "SeedReadinessError";
|
|
22
|
+
this.message = `seed readiness pattern not seen after ${waitedMs}ms: ${readinessMatch}`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
12
25
|
// v1.89 T19 / OBS-406: wait for readiness, answering a fingerprint-matched trust modal at most ONCE
|
|
13
26
|
// on the way. The daemon's own trust loop runs only after runInteractiveSeed returns, and this wait
|
|
14
27
|
// is exactly the window the modal blocks in — a declaration consulted only there is unreachable
|
|
@@ -17,23 +30,34 @@ async function awaitReadiness(opts) {
|
|
|
17
30
|
const { driver, slot, readinessMatch, deadline } = opts;
|
|
18
31
|
const dialog = opts.adapter.trustDialog;
|
|
19
32
|
const left = () => Math.max(0, deadline - Date.now());
|
|
33
|
+
// Every wait below is awaited, and the budget can run out inside any of them (OrcaDriver.waitOutput
|
|
34
|
+
// checks its sweep before its clock). Readiness a wait returns after the deadline is expired — it may
|
|
35
|
+
// be what a key pressed at the edge produced — and a launch whose deadline passed has already
|
|
36
|
+
// failed, so neither a key nor a seed follows it. Both branches apply it.
|
|
37
|
+
const expired = () => Date.now() >= deadline;
|
|
38
|
+
const readyInTime = async (ms) => (await driver.waitOutput(slot, readinessMatch, ms)) && !expired();
|
|
20
39
|
// Nothing this launch could answer (no declaration, an honest {kind:"none"}, or a driver with no
|
|
21
|
-
// keystroke surface): the single long wait,
|
|
40
|
+
// keystroke surface): the single long wait, pre-T19 behaviour plus the post-await deadline check.
|
|
22
41
|
if (!dialog || dialog.kind === "none" || !driver.sendKey) {
|
|
23
|
-
return { ready: await
|
|
42
|
+
return { ready: await readyInTime(left()), trustAnswered: false };
|
|
24
43
|
}
|
|
25
44
|
let trustAnswered = false;
|
|
26
|
-
while (!trustAnswered &&
|
|
27
|
-
if (await
|
|
45
|
+
while (!trustAnswered && !expired()) {
|
|
46
|
+
if (await readyInTime(Math.min(TRUST_POLL_MS, left()))) {
|
|
28
47
|
return { ready: true, trustAnswered };
|
|
29
48
|
}
|
|
30
49
|
let paneText;
|
|
31
50
|
try {
|
|
32
|
-
|
|
51
|
+
// OBS-1205: a cursor-drawn modal has text only on the RENDERED frame, so the slot's screen read
|
|
52
|
+
// is preferred when its driver has one. An unreadable or foreign frame is a failed read, never
|
|
53
|
+
// a cue to match the stream instead; drivers without a screen keep polling `read`.
|
|
54
|
+
paneText = await (slot.readScreen ? slot.readScreen() : driver.read(slot, TRUST_PANE_ROWS));
|
|
33
55
|
}
|
|
34
56
|
catch {
|
|
35
57
|
continue; // a failed read is not a matched modal — keep observing, spend nothing
|
|
36
58
|
}
|
|
59
|
+
if (expired())
|
|
60
|
+
break; // the wait or the read outlived the budget: no key after the deadline
|
|
37
61
|
if (!matchesTrustDialog(paneText, dialog))
|
|
38
62
|
continue;
|
|
39
63
|
// Review round 7 (material): the latch is spent BEFORE the awaited send, not after it. A send
|
|
@@ -54,7 +78,8 @@ async function awaitReadiness(opts) {
|
|
|
54
78
|
/* dispatched-then-rejected: never retried here, and never re-tried by the daemon either */
|
|
55
79
|
}
|
|
56
80
|
}
|
|
57
|
-
|
|
81
|
+
// An expired budget gets no closing sweep: a zero-length wait still reads the terminal once.
|
|
82
|
+
return { ready: !expired() && await readyInTime(left()), trustAnswered };
|
|
58
83
|
}
|
|
59
84
|
// v1.69 T6: launch-then-seed handoff for adapters whose real TUI cannot be argv-seeded.
|
|
60
85
|
// Both the launch command and the seed line are delivered through the driver's existing `run`
|
|
@@ -65,6 +90,8 @@ export async function runInteractiveSeed(opts) {
|
|
|
65
90
|
await opts.driver.run(opts.slot, seed.launch(opts.assignment.model));
|
|
66
91
|
// `trustAnswered` rides EVERY return below, including both early ones: the daemon initializes its
|
|
67
92
|
// per-slot latch from it, and an omission there reads as "no key was sent" — the second-Enter defect.
|
|
93
|
+
// The readiness deadline throws instead; `onTrustAnswered` already carried the latch out.
|
|
94
|
+
const launchedAt = Date.now();
|
|
68
95
|
const { ready, trustAnswered } = await awaitReadiness({
|
|
69
96
|
driver: opts.driver,
|
|
70
97
|
slot: opts.slot,
|
|
@@ -74,9 +101,8 @@ export async function runInteractiveSeed(opts) {
|
|
|
74
101
|
...(opts.onTrustAnswered ? { onTrustAnswered: opts.onTrustAnswered } : {}),
|
|
75
102
|
});
|
|
76
103
|
const banner = await opts.driver.read(opts.slot, 1000);
|
|
77
|
-
if (!ready)
|
|
78
|
-
|
|
79
|
-
}
|
|
104
|
+
if (!ready)
|
|
105
|
+
throw new SeedReadinessError(Date.now() - launchedAt, banner, seed.readinessMatch);
|
|
80
106
|
let sessionId;
|
|
81
107
|
if (seed.confirmBanner) {
|
|
82
108
|
const confirm = seed.confirmBanner(banner, opts.assignment.model);
|
package/dist/run/journal.d.ts
CHANGED
|
@@ -107,6 +107,8 @@ export interface StructuredFinding {
|
|
|
107
107
|
observedFingerprints?: string[];
|
|
108
108
|
/** Prior id validated against the reviewer's reraised list by the review gate. */
|
|
109
109
|
reraisedFrom?: string;
|
|
110
|
+
/** OBS-1195: an anchor's explicitly named parent chain; it retires when that chain is resolved. */
|
|
111
|
+
boundTo?: string;
|
|
110
112
|
/** Resolved definition AND defect identity; bare symbol spelling is never lineage. */
|
|
111
113
|
codeIdentity?: {
|
|
112
114
|
definition: string;
|
|
@@ -185,7 +187,10 @@ export declare function formatPriorFindingEvidence(evidence: PriorFindingEvidenc
|
|
|
185
187
|
/** Normalized identity of a gate failure: the same defect, seen twice, normalizes to the same bytes. */
|
|
186
188
|
export declare function normalizeGateFailure(details: string): string;
|
|
187
189
|
export declare const GATE_FINGERPRINT_CAP = 2;
|
|
190
|
+
/** The invocation a gate row's receipt names — the identity of the execution that observed it. */
|
|
191
|
+
export declare const receiptOrigin: (data: Record<string, unknown>) => string | undefined;
|
|
188
192
|
export declare function identicalGateFailures(events: JournalEvent[], taskId: string, gate: string, normalized: string): number;
|
|
193
|
+
export declare const readableExcerpt: (text: string) => string;
|
|
189
194
|
/** What each funded repair's next battery actually reached. A repair spends its budget only
|
|
190
195
|
* when that battery reaches one of the gates it was funded to fix; an earlier red is evidence that
|
|
191
196
|
* this repair never got its funded turn, not a charge against the repair ladder. */
|
|
@@ -309,7 +314,28 @@ export declare function carryReviewFindings(priors: readonly StructuredFinding[]
|
|
|
309
314
|
* after round re-seats ONE fingerprint, and a revised rationale replaces the prior rationale on that
|
|
310
315
|
* row. N rounds of the same concern therefore carry the newest accepted explanation once, not N rows.
|
|
311
316
|
*/
|
|
317
|
+
/** OBS-1151: this task's journaled judgments, newest first — subjects to compare a fresh ruling against,
|
|
318
|
+
* never verdicts to reuse. A row without a well-formed judgment (legacy, park, unparseable) is skipped. */
|
|
319
|
+
export declare function priorJudgments(events: readonly JournalEvent[], taskId: string): Array<{
|
|
320
|
+
commit: string;
|
|
321
|
+
judge?: string;
|
|
322
|
+
criteria: Array<{
|
|
323
|
+
id: string;
|
|
324
|
+
key: string;
|
|
325
|
+
met: boolean;
|
|
326
|
+
paths: string[];
|
|
327
|
+
}>;
|
|
328
|
+
}>;
|
|
312
329
|
export declare function outstandingReviewFindings(events: JournalEvent[], taskId: string): StructuredFinding[];
|
|
330
|
+
/**
|
|
331
|
+
* OBS-1019 add.2: each outstanding material chain with the number of valid review verdicts that
|
|
332
|
+
* re-raised it since the last review pass or review-gate waive. Only a chain's own observed spellings
|
|
333
|
+
* count, so an unrelated finding sharing a path never lengthens it.
|
|
334
|
+
*/
|
|
335
|
+
export declare function reraisedReviewChains(events: JournalEvent[], taskId: string): Array<{
|
|
336
|
+
finding: StructuredFinding;
|
|
337
|
+
reraises: number;
|
|
338
|
+
}>;
|
|
313
339
|
/** The findings a funded repair must carry into the next dispatch, or undefined if none is pending. */
|
|
314
340
|
export declare function pendingRepairFindings(events: JournalEvent[], taskId: string): string | undefined;
|
|
315
341
|
/**
|
|
@@ -409,8 +435,8 @@ export declare const TelemetryRowSchema: z.ZodObject<{
|
|
|
409
435
|
quotaFailover: z.ZodOptional<z.ZodLiteral<true>>;
|
|
410
436
|
overrun: z.ZodOptional<z.ZodLiteral<true>>;
|
|
411
437
|
retryMode: z.ZodOptional<z.ZodEnum<{
|
|
412
|
-
repair: "repair";
|
|
413
438
|
resume: "resume";
|
|
439
|
+
repair: "repair";
|
|
414
440
|
fresh: "fresh";
|
|
415
441
|
}>>;
|
|
416
442
|
signalQuality: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodLiteral<0.25>, z.ZodLiteral<0.5>, z.ZodLiteral<0.75>, z.ZodLiteral<1>]>>;
|
|
@@ -567,4 +593,100 @@ export declare class Journal {
|
|
|
567
593
|
readTelemetry(): TelemetryRow[];
|
|
568
594
|
readJudgeTelemetry(): TelemetryRow[];
|
|
569
595
|
}
|
|
596
|
+
export declare const OWED_CHECK_VERSION: 1;
|
|
597
|
+
export declare const OWED_DISCHARGE_EVENT: "owed-check-discharged";
|
|
598
|
+
export interface OwedCheck {
|
|
599
|
+
version: typeof OWED_CHECK_VERSION;
|
|
600
|
+
id: string;
|
|
601
|
+
runId: string;
|
|
602
|
+
taskId: string;
|
|
603
|
+
gate: GateName;
|
|
604
|
+
/** The immutable range the waived gate measured, and its canonical subject (daemon gateCommitSubject). */
|
|
605
|
+
base: string;
|
|
606
|
+
head: string;
|
|
607
|
+
subject: string;
|
|
608
|
+
/** Verbatim (whitespace-sensitive) patch identity of the whole range and of each commit, in order — the integration mapping key. */
|
|
609
|
+
patch: string;
|
|
610
|
+
patches: string[];
|
|
611
|
+
criteria: string;
|
|
612
|
+
/** The task's file scope at waive time: a discharge gates exactly this allowlist, never a wider one. */
|
|
613
|
+
files: string[];
|
|
614
|
+
authors: string[];
|
|
615
|
+
/** The channels this repository's adapters declared under its config at waive time (key → vendor):
|
|
616
|
+
* the only seats a review discharge's reviewer and author channels may resolve to. */
|
|
617
|
+
declared: ChannelFact[];
|
|
618
|
+
cause: string;
|
|
619
|
+
evidence: string;
|
|
620
|
+
disposition: "accepted-risk";
|
|
621
|
+
known: boolean;
|
|
622
|
+
unknownReason?: string;
|
|
623
|
+
}
|
|
624
|
+
export interface OwedFold {
|
|
625
|
+
known: boolean;
|
|
626
|
+
debt: number | "unknown";
|
|
627
|
+
outstanding: OwedCheck[];
|
|
628
|
+
acceptedRisk: OwedCheck[];
|
|
629
|
+
discharged: string[];
|
|
630
|
+
unknown: Array<{
|
|
631
|
+
taskId?: string;
|
|
632
|
+
gate?: string;
|
|
633
|
+
reason: string;
|
|
634
|
+
}>;
|
|
635
|
+
}
|
|
636
|
+
export declare const owedCriteria: (acceptance: unknown) => string;
|
|
637
|
+
/** The daemon's canonical gate subject for base..head (daemon.ts gateCommitSubject), byte for byte. */
|
|
638
|
+
export declare const owedSubject: (cwd: string, base: string, head: string) => string;
|
|
639
|
+
/** Ordered verbatim patch ids of the commits in base..head; an empty commit authored no patch. */
|
|
640
|
+
export declare const rangePatches: (cwd: string, base: string, head: string) => string[];
|
|
641
|
+
/** Verbatim patch identity of the whole change base..head introduces. */
|
|
642
|
+
export declare const rangePatch: (cwd: string, base: string, head: string) => string;
|
|
643
|
+
/**
|
|
644
|
+
* `head` is the task's own recorded integration merge of the obligation's range — exactly. Its first
|
|
645
|
+
* parent is `mergeBase`; its second parent replays the waived history source tree for source tree from
|
|
646
|
+
* a base with the waived base's tree (a carry may mint new commit objects, never new content — and
|
|
647
|
+
* patch ids alone ignore where a hunk lands); its tree is git's own clean merge of the two (no
|
|
648
|
+
* resolution, no amend); and it introduced the same ordered verbatim patch series and total patch.
|
|
649
|
+
* Squashed, reordered, relocated, re-indented, reverted or conflict-resolved history fails one of
|
|
650
|
+
* these and is refused as ambiguous; containment never counts.
|
|
651
|
+
* Both verify (before discharging) and the fold (re-reading every discharge) decide through here.
|
|
652
|
+
*/
|
|
653
|
+
export declare function integrationMapped(cwd: string, events: readonly JournalEvent[], o: OwedCheck, mergeBase: unknown, head: unknown): boolean;
|
|
654
|
+
/**
|
|
655
|
+
* Lifetime patch authors of base..head, read from the run: the daemon's subjectAuthors fold
|
|
656
|
+
* (daemon.ts, not exported and not this task's to edit) restated synchronously so the waive row is
|
|
657
|
+
* written without yielding. Recreation rows name SOURCE hashes, so ownership joins by stable patch
|
|
658
|
+
* identity across changed commit objects; a gate-only restore (resume-restore's seat, a recreation
|
|
659
|
+
* after work started) never becomes an author. Unreadable history names an unknown author.
|
|
660
|
+
*/
|
|
661
|
+
export declare function owedAuthors(events: readonly JournalEvent[], taskId: string, cwd: string, base: string, head: string): string[];
|
|
662
|
+
/**
|
|
663
|
+
* The obligation a waive of `gate` leaves on the task branch's current range. Synchronous on purpose:
|
|
664
|
+
* approve writes it into the waive row under the approval serialization without yielding, so a live
|
|
665
|
+
* daemon's boundary sees the same single append it always did. Anything not bound exactly — the
|
|
666
|
+
* waived row measured another subject, unreadable refs, unresolved authors, unreadable criteria — is
|
|
667
|
+
* recorded, never guessed, as known: false.
|
|
668
|
+
*/
|
|
669
|
+
export declare function captureOwedCheck(input: {
|
|
670
|
+
cwd: string;
|
|
671
|
+
runId: string;
|
|
672
|
+
taskId: string;
|
|
673
|
+
gate: GateName;
|
|
674
|
+
cause: string;
|
|
675
|
+
acceptance: unknown;
|
|
676
|
+
files: unknown;
|
|
677
|
+
declared: readonly ChannelFact[] | undefined;
|
|
678
|
+
taskRef: string;
|
|
679
|
+
integrationRef: string;
|
|
680
|
+
events: readonly JournalEvent[];
|
|
681
|
+
}): OwedCheck;
|
|
682
|
+
export type ChannelFact = {
|
|
683
|
+
key: string;
|
|
684
|
+
vendor: string;
|
|
685
|
+
};
|
|
686
|
+
/**
|
|
687
|
+
* The CURRENT owed-check fold: accepted-risk history, outstanding debt, and whether it is known.
|
|
688
|
+
* `cwd` is any checkout of the run's repository (integration discharges are re-proved from git).
|
|
689
|
+
* It never throws: a fold that cannot be computed is unknown debt, not a crash and never zero.
|
|
690
|
+
*/
|
|
691
|
+
export declare function foldOwedChecks(events: readonly JournalEvent[], cwd: string): OwedFold;
|
|
570
692
|
export {};
|