tickmarkr 1.71.0 → 1.73.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/dist/adapters/codex.js +13 -3
- package/dist/cli/commands/approve.js +21 -3
- package/dist/cli/commands/fleet.d.ts +2 -0
- package/dist/cli/commands/fleet.js +212 -449
- package/dist/cli/commands/resume.js +10 -2
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +219 -30
- package/dist/cli/commands/ui.d.ts +6 -2
- package/dist/cli/commands/ui.js +2 -4
- package/dist/config/config.d.ts +4 -0
- package/dist/config/config.js +6 -1
- package/dist/drivers/herdr.d.ts +6 -0
- package/dist/drivers/herdr.js +169 -71
- package/dist/drivers/subprocess.d.ts +3 -3
- package/dist/drivers/subprocess.js +10 -5
- package/dist/gates/acceptance.js +41 -17
- package/dist/route/preference.d.ts +2 -1
- package/dist/route/preference.js +8 -2
- package/dist/run/daemon.d.ts +1 -0
- package/dist/run/daemon.js +139 -4
- package/dist/run/git.d.ts +2 -0
- package/dist/run/git.js +55 -0
- package/dist/run/journal.d.ts +6 -1
- package/dist/run/journal.js +28 -1
- package/dist/tui/ink/components.d.ts +38 -0
- package/dist/tui/ink/components.js +42 -0
- package/dist/tui/ink/fleet-app.d.ts +113 -0
- package/dist/tui/ink/fleet-app.js +678 -0
- package/dist/tui/ink/studio-app.d.ts +59 -0
- package/dist/tui/ink/studio-app.js +320 -0
- package/package.json +4 -1
- package/dist/tui/app.d.ts +0 -72
- package/dist/tui/app.js +0 -334
- package/dist/tui/engine.d.ts +0 -52
- package/dist/tui/engine.js +0 -92
- package/dist/tui/frame.d.ts +0 -22
- package/dist/tui/frame.js +0 -56
- package/dist/tui/input.d.ts +0 -41
- package/dist/tui/input.js +0 -100
- package/dist/tui/views/consult-dossier.d.ts +0 -49
- package/dist/tui/views/consult-dossier.js +0 -169
- package/dist/tui/views/diff-modal.d.ts +0 -9
- package/dist/tui/views/diff-modal.js +0 -19
- package/dist/tui/views/fleet-view.d.ts +0 -91
- package/dist/tui/views/fleet-view.js +0 -337
- package/dist/tui/views/preview-view.d.ts +0 -7
- package/dist/tui/views/preview-view.js +0 -80
- package/dist/tui/views/profile-view.d.ts +0 -15
- package/dist/tui/views/profile-view.js +0 -93
- package/dist/tui/views/routing-view.d.ts +0 -48
- package/dist/tui/views/routing-view.js +0 -234
- package/dist/tui/views/runs-view.d.ts +0 -70
- package/dist/tui/views/runs-view.js +0 -387
package/dist/adapters/codex.js
CHANGED
|
@@ -80,6 +80,15 @@ export function readCodexModelsCache(path) {
|
|
|
80
80
|
// P87-08: "Unable to create …/.git/worktrees/…/index.lock"). Expanded by the pane shell at the
|
|
81
81
|
// worktree cwd; in a plain repo it resolves to ./.git (already writable, harmless).
|
|
82
82
|
const GITDIR_WRITABLE = `-c "sandbox_workspace_write.writable_roots=[\\"$(git rev-parse --path-format=absolute --git-common-dir)\\"]"`;
|
|
83
|
+
// OBS-125: codex 0.144.x gates enabled hooks behind PER-PROJECT-PATH hook trust — a NEW gate distinct
|
|
84
|
+
// from the directory trust seedCodexTrust seeds. Every worker runs in a fresh ephemeral worktree, an
|
|
85
|
+
// untrusted project, so codex re-prompts "Hooks need review" and the interactive worker stalls forever
|
|
86
|
+
// (run-20260722/23 incidents). This flag runs the operator's OWN already-trusted hooks — including the
|
|
87
|
+
// ~/.codex/hooks.json herdr-agent-state hook herdr relies on for agent detection, so the hooks can't
|
|
88
|
+
// just be disabled — WITHOUT requiring persisted per-path trust for this invocation. It KEEPS the
|
|
89
|
+
// -s/--sandbox workspace-write sandbox (deliberately NOT --dangerously-bypass-approvals-and-sandbox,
|
|
90
|
+
// which would drop the sandbox). Listed by `codex --help` and `codex exec --help` (verified 2026-07-23).
|
|
91
|
+
const CODEX_HOOK_TRUST = "--dangerously-bypass-hook-trust";
|
|
83
92
|
// v1.22 T5 / OBS-16: codex keys trust on absolute path under [projects."<root>"] trust_level="trusted"
|
|
84
93
|
// in ~/.codex/config.toml (CODEX_HOME relocates the dir). Worktrees inherit parent-project trust when
|
|
85
94
|
// the REPO ROOT is trusted — seed the root once, cover every future worktree. Idempotent: a second
|
|
@@ -171,14 +180,15 @@ export const codex = {
|
|
|
171
180
|
channels: (cfg) => channelsFromConfig("codex", cfg),
|
|
172
181
|
// v1.65 T3: every flag the command builders below hardcode (incl. codexMcpSuppressionFlags' -c/
|
|
173
182
|
// --disable and GITDIR_WRITABLE's -c) — all listed by top-level `codex --help`, verified 2026-07-22.
|
|
174
|
-
hardcodedFlags: { binary: "codex", flags: ["--sandbox", "--model", "-a", "-s", "-c", "--disable"] },
|
|
183
|
+
hardcodedFlags: { binary: "codex", flags: ["--sandbox", "--model", "-a", "-s", "-c", "--disable", "--dangerously-bypass-hook-trust"] },
|
|
175
184
|
// --sandbox workspace-write is the autonomous sandbox mode (codex v0.144.1+)
|
|
176
185
|
// MCP suppression built per dispatch (config can change between runs) — see codexMcpSuppressionFlags.
|
|
177
|
-
|
|
186
|
+
// CODEX_HOOK_TRUST (OBS-125) clears the per-worktree "Hooks need review" gate while keeping the sandbox.
|
|
187
|
+
headlessCommand: (promptFile, model) => `codex exec --sandbox workspace-write ${CODEX_HOOK_TRUST} ${codexMcpSuppressionFlags()} ${GITDIR_WRITABLE} --model ${shq(model)} "$(cat ${shq(promptFile)})"`,
|
|
178
188
|
// TUI uses expanded -a never -s workspace-write (exec-only flags do not apply)
|
|
179
189
|
// (--help 2026-07-09: valid approval policies are untrusted|on-request|never; the previously
|
|
180
190
|
// used `on-failure` is invalid and made codex exit 2 pre-inference)
|
|
181
|
-
interactiveCommand: (promptFile, model) => `codex -a never -s workspace-write ${codexMcpSuppressionFlags()} ${GITDIR_WRITABLE} --model ${shq(model)} "$(cat ${shq(promptFile)})"`,
|
|
191
|
+
interactiveCommand: (promptFile, model) => `codex -a never -s workspace-write ${CODEX_HOOK_TRUST} ${codexMcpSuppressionFlags()} ${GITDIR_WRITABLE} --model ${shq(model)} "$(cat ${shq(promptFile)})"`,
|
|
182
192
|
invoke(task, _cwd, a, ctx) {
|
|
183
193
|
return { command: this.headlessCommand(ctx.promptFile, a.model) };
|
|
184
194
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { userInfo } from "node:os";
|
|
2
|
-
import {
|
|
2
|
+
import { GATE_NAMES } from "../../graph/schema.js";
|
|
3
|
+
import { ATTEMPT_CAP_RELEASE, GATE_SATISFIED_RELEASE, Journal } from "../../run/journal.js";
|
|
3
4
|
// GATE-08 (v1.12): approve a parked human gate so the next `tickmarkr resume <runId>` dispatches it.
|
|
4
5
|
//
|
|
5
6
|
// The approval is a JOURNAL EVENT (task-approved) carrying who and when — it touches ONLY the
|
|
@@ -31,15 +32,32 @@ export async function approve(argv, cwd = process.cwd()) {
|
|
|
31
32
|
}
|
|
32
33
|
// OBS-18: only the most recent task-human for this task decides whether this approval grants a
|
|
33
34
|
// fresh attempt budget. The closed daemon-issued kind, never a human prose string, controls release.
|
|
34
|
-
const
|
|
35
|
+
const events = journal.read();
|
|
36
|
+
let lastHumanIndex = -1;
|
|
37
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
38
|
+
if (events[i].event === "task-human" && events[i].taskId === taskId) {
|
|
39
|
+
lastHumanIndex = i;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const lastHuman = events[lastHumanIndex];
|
|
35
44
|
const capPark = lastHuman?.data.kind === ATTEMPT_CAP_RELEASE;
|
|
45
|
+
const gateFailPark = lastHuman?.data.kind === "gate-fail";
|
|
46
|
+
const failedGate = gateFailPark
|
|
47
|
+
? events.slice(0, lastHumanIndex).reverse().find((e) => e.event === "gate-result" && e.taskId === taskId && e.data.pass === false
|
|
48
|
+
&& typeof e.data.gate === "string" && GATE_NAMES.includes(e.data.gate))?.data.gate
|
|
49
|
+
: undefined;
|
|
50
|
+
if (gateFailPark && !failedGate) {
|
|
51
|
+
throw new Error(`task ${taskId} is parked on gate-fail but has no failed gate result — refusing to infer one`);
|
|
52
|
+
}
|
|
36
53
|
journal.append("task-approved", taskId, {
|
|
37
54
|
by,
|
|
38
55
|
...(reason ? { reason } : {}),
|
|
39
56
|
via: "cli",
|
|
40
57
|
...(capPark ? { release: ATTEMPT_CAP_RELEASE } : {}),
|
|
58
|
+
...(failedGate ? { release: GATE_SATISFIED_RELEASE, gate: failedGate } : {}),
|
|
41
59
|
});
|
|
42
|
-
return `approved ${taskId} in ${runId} — by ${by}; run \`tickmarkr resume ${runId}\` to dispatch it`;
|
|
60
|
+
return `approved ${taskId} in ${runId} — by ${by}; run \`tickmarkr resume ${runId}\` to ${failedGate ? "continue past the approved gate" : "dispatch it"}`;
|
|
43
61
|
}
|
|
44
62
|
// hand-parsed argv — no CLI framework (house style). Flags --by <name> and --reason <text>; positionals
|
|
45
63
|
// are runId then taskId. Throws usage on missing positionals (mirrors resume.ts/unlock.ts).
|
|
@@ -12,6 +12,8 @@ export type FleetOutput = {
|
|
|
12
12
|
export type FleetIO = {
|
|
13
13
|
input?: FleetInput;
|
|
14
14
|
output?: FleetOutput;
|
|
15
|
+
debug?: boolean;
|
|
16
|
+
reloadGuard?: (bytes: string) => string | null;
|
|
15
17
|
};
|
|
16
18
|
export declare function fleet(argv: string[], cwd?: string, adapters?: WorkerAdapter[], io?: FleetIO): Promise<string | {
|
|
17
19
|
out: string;
|