tickmarkr 1.97.0 → 2.1.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/README.md +19 -1
- package/dist/brand.d.ts +28 -0
- package/dist/brand.js +41 -0
- package/dist/cli/commands/compile.js +32 -1
- package/dist/cli/commands/doctor.d.ts +19 -0
- package/dist/cli/commands/doctor.js +59 -0
- package/dist/cli/commands/init.js +5 -2
- package/dist/cli/commands/resume.js +25 -8
- package/dist/cli/commands/run.d.ts +61 -1
- package/dist/cli/commands/run.js +372 -18
- package/dist/cli/commands/status.js +145 -28
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/compile/collateral.d.ts +25 -0
- package/dist/compile/collateral.js +46 -11
- package/dist/compile/native.js +10 -0
- package/dist/config/config.d.ts +1 -0
- package/dist/config/config.js +2 -2
- package/dist/drivers/herdr.d.ts +19 -13
- package/dist/drivers/herdr.js +90 -26
- package/dist/drivers/index.d.ts +5 -1
- package/dist/drivers/index.js +16 -1
- package/dist/drivers/orca.d.ts +189 -0
- package/dist/drivers/orca.js +879 -0
- package/dist/drivers/types.d.ts +2 -0
- package/dist/gates/acceptance.js +17 -7
- package/dist/gates/llm.d.ts +19 -0
- package/dist/gates/llm.js +104 -6
- package/dist/gates/run-gates.d.ts +18 -0
- package/dist/gates/run-gates.js +195 -29
- package/dist/gates/scope.d.ts +9 -1
- package/dist/gates/scope.js +22 -2
- package/dist/graph/graph.d.ts +1 -0
- package/dist/graph/graph.js +19 -2
- package/dist/report/compare.js +17 -2
- package/dist/run/daemon.d.ts +1 -8
- package/dist/run/daemon.js +231 -246
- package/dist/run/environment.d.ts +18 -1
- package/dist/run/environment.js +19 -2
- package/dist/run/journal.d.ts +50 -3
- package/dist/run/journal.js +181 -5
- package/dist/run/protocol.d.ts +4 -4
- package/dist/run/stall.d.ts +30 -0
- package/dist/run/stall.js +173 -0
- package/dist/tui/ink/init-app.js +14 -4
- package/package.json +1 -1
- package/skills/tickmarkr-overseer/SKILL.md +27 -15
package/dist/gates/scope.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { classifyScopeOffenders } from "../compile/collateral.js";
|
|
1
2
|
import { filesGlob } from "../graph/files-glob.js";
|
|
2
3
|
import { shGitOk } from "../run/git.js";
|
|
3
4
|
// OBS-61: the live integration tip can advance between attempts (sibling merge) while a resumed
|
|
@@ -22,7 +23,12 @@ export function dispositionOffenders(offenders, allowDeviations) {
|
|
|
22
23
|
}
|
|
23
24
|
return { hard, allowed };
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
+
/**
|
|
27
|
+
* OBS-547: `collateral` is this task's slice of the run's ONE full prediction map (computed at run
|
|
28
|
+
* start, uncapped — src/compile/collateral.ts). Absent ⇒ no classification, today's behaviour; the
|
|
29
|
+
* gate never computes a map of its own, so what it classifies on is always what the run predicted.
|
|
30
|
+
*/
|
|
31
|
+
export async function scopeGate(worktree, integrationTip, files, result, allowDeviations = [], collateral) {
|
|
26
32
|
if (!files.length)
|
|
27
33
|
return { gate: "scope", pass: true, details: "no file scope declared — unrestricted" };
|
|
28
34
|
const baseRef = await scopeDiffBase(worktree, integrationTip);
|
|
@@ -38,5 +44,19 @@ export async function scopeGate(worktree, integrationTip, files, result, allowDe
|
|
|
38
44
|
if (!hard.length) {
|
|
39
45
|
return { gate: "scope", pass: true, details: `out-of-scope but operator-allowlisted:\n${allowed.join("\n")}${note}` };
|
|
40
46
|
}
|
|
41
|
-
|
|
47
|
+
// OBS-547: cross-reference at the red — the red supplies the paths, the prediction the classification.
|
|
48
|
+
const verdict = collateral
|
|
49
|
+
? classifyScopeOffenders(collateral.taskId, hard, collateral.predicted)
|
|
50
|
+
: undefined;
|
|
51
|
+
const classification = verdict?.authoring
|
|
52
|
+
? `\nauthoring defect (OBS-547): the collateral lint named every one of these paths before dispatch. Repair:\n${verdict.repair}`
|
|
53
|
+
: verdict && verdict.missed.length
|
|
54
|
+
? `\ncollateral lint did not predict: ${verdict.missed.join(", ")}`
|
|
55
|
+
: "";
|
|
56
|
+
return {
|
|
57
|
+
gate: "scope",
|
|
58
|
+
pass: false,
|
|
59
|
+
details: `out-of-scope edits not covered by scope.allowDeviations:\n${hard.join("\n")}${note}${classification}`,
|
|
60
|
+
...(verdict ? { meta: { collateral: verdict } } : {}),
|
|
61
|
+
};
|
|
42
62
|
}
|
package/dist/graph/graph.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type RunGraph, type Task, type TaskStatus } from "./schema.js";
|
|
|
2
2
|
export declare function stateDirName(_repoRoot: string): string;
|
|
3
3
|
export declare function graphPath(repoRoot: string): string;
|
|
4
4
|
export declare function graphDefinitionHash(g: RunGraph): string;
|
|
5
|
+
export declare function taskContentDigest(task: Pick<Task, "goal" | "files" | "acceptance">): string;
|
|
5
6
|
export declare function tickmarkrDir(repoRoot: string): string;
|
|
6
7
|
export declare function loadGraph(repoRoot: string): RunGraph;
|
|
7
8
|
export declare function saveGraph(repoRoot: string, g: RunGraph): void;
|
package/dist/graph/graph.js
CHANGED
|
@@ -19,6 +19,16 @@ export function graphDefinitionHash(g) {
|
|
|
19
19
|
const definitions = g.tasks.map(({ status: _status, evidence: _evidence, ...def }) => def);
|
|
20
20
|
return createHash("sha256").update(JSON.stringify({ version: g.version, spec: g.spec, tasks: definitions })).digest("hex").slice(0, 16);
|
|
21
21
|
}
|
|
22
|
+
// OBS-543: cross-run evidence belongs to the artifact one task describes, not to the whole compiled
|
|
23
|
+
// graph. A sibling task, dependency, routing hint or status change therefore cannot expire a useful
|
|
24
|
+
// finding; changing the goal, write surface or acceptance contract does. Keep the full digest here:
|
|
25
|
+
// unlike graphDefinitionHash this value is persisted beside evidence and is the fail-closed join a
|
|
26
|
+
// later run uses, so there is no benefit in making collision diagnosis less explicit.
|
|
27
|
+
export function taskContentDigest(task) {
|
|
28
|
+
return createHash("sha256")
|
|
29
|
+
.update(JSON.stringify({ goal: task.goal, files: task.files, acceptance: task.acceptance }))
|
|
30
|
+
.digest("hex");
|
|
31
|
+
}
|
|
22
32
|
export function tickmarkrDir(repoRoot) {
|
|
23
33
|
const dir = join(repoRoot, stateDirName(repoRoot));
|
|
24
34
|
mkdirSync(dir, { recursive: true });
|
|
@@ -59,7 +69,14 @@ export function setStatus(g, id, status) {
|
|
|
59
69
|
return { ...g, tasks: g.tasks.map((t) => (t.id === id ? { ...t, status } : t)) };
|
|
60
70
|
}
|
|
61
71
|
export function addEvidence(g, id, patch) {
|
|
62
|
-
getTask(g, id);
|
|
72
|
+
const subject = getTask(g, id);
|
|
73
|
+
const digest = taskContentDigest(subject);
|
|
74
|
+
// This is the graph-evidence boundary where a gate result meets the task it measured. Stamp a
|
|
75
|
+
// copy, never mutate the gate result runGates returned: callers still use that live object for
|
|
76
|
+
// predicates, while durable evidence gains the content identity a later run can compare.
|
|
77
|
+
const gateResults = (patch.gateResults ?? []).map((result) => result !== null && typeof result === "object" && !Array.isArray(result)
|
|
78
|
+
? { ...result, taskContentDigest: digest }
|
|
79
|
+
: result);
|
|
63
80
|
return {
|
|
64
81
|
...g,
|
|
65
82
|
tasks: g.tasks.map((t) => t.id === id
|
|
@@ -68,7 +85,7 @@ export function addEvidence(g, id, patch) {
|
|
|
68
85
|
evidence: {
|
|
69
86
|
commits: [...t.evidence.commits, ...(patch.commits ?? [])],
|
|
70
87
|
artifacts: [...t.evidence.artifacts, ...(patch.artifacts ?? [])],
|
|
71
|
-
gateResults: [...t.evidence.gateResults, ...
|
|
88
|
+
gateResults: [...t.evidence.gateResults, ...gateResults],
|
|
72
89
|
},
|
|
73
90
|
}
|
|
74
91
|
: t),
|
package/dist/report/compare.js
CHANGED
|
@@ -21,7 +21,21 @@ export function recordedEnvironment(events) {
|
|
|
21
21
|
return undefined;
|
|
22
22
|
adapterVersions[k] = v;
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
// Capacity arrived in v2.0 as a pair. Two absent fields are an honest older record; one without
|
|
25
|
+
// the other is a malformed new record and fails closed instead of being compared as legacy.
|
|
26
|
+
const hasCores = Object.hasOwn(o, "cores");
|
|
27
|
+
const hasForkCap = Object.hasOwn(o, "forkCap");
|
|
28
|
+
if (hasCores !== hasForkCap)
|
|
29
|
+
return undefined;
|
|
30
|
+
if (hasCores && (typeof o.cores !== "number" || !Number.isFinite(o.cores) || o.cores <= 0
|
|
31
|
+
|| typeof o.forkCap !== "number" || !Number.isFinite(o.forkCap) || o.forkCap <= 0))
|
|
32
|
+
return undefined;
|
|
33
|
+
return {
|
|
34
|
+
tickmarkrVersion: o.tickmarkrVersion,
|
|
35
|
+
configHash: o.configHash,
|
|
36
|
+
adapterVersions,
|
|
37
|
+
...(hasCores ? { cores: o.cores, forkCap: o.forkCap } : {}),
|
|
38
|
+
};
|
|
25
39
|
}
|
|
26
40
|
return undefined;
|
|
27
41
|
}
|
|
@@ -31,7 +45,8 @@ function envFingerprint(env) {
|
|
|
31
45
|
return env.configHash;
|
|
32
46
|
}
|
|
33
47
|
function envEqual(a, b) {
|
|
34
|
-
if (a.tickmarkrVersion !== b.tickmarkrVersion || a.configHash !== b.configHash
|
|
48
|
+
if (a.tickmarkrVersion !== b.tickmarkrVersion || a.configHash !== b.configHash
|
|
49
|
+
|| a.cores !== b.cores || a.forkCap !== b.forkCap)
|
|
35
50
|
return false;
|
|
36
51
|
const ak = Object.keys(a.adapterVersions).sort();
|
|
37
52
|
const bk = Object.keys(b.adapterVersions).sort();
|
package/dist/run/daemon.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type ExecutorDriver } from "../drivers/types.js";
|
|
|
4
4
|
import { type Baseline } from "../gates/baseline.js";
|
|
5
5
|
import type { GateResult } from "../gates/types.js";
|
|
6
6
|
import { Journal, type JournalEvent } from "./journal.js";
|
|
7
|
+
export { harvestCpuFlatWindowMs, resetHarvestCpuFlatMsForTests, setHarvestCpuFlatMsForTests, workerTreeCpuMs, } from "./stall.js";
|
|
7
8
|
export interface RunOptions {
|
|
8
9
|
runId?: string;
|
|
9
10
|
resume?: boolean;
|
|
@@ -117,10 +118,6 @@ export declare function resetDeadChannelFastKillMsForTests(): void;
|
|
|
117
118
|
/** Test seam — shrink the harvest silence gate without minute-long sleeps. */
|
|
118
119
|
export declare function setHarvestSilentMsForTests(ms: number): void;
|
|
119
120
|
export declare function resetHarvestSilentMsForTests(): void;
|
|
120
|
-
export declare function harvestCpuFlatWindowMs(resolutionMs: number): number;
|
|
121
|
-
/** Test seam — pin the flat window so a probe case need not sit through a real one. */
|
|
122
|
-
export declare function setHarvestCpuFlatMsForTests(ms: number): void;
|
|
123
|
-
export declare function resetHarvestCpuFlatMsForTests(): void;
|
|
124
121
|
export declare const HARVESTED_RESULT_SUMMARY = "harvested: the worktree carries committed work; the worker emitted no TICKMARKR_RESULT trailer";
|
|
125
122
|
/** T4 (OBS-266): identity of the command SET a tip verify ran — a changed command is a different verify. */
|
|
126
123
|
export declare function commandsHash(commands: Record<string, string>): string;
|
|
@@ -139,10 +136,6 @@ export declare function verifyIntegrationTipCached(intWt: string, commands: Reco
|
|
|
139
136
|
lastMergedTask?: string;
|
|
140
137
|
baseline?: Baseline;
|
|
141
138
|
}): Promise<boolean>;
|
|
142
|
-
export declare function workerTreeCpuMs(marker: string, cwd: string): Promise<{
|
|
143
|
-
ms: number;
|
|
144
|
-
resolutionMs: number;
|
|
145
|
-
} | undefined>;
|
|
146
139
|
/** Test seam — exercise the production observer's total read bound with a small real tree. */
|
|
147
140
|
export declare function setObserveBudgetBytesForTests(bytes: number): void;
|
|
148
141
|
export declare function resetObserveBudgetBytesForTests(): void;
|