tickmarkr 2.6.3 → 2.6.5
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 +10 -2
- package/dist/adapters/catalog-remote.d.ts +23 -0
- package/dist/adapters/catalog-remote.js +38 -0
- package/dist/adapters/claude-code.d.ts +1 -1
- package/dist/adapters/claude-code.js +4 -1
- package/dist/adapters/codex-commit-check.d.ts +25 -0
- package/dist/adapters/codex-commit-check.js +108 -0
- package/dist/adapters/codex.d.ts +2 -1
- package/dist/adapters/codex.js +26 -5
- package/dist/adapters/model-discovery-check.d.ts +33 -0
- package/dist/adapters/model-discovery-check.js +123 -0
- package/dist/adapters/model-lints.d.ts +2 -1
- package/dist/adapters/model-lints.js +52 -1
- package/dist/adapters/model-windows.d.ts +2 -1
- package/dist/adapters/model-windows.js +18 -7
- package/dist/adapters/prompt.js +3 -2
- package/dist/adapters/types.d.ts +13 -0
- package/dist/cli/commands/approve.js +37 -6
- package/dist/cli/commands/doctor.d.ts +4 -0
- package/dist/cli/commands/doctor.js +20 -3
- package/dist/cli/commands/fleet.d.ts +10 -1
- package/dist/cli/commands/fleet.js +279 -95
- package/dist/cli/commands/init.js +10 -4
- package/dist/cli/commands/plan.js +65 -4
- package/dist/cli/commands/report.d.ts +39 -2
- package/dist/cli/commands/report.js +227 -10
- 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 +30 -3
- package/dist/cli/commands/verify.d.ts +1 -1
- package/dist/cli/commands/verify.js +356 -123
- package/dist/compile/native.js +130 -0
- package/dist/config/config.d.ts +25 -7
- package/dist/config/config.js +92 -11
- package/dist/config/fleet-overlay.d.ts +2 -1
- package/dist/config/fleet-overlay.js +77 -4
- package/dist/drivers/orca.d.ts +19 -1
- package/dist/drivers/orca.js +161 -31
- package/dist/gates/cache.d.ts +4 -0
- package/dist/gates/cache.js +10 -2
- package/dist/gates/llm.d.ts +4 -1
- package/dist/gates/llm.js +6 -1
- package/dist/gates/review.js +8 -3
- package/dist/gates/run-gates.d.ts +3 -2
- package/dist/gates/run-gates.js +91 -50
- package/dist/route/router.d.ts +11 -0
- package/dist/route/router.js +29 -8
- package/dist/run/daemon.js +158 -22
- package/dist/run/git.js +9 -0
- package/dist/run/journal.d.ts +101 -1
- package/dist/run/journal.js +352 -2
- package/dist/run/launchservices-check.d.ts +56 -0
- package/dist/run/launchservices-check.js +117 -0
- package/dist/run/operator-state.d.ts +22 -2
- package/dist/run/operator-state.js +20 -3
- package/dist/run/title-environment.d.ts +45 -0
- package/dist/run/title-environment.js +127 -0
- package/dist/run/title-preload.cjs +38 -0
- package/dist/run/title-preload.d.cts +1 -0
- package/dist/tui/cockpit/board.js +12 -6
- package/dist/tui/cockpit/keys.d.ts +8 -0
- package/dist/tui/cockpit/keys.js +4 -1
- package/dist/tui/cockpit/layout.d.ts +2 -2
- package/dist/tui/cockpit/layout.js +2 -2
- package/dist/tui/cockpit/live-runtime.js +46 -20
- package/dist/tui/cockpit/live-store.d.ts +30 -1
- package/dist/tui/cockpit/live-store.js +134 -18
- package/dist/tui/cockpit/log-view.d.ts +28 -0
- package/dist/tui/cockpit/log-view.js +60 -0
- package/dist/tui/cockpit/run-view.js +4 -0
- package/dist/tui/cockpit/shell.d.ts +2 -1
- package/dist/tui/cockpit/shell.js +6 -4
- package/dist/tui/ink/fleet-app.d.ts +12 -6
- package/dist/tui/ink/fleet-app.js +17 -11
- package/package.json +1 -1
- package/skills/tickmarkr-auto/SKILL.md +33 -3
- package/skills/tickmarkr-loop/SKILL.md +55 -5
- package/skills/tickmarkr-overseer/SKILL.md +83 -8
package/dist/cli/commands/run.js
CHANGED
|
@@ -6,10 +6,11 @@ import { loadGraph, onDiskSpecHash, readCompileRefusal } from "../../graph/graph
|
|
|
6
6
|
import { formatSummary, resolveRunMode, runDaemon } from "../../run/daemon.js";
|
|
7
7
|
import { isRunLockLive } from "../../run/lock.js";
|
|
8
8
|
import { route, NO_EXPLORE_ENV } from "../../route/router.js";
|
|
9
|
-
import { formatJournalNarration, loadRoutingProfile, newRunId } from "../../run/journal.js";
|
|
9
|
+
import { formatJournalNarration, Journal, loadRoutingProfile, newRunId } from "../../run/journal.js";
|
|
10
10
|
import { normalizeGateOutcome } from "../../run/outcome.js";
|
|
11
11
|
import { GLYPHS, LIVE } from "../../brand.js";
|
|
12
12
|
import { cellWidth, fitCells } from "../../tui/cockpit/width.js";
|
|
13
|
+
import { currentOwed, outstandingText } from "./report.js";
|
|
13
14
|
import { assertRefsWritable } from "../../run/git.js";
|
|
14
15
|
// ── the operator event rail (v1.99 T2) ──────────────────────────────────────────────────────────
|
|
15
16
|
// A run's TTY narration is an operator EVENT RAIL, not the journal dump it used to echo. The
|
|
@@ -166,17 +167,25 @@ const bucket = (value) => (Array.isArray(value) ? value.length : 0);
|
|
|
166
167
|
*
|
|
167
168
|
* a fatal crash, a failed task or a failed integration tip is a FAILURE;
|
|
168
169
|
* an incomplete run — parked, blocked or still-pending work — wants ATTENTION;
|
|
170
|
+
* so does a complete execution that owes a check, or whose owed-check fold is unknown (CG2);
|
|
169
171
|
* only a run with none of those is a pass.
|
|
170
172
|
*
|
|
171
173
|
* A rail that paints the terminal record by the same predicate the exit code uses can never show a
|
|
172
|
-
* green tickmark over a run whose exit code is 2
|
|
174
|
+
* green tickmark over a run whose exit code is 2 — and, since the exit code is execution-based, the
|
|
175
|
+
* debt clause is the one place the tone is stricter than it: exit 0 with an owed check is not green.
|
|
176
|
+
* The fold is the one this row carries, reduced at its own append: live, that IS the current fold.
|
|
173
177
|
*/
|
|
174
178
|
const runEndTone = (data) => {
|
|
175
179
|
if (data.fatal === true || bucket(data.failed) > 0 || data.tipVerify === "failed")
|
|
176
180
|
return "fail";
|
|
177
181
|
if (bucket(data.human) + bucket(data.blocked) + bucket(data.pending) > 0)
|
|
178
182
|
return "attention";
|
|
179
|
-
return "pass";
|
|
183
|
+
return recordedDebt(data) === 0 ? "pass" : "attention";
|
|
184
|
+
};
|
|
185
|
+
/** The outstanding count a run-end record's own fold carries; undefined when it carries none or an unknown one. */
|
|
186
|
+
const recordedDebt = (data) => {
|
|
187
|
+
const owed = data.owedChecks;
|
|
188
|
+
return owed?.known === true && Array.isArray(owed.outstanding) ? owed.outstanding.length : undefined;
|
|
180
189
|
};
|
|
181
190
|
/** A gate row's non-failure is spelled across `pass`, `skipped`, `verdict` and `infra`, and a row may
|
|
182
191
|
* state NONE of them (src/run/outcome.ts) — so the rail reads the canonical outcome rather than
|
|
@@ -330,6 +339,8 @@ const RAIL_PROJECTION = {
|
|
|
330
339
|
"tip-moved": (d) => typeof d.gatedCommit === "string" && typeof d.branchTip === "string"
|
|
331
340
|
? `gated ${d.gatedCommit.slice(0, 12)}, tip ${d.branchTip.slice(0, 12)}`
|
|
332
341
|
: undefined,
|
|
342
|
+
// CG2: the terminal row names its debt — a legacy record without a fold is unknown, never zero
|
|
343
|
+
"run-end": (d) => `outstanding ${recordedDebt(d) ?? "unknown"}`,
|
|
333
344
|
"trust-auto-answer": (d) => typeof d.adapter === "string" ? `${d.adapter}${typeof d.phase === "string" ? ` ${d.phase}` : ""}` : undefined,
|
|
334
345
|
// SB-1: the census the ceiling released beside, and the budget the round ran under versus the one it
|
|
335
346
|
// would have had on an empty census — none of `{count, occupancyCap, conservativeCap}` is on the ladder
|
|
@@ -420,8 +431,25 @@ export function bindNarration(driver, narrate) {
|
|
|
420
431
|
driver.narrateWith?.(narrate);
|
|
421
432
|
return driver;
|
|
422
433
|
}
|
|
423
|
-
|
|
434
|
+
/** Execution green: the exit-code predicate run and resume share. Users' scripts read it; debt never moves it. */
|
|
435
|
+
export const summaryGreen = (s) => s.failed.length === 0 && s.human.length === 0 && s.blocked.length === 0 && s.pending.length === 0
|
|
424
436
|
&& s.tipVerify !== "failed";
|
|
437
|
+
/**
|
|
438
|
+
* CG2 (v2.6.4): the last line of a run or resume, read from the CURRENT owed-check fold after the
|
|
439
|
+
* daemon returns — never the run-end row's copy, which a later `verify --record` discharge leaves
|
|
440
|
+
* historical. "verified" requires execution green AND outstanding empty AND known; an execution-green
|
|
441
|
+
* run that owes a check, or whose debt is unknown, says so and is not green. A partial or failed run
|
|
442
|
+
* adds nothing: its summary keeps its own wording and is never called complete.
|
|
443
|
+
*/
|
|
444
|
+
export function finalRail(s, cwd) {
|
|
445
|
+
if (!summaryGreen(s))
|
|
446
|
+
return "";
|
|
447
|
+
const owed = currentOwed(Journal.open(cwd, s.runId).read(), cwd);
|
|
448
|
+
if (owed.known && owed.outstanding.length === 0)
|
|
449
|
+
return `\nverified — execution complete, ${outstandingText(owed)}`;
|
|
450
|
+
const why = owed.known ? "" : ` (${owed.unknown[0]?.reason ?? "owed checks unreadable"})`;
|
|
451
|
+
return `\nexecution complete; ${outstandingText(owed)}${why} — not green until outstanding is empty and known`;
|
|
452
|
+
}
|
|
425
453
|
// v1.51 T2: --quality is a pure compatibility alias for `--mode partner-led` (this run only). It
|
|
426
454
|
// carries no one-band floor raise of its own — and since the OBS-89 rip (v1.60) route() no longer
|
|
427
455
|
// reads the retired TICKMARKR_QUALITY env at all, so no downstream code can raise a floor on its
|
|
@@ -526,7 +554,7 @@ export async function run(argv, cwd = process.cwd()) {
|
|
|
526
554
|
supersedes: values.supersedes,
|
|
527
555
|
narrate,
|
|
528
556
|
});
|
|
529
|
-
const out = `run ${s.runId} finished — ${formatSummary(s)} (merge to main is a human decision)`;
|
|
557
|
+
const out = `run ${s.runId} finished — ${formatSummary(s)} (merge to main is a human decision)${finalRail(s, cwd)}`;
|
|
530
558
|
return { out, code: summaryGreen(s) ? 0 : 2 };
|
|
531
559
|
}
|
|
532
560
|
finally {
|
|
@@ -12,6 +12,7 @@ import { authorsNote, doneAuthors } from "../../run/operator-state.js";
|
|
|
12
12
|
import { projectOperatorSummary } from "../../run/operator-summary.js";
|
|
13
13
|
import { trackJournalRows } from "../../run/protocol.js";
|
|
14
14
|
import { newestPark, permittedDecisionVerbs } from "./approve.js";
|
|
15
|
+
import { currentOwed, endToEndFirstPass, firstPassText, leadLines, leadRows, needsYouText, wallText } from "./report.js";
|
|
15
16
|
import { Journal, bindingToken, effectiveEvents, formatJournalNarration, parseJournalText, physicalLine, engagementComparable, isQualityFailureParkKind, parseRunId, preservedRefsByTask, recordedTaskFailureKind, runHasEnded, upheldFeedbackByTask, } from "../../run/journal.js";
|
|
16
17
|
import { isPidLive, runLockRunId, runStatusLine } from "../../run/lock.js";
|
|
17
18
|
import { normalizeGateOutcome } from "../../run/outcome.js";
|
|
@@ -448,6 +449,8 @@ export const shortGoal = (goal, max) => {
|
|
|
448
449
|
};
|
|
449
450
|
/** Columns the machine row always spends on the task title, however long its machinery segment runs. */
|
|
450
451
|
const MACHINE_TITLE_FLOOR = 24;
|
|
452
|
+
/** The plain print's own width when none is configured: its machine rows are laid out, and parsed whole, at it. */
|
|
453
|
+
const MACHINE_COLUMNS = 120;
|
|
451
454
|
// The approved task board derives an area from files[] rather than adding another graph field.
|
|
452
455
|
// Known tickmarkr domains keep their reviewed names; other repositories fall back to their first
|
|
453
456
|
// meaningful path segment so the shipped surface never turns a foreign project into UNMAPPED rows.
|
|
@@ -1037,7 +1040,7 @@ binaryVersion, now = Date.now(), animationFrame = 0, workerLiveness = new Map(),
|
|
|
1037
1040
|
// SUP-01: derived by stat() alone, from THIS frame's clock. status stays a reader — nothing here
|
|
1038
1041
|
// creates, touches or reaps a beat file, so an absent supervision dir stays absent.
|
|
1039
1042
|
const supervision = readSupervision(cwd, now);
|
|
1040
|
-
const width = process.stdout.columns ??
|
|
1043
|
+
const width = process.stdout.columns ?? MACHINE_COLUMNS;
|
|
1041
1044
|
const done = journalRowsOnly
|
|
1042
1045
|
? recordedDone(renderedTasks, taskRows)
|
|
1043
1046
|
: effective.tasks.filter((task) => task.status === "done").length;
|
|
@@ -1055,6 +1058,16 @@ binaryVersion, now = Date.now(), animationFrame = 0, workerLiveness = new Map(),
|
|
|
1055
1058
|
if (!taskIds.has(taskId))
|
|
1056
1059
|
phases.delete(taskId);
|
|
1057
1060
|
const hotPhase = [...phases.values()].sort((a, b) => a.order - b.order).at(-1);
|
|
1061
|
+
// CG1: the three lead lines — finished, wall, needs you from the CURRENT owed-check fold — open
|
|
1062
|
+
// every frame, plain and terminal; the header below keeps every comparability, supersession and verify fact.
|
|
1063
|
+
const lead = runId
|
|
1064
|
+
? leadLines(events, currentOwed(events, cwd), {
|
|
1065
|
+
// The header's own rule: while the tip is unverified the tally never reads as a finished run.
|
|
1066
|
+
tally: comparable ? tipPhase ? `${done}/${total} tasks done` : `${done}/${total} done` : NOT_COMPARABLE_CLAIM,
|
|
1067
|
+
tip: verify ? `tip ${verify}` : "tip verify pending",
|
|
1068
|
+
notes: supersededBy ? [`superseded by ${supersededBy}`] : [],
|
|
1069
|
+
}).map(sanitizeTaskText)
|
|
1070
|
+
: [];
|
|
1058
1071
|
// OBS-738: recovery facts stay on the journal's two established reducers. The prefix fold keeps an
|
|
1059
1072
|
// older journal equally readable by asking upheldFeedbackByTask what was active at that exact
|
|
1060
1073
|
// restore boundary; current resume-restore rows additionally carry the same task for narration.
|
|
@@ -1151,8 +1164,16 @@ binaryVersion, now = Date.now(), animationFrame = 0, workerLiveness = new Map(),
|
|
|
1151
1164
|
? `tickmarkr status${divider}${runLine ?? `run ${runId}`}${zone}${supersededBy ? `${divider}superseded by ${supersededBy}` : ""}${!comparable ? `${divider}${NOT_COMPARABLE_NOTICE}` : ""}${divider}${liveness(events, daemon, now).replaceAll(" · ", divider)}${verify ? `${divider}${verify}` : ""}${divider}${tipPhase ? `${done}/${total} tasks done${divider}run not verified` : `${done}/${total} done`}`
|
|
1152
1165
|
: `tickmarkr status${zone}${divider}no runs yet${divider}${done}/${total} done`;
|
|
1153
1166
|
const legendLine = ` gates: ${GATE_NAMES.map((gate) => `${GATE_KEYS[gate]} ${gate}`).join(divider)}`;
|
|
1167
|
+
// At its machine width and wider the plain print keeps each machine row whole — one row per task and
|
|
1168
|
+
// its evidence line after it, which consumers parse. A configured width narrower than that holds for
|
|
1169
|
+
// EVERY row: one that overflows wraps beneath its own indent, its identity kept on the first.
|
|
1170
|
+
const body = [header, legendLine, ` ${supervisionText(supervision, divider)}`, ...rows];
|
|
1171
|
+
const wrapRow = (line) => wrapCells(line, width, { continuationPrefix: `${/^ */u.exec(line)[0]} ` });
|
|
1154
1172
|
return {
|
|
1155
|
-
content: [
|
|
1173
|
+
content: [
|
|
1174
|
+
...leadRows(lead, width),
|
|
1175
|
+
...(width >= MACHINE_COLUMNS ? body : body.flatMap(wrapRow)),
|
|
1176
|
+
].join("\n"),
|
|
1156
1177
|
...(hotPhase ? { hotPhase } : {}),
|
|
1157
1178
|
...(runId ? { runId } : {}),
|
|
1158
1179
|
workerPhases: [...phases.values()].filter((phase) => phase.phase === "worker"),
|
|
@@ -1349,6 +1370,7 @@ binaryVersion, now = Date.now(), animationFrame = 0, workerLiveness = new Map(),
|
|
|
1349
1370
|
const effort = effortPanel(g.tasks, record && !comparable ? undefined : events, boardColumns);
|
|
1350
1371
|
return {
|
|
1351
1372
|
content: boardRows([
|
|
1373
|
+
...leadRows(lead, boardColumns),
|
|
1352
1374
|
...headerRows,
|
|
1353
1375
|
...nowLine,
|
|
1354
1376
|
supervisionLegend,
|
|
@@ -1404,7 +1426,12 @@ const oneLine = (cwd, namedRunId) => {
|
|
|
1404
1426
|
`verify ${recordedVerify(record.events)}`,
|
|
1405
1427
|
]
|
|
1406
1428
|
: [NOT_COMPARABLE_CLAIM, "verify unavailable"];
|
|
1407
|
-
|
|
1429
|
+
// CG1: the lead's facts in one line — lineage first pass, the wall window, and what needs you from
|
|
1430
|
+
// the CURRENT fold, so a discharge after run-end moves this line too.
|
|
1431
|
+
const { events } = record;
|
|
1432
|
+
return sanitizeTaskText([
|
|
1433
|
+
record.runId, ...claims, firstPassText(endToEndFirstPass(events)), wallText(events), needsYouText(events, currentOwed(events, cwd)),
|
|
1434
|
+
].join(" · "));
|
|
1408
1435
|
};
|
|
1409
1436
|
export async function status(argv, cwd = process.cwd(), opts = {}) {
|
|
1410
1437
|
if (argv.some((arg) => arg === "--help" || arg === "-h"))
|
|
@@ -7,7 +7,7 @@ export declare const HUMAN_AUTHOR: Assignment;
|
|
|
7
7
|
export declare function verifyStateDir(cwd: string): string;
|
|
8
8
|
/** Linked worktrees share operational state with the repository that owns the common git dir. */
|
|
9
9
|
export declare function verifyStateRoot(cwd: string): Promise<string>;
|
|
10
|
-
/**
|
|
10
|
+
/** Repository content plus the effective runner inputs the daemon hashes; never a checkout path. */
|
|
11
11
|
export declare function baselineCachePath(cwd: string, baseSha: string, commands: Record<string, string>): string;
|
|
12
12
|
export declare function excludeAuthorProvider(channels: BillingChannel[], author: BillingChannel): BillingChannel[];
|
|
13
13
|
export declare const VERIFY_HELP = "usage: tickmarkr verify [--base <ref>] [--criteria <file> | --task <id>] [--json]\nThe final verdict and JSON result are written to stdout; progress and diagnostics are written to stderr.\nDo not merge stdout and stderr (for example with 2>&1): doing so corrupts the verdict stream.";
|