tickmarkr 1.36.0 → 1.38.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/LICENSE +21 -0
- package/README.md +83 -207
- package/dist/adapters/claude-code.js +4 -4
- package/dist/adapters/codex.js +1 -1
- package/dist/adapters/fake.d.ts +2 -2
- package/dist/adapters/fake.js +8 -8
- package/dist/adapters/grok.js +5 -5
- package/dist/adapters/model-lints.d.ts +4 -4
- package/dist/adapters/model-lints.js +1 -1
- package/dist/adapters/prompt.js +8 -13
- package/dist/adapters/registry.d.ts +8 -8
- package/dist/adapters/registry.js +5 -5
- package/dist/adapters/types.d.ts +3 -3
- package/dist/adapters/types.js +1 -1
- package/dist/brand.d.ts +2 -0
- package/dist/brand.js +17 -0
- package/dist/cli/commands/approve.js +3 -3
- package/dist/cli/commands/compile.js +1 -1
- package/dist/cli/commands/doctor.js +3 -3
- package/dist/cli/commands/init.js +14 -9
- package/dist/cli/commands/profile.js +6 -6
- package/dist/cli/commands/status.js +2 -1
- package/dist/cli/commands/unlock.js +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +9 -7
- package/dist/compile/gsd.js +1 -1
- package/dist/compile/index.js +9 -3
- package/dist/compile/native.d.ts +2 -0
- package/dist/compile/native.js +4 -2
- package/dist/config/config.d.ts +6 -6
- package/dist/config/config.js +13 -12
- package/dist/drivers/herdr.js +5 -5
- package/dist/drivers/index.d.ts +2 -2
- package/dist/drivers/subprocess.js +3 -3
- package/dist/drivers/types.js +4 -6
- package/dist/gates/acceptance.js +1 -1
- package/dist/gates/baseline.d.ts +2 -2
- package/dist/gates/llm.js +12 -9
- package/dist/gates/review.d.ts +2 -2
- package/dist/gates/review.js +1 -1
- package/dist/gates/run-gates.d.ts +2 -2
- package/dist/graph/graph.d.ts +2 -2
- package/dist/graph/graph.js +4 -16
- package/dist/plan/prompt.js +1 -1
- package/dist/plan/scope.d.ts +2 -2
- package/dist/plan/scope.js +5 -5
- package/dist/route/preference.d.ts +4 -4
- package/dist/route/router.d.ts +3 -3
- package/dist/run/consult.d.ts +2 -2
- package/dist/run/consult.js +5 -5
- package/dist/run/daemon.d.ts +2 -0
- package/dist/run/daemon.js +48 -17
- package/dist/run/git.d.ts +1 -1
- package/dist/run/git.js +5 -9
- package/dist/run/journal.d.ts +2 -2
- package/dist/run/journal.js +9 -5
- package/dist/run/lock.js +11 -11
- package/dist/run/merge.d.ts +11 -2
- package/dist/run/merge.js +21 -3
- package/dist/run/reconcile.js +1 -1
- package/package.json +4 -2
- package/skills/tickmarkr-auto/SKILL.md +1 -1
- package/skills/tickmarkr-loop/SKILL.md +1 -1
package/dist/run/git.js
CHANGED
|
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { existsSync, symlinkSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { shq } from "../adapters/types.js";
|
|
5
|
-
import {
|
|
5
|
+
import { tickmarkrDir } from "../graph/graph.js";
|
|
6
6
|
// stdin "ignore": same class as HARD-05 / SubprocessDriver — never leave an open pipe a child can block on
|
|
7
7
|
// (pi -p / codex exec wait for stdin EOF). timedOut distinguishes SIGKILL-timeout from a real nonzero exit.
|
|
8
8
|
export function sh(cmd, cwd, timeoutMs = 600000) {
|
|
@@ -49,7 +49,7 @@ export async function gitHead(cwd) {
|
|
|
49
49
|
}
|
|
50
50
|
export const sanitizeBranch = (branch) => branch.replace(/[^\w.-]+/g, "-");
|
|
51
51
|
const sanitize = sanitizeBranch;
|
|
52
|
-
export const worktreePath = (repo, branch) => join(
|
|
52
|
+
export const worktreePath = (repo, branch) => join(tickmarkrDir(repo), "worktrees", sanitize(branch));
|
|
53
53
|
/** OBS-28: remove this run's recorded worktrees; tolerates already-gone paths. */
|
|
54
54
|
export async function cleanupRunWorktrees(repo, branch, opts) {
|
|
55
55
|
if (opts.removeIntegration)
|
|
@@ -57,12 +57,8 @@ export async function cleanupRunWorktrees(repo, branch, opts) {
|
|
|
57
57
|
for (const id of opts.removeTaskIds)
|
|
58
58
|
await removeWorktree(repo, worktreePath(repo, `${branch}--${id}`));
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!branch.startsWith("drovr/"))
|
|
63
|
-
return branch;
|
|
64
|
-
const legacy = `drover/${branch.slice("drovr/".length)}`;
|
|
65
|
-
return !(await branchExists(repo, branch)) && await branchExists(repo, legacy) ? legacy : branch;
|
|
60
|
+
export async function resolveIntegrationBranch(_repo, branch) {
|
|
61
|
+
return branch;
|
|
66
62
|
}
|
|
67
63
|
const resolveTaskBranch = async (repo, branch) => {
|
|
68
64
|
const split = branch.lastIndexOf("--");
|
|
@@ -73,7 +69,7 @@ const resolveTaskBranch = async (repo, branch) => {
|
|
|
73
69
|
};
|
|
74
70
|
export async function createWorktree(repo, branch, baseRef) {
|
|
75
71
|
branch = await resolveTaskBranch(repo, branch);
|
|
76
|
-
const dir = join(
|
|
72
|
+
const dir = join(tickmarkrDir(repo), "worktrees", sanitize(branch));
|
|
77
73
|
if (existsSync(dir))
|
|
78
74
|
await removeWorktree(repo, dir);
|
|
79
75
|
await shOk(`git worktree add -B ${shq(branch)} ${shq(dir)} ${shq(baseRef)}`, repo);
|
package/dist/run/journal.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { type Assignment } from "../adapters/types.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { TickmarkrConfig } from "../config/config.js";
|
|
4
4
|
import { type TaskStatus } from "../graph/schema.js";
|
|
5
5
|
import { type RoutingProfile } from "../route/profile.js";
|
|
6
6
|
export interface JournalEvent {
|
|
@@ -70,7 +70,7 @@ export declare function readAllTelemetry(repoRoot: string, lastK: number, opts?:
|
|
|
70
70
|
})[];
|
|
71
71
|
export declare const RUNS_WINDOW = 50;
|
|
72
72
|
export declare function readProfileCursor(repoRoot: string): string | undefined;
|
|
73
|
-
export declare function loadRoutingProfile(repoRoot: string, cfg:
|
|
73
|
+
export declare function loadRoutingProfile(repoRoot: string, cfg: TickmarkrConfig, opts?: {
|
|
74
74
|
preview?: boolean;
|
|
75
75
|
}): RoutingProfile | undefined;
|
|
76
76
|
export declare class Journal {
|
package/dist/run/journal.js
CHANGED
|
@@ -12,7 +12,11 @@ export function formatJournalNarration({ event, taskId, data }) {
|
|
|
12
12
|
const detail = Array.isArray(data.done)
|
|
13
13
|
? `done ${data.done.length}, failed ${Array.isArray(data.failed) ? data.failed.length : 0}`
|
|
14
14
|
: typeof data.gate === "string"
|
|
15
|
-
?
|
|
15
|
+
? event === "tip-verify-failed"
|
|
16
|
+
? `${data.gate} failed${typeof data.lastMergedTask === "string" ? ` after ${data.lastMergedTask}` : ""}`
|
|
17
|
+
: event === "tip-verify"
|
|
18
|
+
? `${data.gate} passed`
|
|
19
|
+
: `${data.gate}${data.pass === true ? " passed" : data.pass === false ? " failed" : ""}`
|
|
16
20
|
: typeof data.code === "number" ? `exit ${data.code}`
|
|
17
21
|
: typeof data.pid === "number" ? `pid ${data.pid}`
|
|
18
22
|
: typeof data.baseRef === "string" ? `base ${data.baseRef.slice(0, 12)}`
|
|
@@ -119,8 +123,8 @@ export function readAllTelemetry(repoRoot, lastK, opts = {}) {
|
|
|
119
123
|
}
|
|
120
124
|
// ponytail: fixed 50-run window; promote to a routing.learned.* config knob only if operators need to tune it.
|
|
121
125
|
export const RUNS_WINDOW = 50;
|
|
122
|
-
// VIS-03 reset cursor — one trimmed runId line at .
|
|
123
|
-
// Opaque: used ONLY in the runId > comparison above, never a shell or path join beyond .
|
|
126
|
+
// VIS-03 reset cursor — one trimmed runId line at .tickmarkr/profile-since; absent/empty ⇒ undefined.
|
|
127
|
+
// Opaque: used ONLY in the runId > comparison above, never a shell or path join beyond .tickmarkr/.
|
|
124
128
|
export function readProfileCursor(repoRoot) {
|
|
125
129
|
const path = join(repoRoot, stateDirName(repoRoot), "profile-since");
|
|
126
130
|
if (!existsSync(path))
|
|
@@ -128,7 +132,7 @@ export function readProfileCursor(repoRoot) {
|
|
|
128
132
|
return readFileSync(path, "utf8").trim() || undefined;
|
|
129
133
|
}
|
|
130
134
|
// The one shared profile builder (criterion 4: plan and daemon share ONE code path).
|
|
131
|
-
// preview:true bypasses the routing.learned:off short-circuit so `
|
|
135
|
+
// preview:true bypasses the routing.learned:off short-circuit so `tickmarkr plan` can render the
|
|
132
136
|
// trust-ramp preview while the daemon (no preview) stays inert (VALIDATION 13-01-11).
|
|
133
137
|
export function loadRoutingProfile(repoRoot, cfg, opts = {}) {
|
|
134
138
|
if (cfg.routing.learned === "off" && !opts.preview)
|
|
@@ -214,7 +218,7 @@ export class Journal {
|
|
|
214
218
|
// lastAssignment} from EXISTING events only (task-dispatch + consult-verdict + optional v1.24
|
|
215
219
|
// task-approved{release:attempt-cap}). Additive-only: no new required event, no schema change, the
|
|
216
220
|
// status replay above is byte-untouched (corpus criterion 3 is git-diff-provable). Motivated by the
|
|
217
|
-
// 2026-07-11 incident (run-20260711-185020, P43-03): `
|
|
221
|
+
// 2026-07-11 incident (run-20260711-185020, P43-03): `tickmarkr resume` re-dispatched at attempt 0 on
|
|
218
222
|
// pi:zai/glm-5.2, the exact channel a frontier consult had just banned, because execTask's
|
|
219
223
|
// attempt/tried/assignment state is loop-local and dies with the process while the journal held every fact needed.
|
|
220
224
|
//
|
package/dist/run/lock.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { linkSync, readFileSync, statSync, unlinkSync, utimesSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import {
|
|
5
|
-
// HARD-01/02: coarse per-run advisory lock over .
|
|
4
|
+
import { tickmarkrDir, stateDirName } from "../graph/graph.js";
|
|
5
|
+
// HARD-01/02: coarse per-run advisory lock over .tickmarkr/graph.json. LOCK-02: the lock is created by
|
|
6
6
|
// the link(2) idiom — write the full payload to graph.lock.<pid>.tmp, then linkSync(tmp, lockPath),
|
|
7
7
|
// which is atomic and throws EEXIST if the lock already exists (the mutual-exclusion primitive).
|
|
8
8
|
// rename() was REJECTED: it silently clobbers an existing destination, destroying that mutual
|
|
9
9
|
// exclusion (two daemons would both "acquire"). LOCK-02 (OBS-05): a PROVABLY-dead holder (ESRCH)
|
|
10
10
|
// self-clears immediately — expiry is NOT required. ESRCH is proof-positive death; the PID-reuse
|
|
11
|
-
// hazard runs the OTHER way (a reused pid reads ALIVE and refuses until `
|
|
11
|
+
// hazard runs the OTHER way (a reused pid reads ALIVE and refuses until `tickmarkr unlock`). mtime stays
|
|
12
12
|
// the heartbeat — it feeds the reclaim race guard (ino+mtime re-stat) and the reclaimed audit value.
|
|
13
13
|
// Zero new deps — node:fs stdlib.
|
|
14
14
|
export const HEARTBEAT_MS = 10_000;
|
|
@@ -16,7 +16,7 @@ export const STALE_MS = 60_000; // 6× heartbeat headroom; PITFALLS floor is ≥
|
|
|
16
16
|
// T-10-01: the payload is a trust boundary — parse with zod, fail closed on garbage. Only
|
|
17
17
|
// pid/runId/startedAt are ever read; anything else is ignored (info-disclosure surface).
|
|
18
18
|
const PayloadSchema = z.object({ pid: z.number().int().positive(), runId: z.string(), startedAt: z.number() });
|
|
19
|
-
const lockPath = (repoRoot) => join(
|
|
19
|
+
const lockPath = (repoRoot) => join(tickmarkrDir(repoRoot), "graph.lock");
|
|
20
20
|
let heartbeat;
|
|
21
21
|
let heldPath;
|
|
22
22
|
// Best-effort release if the daemon exits without hitting its finally (crash mid-body). NO
|
|
@@ -33,12 +33,12 @@ process.once("exit", () => { if (heldPath)
|
|
|
33
33
|
// `expired` for the race guard + reclaim audit); the heartbeat mechanism itself is untouched.
|
|
34
34
|
// ponytail: a pid REUSED by an unrelated live process reads ALIVE (kill(pid,0) succeeds) and now
|
|
35
35
|
// refuses indefinitely instead of expiring out in ≤60s — that is the fail-closed direction; the
|
|
36
|
-
// escape hatch is `
|
|
36
|
+
// escape hatch is `tickmarkr unlock`. Acceptable for a single-machine tool (ESRCH is the only
|
|
37
37
|
// proof-positive death; narrowing further needs pid-start-time correlation, out of scope here).
|
|
38
38
|
// LOCK-01: garbage ⇒ always refuse (mtime irrelevant). It short-circuits before dead can matter —
|
|
39
39
|
// so inspect()'s `dead = pid === undefined` fallback for the garbage row stays harmless. Safe post-16-01:
|
|
40
|
-
// the atomic link(2) write means
|
|
41
|
-
// come from external corruption, which is exactly what must refuse. Only `
|
|
40
|
+
// the atomic link(2) write means tickmarkr can no longer mint garbage itself; a garbage payload can only
|
|
41
|
+
// come from external corruption, which is exactly what must refuse. Only `tickmarkr unlock` removes it
|
|
42
42
|
// — a self-heal reclaim would silently overwrite whatever corrupted the file.
|
|
43
43
|
export function shouldRefuse(i) {
|
|
44
44
|
return i.garbage || !i.dead;
|
|
@@ -49,7 +49,7 @@ function inspect(p) {
|
|
|
49
49
|
const mtimeMs = st.mtimeMs;
|
|
50
50
|
const expired = Date.now() - mtimeMs > STALE_MS;
|
|
51
51
|
const parsed = PayloadSchema.safeParse(readPayload(p));
|
|
52
|
-
const garbage = !parsed.success; // LOCK-01: its own state — shouldRefuse refuses it unconditionally; only `
|
|
52
|
+
const garbage = !parsed.success; // LOCK-01: its own state — shouldRefuse refuses it unconditionally; only `tickmarkr unlock` removes it
|
|
53
53
|
const pid = parsed.success ? parsed.data.pid : undefined;
|
|
54
54
|
let dead = pid === undefined; // harmless fallback for the garbage row — garbage short-circuits shouldRefuse before this is read
|
|
55
55
|
if (pid !== undefined) {
|
|
@@ -81,7 +81,7 @@ function unlinkIfOurs(p) {
|
|
|
81
81
|
}
|
|
82
82
|
export function acquireRunLock(repoRoot, runId) {
|
|
83
83
|
const p = lockPath(repoRoot);
|
|
84
|
-
const tmp = join(
|
|
84
|
+
const tmp = join(tickmarkrDir(repoRoot), `graph.lock.${process.pid}.tmp`);
|
|
85
85
|
try {
|
|
86
86
|
try {
|
|
87
87
|
unlinkSync(tmp);
|
|
@@ -127,10 +127,10 @@ export function acquireRunLock(repoRoot, runId) {
|
|
|
127
127
|
}
|
|
128
128
|
const stateDir = stateDirName(repoRoot);
|
|
129
129
|
if (garbage)
|
|
130
|
-
throw new Error(`${stateDir}/graph.lock holds an unreadable/garbage payload — refusing to reclaim it; run \`
|
|
130
|
+
throw new Error(`${stateDir}/graph.lock holds an unreadable/garbage payload — refusing to reclaim it; run \`tickmarkr unlock\` to remove it`);
|
|
131
131
|
// LOCK-02: shouldRefuse is false whenever dead, so this throw is reached only for a LIVE holder
|
|
132
132
|
// (incl. EPERM = alive-but-not-ours). The dead-but-fresh case self-clears via the reclaim branch.
|
|
133
|
-
throw new Error(`${stateDir}/graph.lock held by pid ${pid ?? "?"}${heldRun ? ` (run ${heldRun})` : ""} — another
|
|
133
|
+
throw new Error(`${stateDir}/graph.lock held by pid ${pid ?? "?"}${heldRun ? ` (run ${heldRun})` : ""} — another tickmarkr run? (operator escape: \`tickmarkr unlock\`)`);
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
export function releaseRunLock(repoRoot) {
|
package/dist/run/merge.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export
|
|
1
|
+
import type { TickmarkrConfig } from "../config/config.js";
|
|
2
|
+
export interface TipVerifyResult {
|
|
3
|
+
gate: string;
|
|
4
|
+
cmd: string;
|
|
5
|
+
pass: boolean;
|
|
6
|
+
exitCode: number;
|
|
7
|
+
fingerprints: string[];
|
|
8
|
+
details: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function integrationBranch(cfg: TickmarkrConfig, runId: string): string;
|
|
3
11
|
export declare function ensureIntegration(repo: string, branch: string, baseRef: string): Promise<string>;
|
|
4
12
|
export declare function integrationHead(intWt: string): Promise<string>;
|
|
5
13
|
export declare function mergeTask(intWt: string, taskBranch: string, message: string, gatedCommit: string): Promise<{
|
|
@@ -10,3 +18,4 @@ export declare function mergeTask(intWt: string, taskBranch: string, message: st
|
|
|
10
18
|
branchTip: string;
|
|
11
19
|
};
|
|
12
20
|
}>;
|
|
21
|
+
export declare function verifyIntegrationTip(intWt: string, commands: Record<string, string>): Promise<TipVerifyResult[]>;
|
package/dist/run/merge.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { shq } from "../adapters/types.js";
|
|
4
|
-
import {
|
|
4
|
+
import { fingerprint } from "../gates/baseline.js";
|
|
5
|
+
import { tickmarkrDir } from "../graph/graph.js";
|
|
5
6
|
import { gitHead, resolveIntegrationBranch, sh, shOk } from "./git.js";
|
|
6
7
|
export function integrationBranch(cfg, runId) {
|
|
7
|
-
return
|
|
8
|
+
return `${cfg.integrationBranchPrefix}${runId}`;
|
|
8
9
|
}
|
|
9
10
|
const sanitize = (branch) => branch.replace(/[^\w.-]+/g, "-");
|
|
10
11
|
export async function ensureIntegration(repo, branch, baseRef) {
|
|
11
12
|
branch = await resolveIntegrationBranch(repo, branch);
|
|
12
|
-
const dir = join(
|
|
13
|
+
const dir = join(tickmarkrDir(repo), "worktrees", sanitize(branch));
|
|
13
14
|
if (existsSync(join(dir, ".git")))
|
|
14
15
|
return dir; // resume: keep existing tip
|
|
15
16
|
const exists = (await sh(`git rev-parse --verify refs/heads/${shq(branch)}`, repo)).code === 0;
|
|
@@ -42,3 +43,20 @@ export async function mergeTask(intWt, taskBranch, message, gatedCommit) {
|
|
|
42
43
|
await sh("git merge --abort", intWt);
|
|
43
44
|
return { ok: false, conflict };
|
|
44
45
|
}
|
|
46
|
+
// OBS-34: strict exit-code verify on the integration tip — no baseline forgiveness.
|
|
47
|
+
export async function verifyIntegrationTip(intWt, commands) {
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const [gate, cmd] of Object.entries(commands)) {
|
|
50
|
+
const r = await sh(cmd, intWt);
|
|
51
|
+
const raw = (r.stdout + "\n" + r.stderr).split(intWt).join("");
|
|
52
|
+
results.push({
|
|
53
|
+
gate,
|
|
54
|
+
cmd,
|
|
55
|
+
pass: r.code === 0,
|
|
56
|
+
exitCode: r.code,
|
|
57
|
+
fingerprints: r.code !== 0 ? fingerprint(raw) : [],
|
|
58
|
+
details: r.code === 0 ? "exit 0" : `exit ${r.code}`,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return results;
|
|
62
|
+
}
|
package/dist/run/reconcile.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { formatOwnedName, isForeignName, panesToClose, parseOwnedName } from "../drivers/types.js";
|
|
2
2
|
export { isForeignName, panesToClose, parseOwnedName };
|
|
3
|
-
// T1: pure fold over journal rows — the exact set of
|
|
3
|
+
// T1: pure fold over journal rows — the exact set of tickmarkr-owned pane/tab names that SHOULD exist
|
|
4
4
|
// right now for a live run. No I/O: the caller supplies rows (Journal.read()) and a live pane listing
|
|
5
5
|
// separately. Anything owned (parseOwnedName succeeds) but not in this set is garbage to close;
|
|
6
6
|
// anything foreign (parseOwnedName fails) is never a candidate, no matter what state it's in.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tickmarkr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"description": "Spec in, verified work out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"lint": "oxlint src tests scripts",
|
|
21
22
|
"test": "vitest run",
|
|
22
23
|
"test:coverage": "vitest run --coverage",
|
|
23
24
|
"schema": "tsx scripts/emit-schema.ts",
|
|
24
|
-
"e2e": "
|
|
25
|
+
"e2e": "TICKMARKR_E2E=1 vitest run tests/e2e --testTimeout 900000"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
28
|
"picomatch": "^4.0.2",
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
"@types/node": "^20.14.0",
|
|
33
34
|
"@types/picomatch": "^4.0.0",
|
|
34
35
|
"@vitest/coverage-v8": "^3.0.0",
|
|
36
|
+
"oxlint": "1.74.0",
|
|
35
37
|
"tsx": "^4.19.0",
|
|
36
38
|
"typescript": "^5.6.0",
|
|
37
39
|
"vitest": "^3.0.0"
|
|
@@ -36,6 +36,6 @@ Run every requested target in order without seeking routine confirmation. Stop o
|
|
|
36
36
|
2. **Compile** — run `tickmarkr compile <spec-or-directory>`. Fix source-spec defects instead of editing the generated graph.
|
|
37
37
|
3. **Plan** — run `tickmarkr plan`. Review routes, capability-floor warnings, and human gates before execution.
|
|
38
38
|
4. **Run** — run `tickmarkr run`. Watch the run journal for its terminal event rather than polling agents. Resolve blocked interactions in the relevant agent session.
|
|
39
|
-
5. **Verify and consolidate** — continue only after a green run. Tickmarkr consolidates accepted work on `tickmarkr/<runId>` and never signs off to the main branch. A human controls any later release merge.
|
|
39
|
+
5. **Verify and consolidate** — continue only after a green run. A run is green when the run-end event exists in the journal AND the tip verify is not "failed". Tickmarkr consolidates accepted work on `tickmarkr/<runId>` and never signs off to the main branch. A human controls any later release merge.
|
|
40
40
|
6. **Record** — write `tickmarkr report <runId> --md` beside the source spec and commit the execution record when the repository tracks those records.
|
|
41
41
|
7. **Continue** — move to the next requested target. If a target fails or is parked, stop with the journal evidence rather than silently skipping it.
|
|
@@ -35,5 +35,5 @@ Proceed through the loop without seeking routine confirmation. Stop only for a b
|
|
|
35
35
|
2. **Compile** — run `tickmarkr compile <spec>`. Correct compilation errors in the spec, never in the generated graph.
|
|
36
36
|
3. **Plan** — run `tickmarkr plan`. Review the routing table, capability-floor warnings, and every human gate, including work that each gate blocks.
|
|
37
37
|
4. **Run** — run `tickmarkr run`. Watch the run journal for its terminal event rather than repeatedly polling agents. Resolve blocked interactions in the agent session; do not turn them into proxy questions.
|
|
38
|
-
5. **Verify and consolidate** — accept only a green run. Tickmarkr consolidates accepted task work on `tickmarkr/<runId>`; it never signs off to the main branch. A human may later merge that integration branch through the repository's normal release process.
|
|
38
|
+
5. **Verify and consolidate** — accept only a green run. A run is green when the run-end event exists in the journal AND the tip verify is not "failed". Tickmarkr consolidates accepted task work on `tickmarkr/<runId>`; it never signs off to the main branch. A human may later merge that integration branch through the repository's normal release process.
|
|
39
39
|
6. **Record** — write `tickmarkr report <runId> --md` beside the source spec and commit the execution record when the repository tracks those records.
|