@inerrata-corporation/errata 2.0.2-dev.1066 → 2.0.2-dev.1109
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/errata.mjs +228 -37
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -19166,7 +19166,8 @@ function ingestDesignProblem(store, flag, opts) {
|
|
|
19166
19166
|
designProblemId: problemId,
|
|
19167
19167
|
sources: [opts.source],
|
|
19168
19168
|
corroborations: 0,
|
|
19169
|
-
scope: {}
|
|
19169
|
+
scope: {},
|
|
19170
|
+
...opts.hostHarness ? { hostHarness: opts.hostHarness } : {}
|
|
19170
19171
|
})
|
|
19171
19172
|
);
|
|
19172
19173
|
}
|
|
@@ -53100,7 +53101,64 @@ function readAssistantTurnsFrom(transcriptPath, fromByte, includeThinking = true
|
|
|
53100
53101
|
losses: { parseFailures: parsed.parseFailures, ioFailed, bytesUnreachable: 0 }
|
|
53101
53102
|
};
|
|
53102
53103
|
}
|
|
53104
|
+
function detectHostHarness(raw2) {
|
|
53105
|
+
const lines = raw2.split(/\r?\n/);
|
|
53106
|
+
let checked = 0;
|
|
53107
|
+
for (const line of lines) {
|
|
53108
|
+
if (!line.trim()) continue;
|
|
53109
|
+
if (checked++ >= 5) break;
|
|
53110
|
+
let obj;
|
|
53111
|
+
try {
|
|
53112
|
+
obj = JSON.parse(line);
|
|
53113
|
+
} catch {
|
|
53114
|
+
continue;
|
|
53115
|
+
}
|
|
53116
|
+
if (obj.type === "response_item" || obj.type === "event_msg" || obj.type === "session_meta" || obj.type === "turn_context" || obj.type === "world_state") {
|
|
53117
|
+
return "codex";
|
|
53118
|
+
}
|
|
53119
|
+
if (obj.type === "user" || obj.type === "assistant" || obj.type === "summary") {
|
|
53120
|
+
return "claude_code";
|
|
53121
|
+
}
|
|
53122
|
+
}
|
|
53123
|
+
return "claude_code";
|
|
53124
|
+
}
|
|
53103
53125
|
function parseAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure = false) {
|
|
53126
|
+
if (!raw2) return { turns: [], parseFailures: 0 };
|
|
53127
|
+
return detectHostHarness(raw2) === "codex" ? parseCodexAssistantTurns(raw2, skipFirstLineParseFailure) : parseClaudeAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure);
|
|
53128
|
+
}
|
|
53129
|
+
function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false) {
|
|
53130
|
+
const turns = [];
|
|
53131
|
+
const lines = raw2.split(/\r?\n/);
|
|
53132
|
+
let parseFailures = 0;
|
|
53133
|
+
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
53134
|
+
const line = lines[i2];
|
|
53135
|
+
if (!line) continue;
|
|
53136
|
+
let obj;
|
|
53137
|
+
try {
|
|
53138
|
+
obj = JSON.parse(line);
|
|
53139
|
+
} catch {
|
|
53140
|
+
if (!(i2 === 0 && skipFirstLineParseFailure)) parseFailures++;
|
|
53141
|
+
continue;
|
|
53142
|
+
}
|
|
53143
|
+
if (obj.type !== "response_item") continue;
|
|
53144
|
+
const payload = obj.payload;
|
|
53145
|
+
if (!payload || payload["type"] !== "message" || payload["role"] !== "assistant") continue;
|
|
53146
|
+
const content = payload["content"];
|
|
53147
|
+
if (!Array.isArray(content)) continue;
|
|
53148
|
+
const parts2 = [];
|
|
53149
|
+
for (const b of content) {
|
|
53150
|
+
if (b["type"] === "output_text" && typeof b["text"] === "string") parts2.push(b["text"]);
|
|
53151
|
+
}
|
|
53152
|
+
if (parts2.length === 0) continue;
|
|
53153
|
+
turns.push({
|
|
53154
|
+
uuid: typeof payload["id"] === "string" ? payload["id"] : `codex-${i2}`,
|
|
53155
|
+
text: parts2.join("\n\n"),
|
|
53156
|
+
hostHarness: "codex"
|
|
53157
|
+
});
|
|
53158
|
+
}
|
|
53159
|
+
return { turns, parseFailures };
|
|
53160
|
+
}
|
|
53161
|
+
function parseClaudeAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure = false) {
|
|
53104
53162
|
if (!raw2) return { turns: [], parseFailures: 0 };
|
|
53105
53163
|
const turns = [];
|
|
53106
53164
|
const lines = raw2.split(/\r?\n/);
|
|
@@ -53154,6 +53212,7 @@ function parseAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure =
|
|
|
53154
53212
|
turns.push({
|
|
53155
53213
|
uuid: String(obj.uuid ?? i2),
|
|
53156
53214
|
text: parts2.join("\n\n"),
|
|
53215
|
+
hostHarness: "claude_code",
|
|
53157
53216
|
...lastFile ? { workingFile: lastFile } : {},
|
|
53158
53217
|
...provenance ? { workingFileProvenance: provenance } : {},
|
|
53159
53218
|
...editedFile && editedFileTurnSeq === turnSeq ? { editedFile } : {},
|
|
@@ -53221,6 +53280,91 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
|
|
|
53221
53280
|
refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
53222
53281
|
return refs;
|
|
53223
53282
|
}
|
|
53283
|
+
function codexSessionRoots(env2 = process.env, home = homedir4()) {
|
|
53284
|
+
const roots = /* @__PURE__ */ new Set();
|
|
53285
|
+
const explicit = env2["ERRATA_CODEX_SESSIONS_DIRS"];
|
|
53286
|
+
if (explicit) {
|
|
53287
|
+
for (const d of explicit.split(":")) if (d.trim()) roots.add(d.trim());
|
|
53288
|
+
}
|
|
53289
|
+
if (env2["CODEX_HOME"]) roots.add(join16(env2["CODEX_HOME"], "sessions"));
|
|
53290
|
+
roots.add(join16(home, ".codex", "sessions"));
|
|
53291
|
+
return [...roots];
|
|
53292
|
+
}
|
|
53293
|
+
function readCodexRolloutCwd(path2) {
|
|
53294
|
+
let fd;
|
|
53295
|
+
try {
|
|
53296
|
+
fd = openSync(path2, "r");
|
|
53297
|
+
const CAP = 1e6;
|
|
53298
|
+
const chunk = 65536;
|
|
53299
|
+
let acc = Buffer.alloc(0);
|
|
53300
|
+
let pos = 0;
|
|
53301
|
+
let nl = -1;
|
|
53302
|
+
while (acc.length < CAP) {
|
|
53303
|
+
const buf = Buffer.allocUnsafe(chunk);
|
|
53304
|
+
const n = readSync(fd, buf, 0, chunk, pos);
|
|
53305
|
+
if (n <= 0) break;
|
|
53306
|
+
acc = acc.length === 0 ? buf.subarray(0, n) : Buffer.concat([acc, buf.subarray(0, n)]);
|
|
53307
|
+
pos += n;
|
|
53308
|
+
nl = acc.indexOf(10);
|
|
53309
|
+
if (nl >= 0) break;
|
|
53310
|
+
}
|
|
53311
|
+
const firstLine = acc.toString("utf8", 0, nl >= 0 ? nl : acc.length);
|
|
53312
|
+
try {
|
|
53313
|
+
const o = JSON.parse(firstLine);
|
|
53314
|
+
const meta3 = o?.type === "session_meta" ? o.payload ?? o : o.payload ?? o;
|
|
53315
|
+
const cwd = meta3?.cwd ?? o?.cwd;
|
|
53316
|
+
if (typeof cwd === "string") return cwd;
|
|
53317
|
+
} catch {
|
|
53318
|
+
}
|
|
53319
|
+
const m = firstLine.match(/"cwd"\s*:\s*"((?:[^"\\]|\\.)*)"/);
|
|
53320
|
+
return m ? JSON.parse(`"${m[1]}"`) : null;
|
|
53321
|
+
} catch {
|
|
53322
|
+
return null;
|
|
53323
|
+
} finally {
|
|
53324
|
+
if (fd !== void 0) try {
|
|
53325
|
+
closeSync(fd);
|
|
53326
|
+
} catch {
|
|
53327
|
+
}
|
|
53328
|
+
}
|
|
53329
|
+
}
|
|
53330
|
+
function codexRolloutsForCwd(cwd, opts = {}) {
|
|
53331
|
+
const sinceMs = opts.sinceMs ?? 0;
|
|
53332
|
+
const limit = opts.limit ?? 25;
|
|
53333
|
+
const out2 = [];
|
|
53334
|
+
for (const root of codexSessionRoots(opts.env, opts.home)) {
|
|
53335
|
+
if (!existsSync13(root)) continue;
|
|
53336
|
+
const stack = [{ dir: root, depth: 0 }];
|
|
53337
|
+
while (stack.length > 0) {
|
|
53338
|
+
const { dir, depth } = stack.pop();
|
|
53339
|
+
let names;
|
|
53340
|
+
try {
|
|
53341
|
+
names = readdirSync6(dir);
|
|
53342
|
+
} catch {
|
|
53343
|
+
continue;
|
|
53344
|
+
}
|
|
53345
|
+
for (const name2 of names) {
|
|
53346
|
+
const full = join16(dir, name2);
|
|
53347
|
+
let st;
|
|
53348
|
+
try {
|
|
53349
|
+
st = statSync4(full);
|
|
53350
|
+
} catch {
|
|
53351
|
+
continue;
|
|
53352
|
+
}
|
|
53353
|
+
if (st.isDirectory()) {
|
|
53354
|
+
if (depth < 3) stack.push({ dir: full, depth: depth + 1 });
|
|
53355
|
+
continue;
|
|
53356
|
+
}
|
|
53357
|
+
if (depth < 3) continue;
|
|
53358
|
+
if (!name2.startsWith("rollout-") || !name2.endsWith(".jsonl")) continue;
|
|
53359
|
+
if (st.mtimeMs < sinceMs) continue;
|
|
53360
|
+
if (readCodexRolloutCwd(full) !== cwd) continue;
|
|
53361
|
+
out2.push({ path: full, sessionId: `codex:${basename3(name2, ".jsonl")}`, mtimeMs: st.mtimeMs });
|
|
53362
|
+
}
|
|
53363
|
+
}
|
|
53364
|
+
}
|
|
53365
|
+
out2.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
53366
|
+
return out2.slice(0, limit);
|
|
53367
|
+
}
|
|
53224
53368
|
|
|
53225
53369
|
// src/prior-tags.ts
|
|
53226
53370
|
init_src();
|
|
@@ -56442,13 +56586,14 @@ function createLivenessWatch(deps) {
|
|
|
56442
56586
|
}
|
|
56443
56587
|
|
|
56444
56588
|
// src/engine.ts
|
|
56445
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
56589
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.1109" : "2.0.0-alpha.0";
|
|
56446
56590
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
56447
56591
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
56448
56592
|
var GIT_OP_MUTE_MS = 4e3;
|
|
56449
56593
|
var REINDEX_DEBOUNCE_MS = 200;
|
|
56450
56594
|
var IDENTITY_AUDIT_MAX_BYTES = 16 * 1024 * 1024;
|
|
56451
56595
|
var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
56596
|
+
var CODEX_SWEEP_LOOKBACK_MS = 10 * 6e4;
|
|
56452
56597
|
function appendIdentityAudit(path2, record2, line) {
|
|
56453
56598
|
if (!record2.accepted && record2.score <= 0) return;
|
|
56454
56599
|
try {
|
|
@@ -57308,7 +57453,8 @@ function createWorkspaceEngine(opts) {
|
|
|
57308
57453
|
const r = ingestDesignProblem(store, flag, {
|
|
57309
57454
|
workspaceId: profile.id,
|
|
57310
57455
|
source: sessionId,
|
|
57311
|
-
ts: t
|
|
57456
|
+
ts: t,
|
|
57457
|
+
hostHarness: turn.hostHarness
|
|
57312
57458
|
});
|
|
57313
57459
|
if (r.created || r.corroborated) minted++;
|
|
57314
57460
|
else if (r.rejected) tagsRejected++;
|
|
@@ -57427,7 +57573,8 @@ function createWorkspaceEngine(opts) {
|
|
|
57427
57573
|
const r = ingestDesignProblem(store, { problem: p.statement, kind: p.kind }, {
|
|
57428
57574
|
workspaceId: profile.id,
|
|
57429
57575
|
source: sessionId,
|
|
57430
|
-
ts: t
|
|
57576
|
+
ts: t,
|
|
57577
|
+
hostHarness: turn.hostHarness
|
|
57431
57578
|
});
|
|
57432
57579
|
if (r.created || r.corroborated) {
|
|
57433
57580
|
minted++;
|
|
@@ -57965,10 +58112,35 @@ function createWorkspaceEngine(opts) {
|
|
|
57965
58112
|
await yieldToLoop();
|
|
57966
58113
|
await harvestSession(ref.sessionId, ref.path);
|
|
57967
58114
|
}
|
|
58115
|
+
const codexRefs = codexRolloutsForCwd(opts.workspaceRoot, {
|
|
58116
|
+
sinceMs: Date.now() - TURN_REPLAY_LOOKBACK_MS,
|
|
58117
|
+
limit: 25
|
|
58118
|
+
});
|
|
58119
|
+
for (const ref of codexRefs) {
|
|
58120
|
+
await yieldToLoop();
|
|
58121
|
+
await harvestSession(ref.sessionId, ref.path);
|
|
58122
|
+
}
|
|
57968
58123
|
} catch {
|
|
57969
58124
|
}
|
|
57970
58125
|
})();
|
|
57971
58126
|
});
|
|
58127
|
+
const sweepCodexRollouts = () => {
|
|
58128
|
+
setImmediate(() => {
|
|
58129
|
+
void (async () => {
|
|
58130
|
+
try {
|
|
58131
|
+
const refs = codexRolloutsForCwd(opts.workspaceRoot, {
|
|
58132
|
+
sinceMs: Date.now() - CODEX_SWEEP_LOOKBACK_MS,
|
|
58133
|
+
limit: 10
|
|
58134
|
+
});
|
|
58135
|
+
for (const ref of refs) {
|
|
58136
|
+
await yieldToLoop();
|
|
58137
|
+
await harvestSession(ref.sessionId, ref.path);
|
|
58138
|
+
}
|
|
58139
|
+
} catch {
|
|
58140
|
+
}
|
|
58141
|
+
})();
|
|
58142
|
+
});
|
|
58143
|
+
};
|
|
57972
58144
|
const designRollup = opts.designRollup ?? (process.env["ERRATA_ROLLUP"] === "1" ? haikuDesignRollup(process.env["ANTHROPIC_API_KEY"] ?? null) : void 0);
|
|
57973
58145
|
const onSessionEnd = (e) => {
|
|
57974
58146
|
if (!designRollup) return;
|
|
@@ -58107,6 +58279,7 @@ function createWorkspaceEngine(opts) {
|
|
|
58107
58279
|
refreshContextNow();
|
|
58108
58280
|
},
|
|
58109
58281
|
async tick() {
|
|
58282
|
+
sweepCodexRollouts();
|
|
58110
58283
|
maybeRefreshRemotePriors();
|
|
58111
58284
|
const report = {
|
|
58112
58285
|
generalizerEventsProcessed: 0,
|
|
@@ -61767,6 +61940,45 @@ function consolidationGapMs(lastPassMs, policy) {
|
|
|
61767
61940
|
return Math.max(policy.baseFloorMs, lastPassMs * policy.dutyFactor);
|
|
61768
61941
|
}
|
|
61769
61942
|
|
|
61943
|
+
// src/hook-commands.ts
|
|
61944
|
+
function hookCurlCommand(port, path2 = "/api/hook") {
|
|
61945
|
+
const url2 = `http://127.0.0.1:${port}${path2}`;
|
|
61946
|
+
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 3 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} >NUL 2>NUL || exit /b 0"` : `curl -s --connect-timeout 1 --max-time 3 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} >/dev/null 2>&1 || true`;
|
|
61947
|
+
}
|
|
61948
|
+
function hookRelayCommand(port, path2) {
|
|
61949
|
+
const url2 = `http://127.0.0.1:${port}${path2}`;
|
|
61950
|
+
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
|
|
61951
|
+
}
|
|
61952
|
+
var CODEX_HOOKS_BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
61953
|
+
var CODEX_HOOKS_END = `# <<< errata hooks`;
|
|
61954
|
+
function buildCodexHooksToml(port) {
|
|
61955
|
+
const cmd2 = hookCurlCommand(port).replace(/"/g, '\\"');
|
|
61956
|
+
const turnCmd = hookCurlCommand(port, "/api/turn").replace(/"/g, '\\"');
|
|
61957
|
+
return `${CODEX_HOOKS_BEGIN}
|
|
61958
|
+
[[hooks.PreToolUse]]
|
|
61959
|
+
matcher = ".*"
|
|
61960
|
+
|
|
61961
|
+
[[hooks.PreToolUse.hooks]]
|
|
61962
|
+
type = "command"
|
|
61963
|
+
command = "${cmd2}"
|
|
61964
|
+
timeout = 10
|
|
61965
|
+
|
|
61966
|
+
[[hooks.PostToolUse]]
|
|
61967
|
+
matcher = ".*"
|
|
61968
|
+
|
|
61969
|
+
[[hooks.PostToolUse.hooks]]
|
|
61970
|
+
type = "command"
|
|
61971
|
+
command = "${cmd2}"
|
|
61972
|
+
timeout = 10
|
|
61973
|
+
|
|
61974
|
+
[[hooks.PostToolUse.hooks]]
|
|
61975
|
+
type = "command"
|
|
61976
|
+
command = "${turnCmd}"
|
|
61977
|
+
timeout = 10
|
|
61978
|
+
${CODEX_HOOKS_END}
|
|
61979
|
+
`;
|
|
61980
|
+
}
|
|
61981
|
+
|
|
61770
61982
|
// src/cli.ts
|
|
61771
61983
|
var exitCleanOnEpipe = (err2) => {
|
|
61772
61984
|
if (err2.code === "EPIPE") process.exit(0);
|
|
@@ -63858,14 +64070,6 @@ function errataMcpInvocation() {
|
|
|
63858
64070
|
const { cmd: cmd2, args: args2 } = selfArgv("mcp");
|
|
63859
64071
|
return { command: cmd2, args: args2 };
|
|
63860
64072
|
}
|
|
63861
|
-
function hookCurlCommand(port, path2 = "/api/hook") {
|
|
63862
|
-
const url2 = `http://127.0.0.1:${port}${path2}`;
|
|
63863
|
-
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 3 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} >NUL 2>NUL || exit /b 0"` : `curl -s --connect-timeout 1 --max-time 3 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} >/dev/null 2>&1 || true`;
|
|
63864
|
-
}
|
|
63865
|
-
function hookRelayCommand(port, path2) {
|
|
63866
|
-
const url2 = `http://127.0.0.1:${port}${path2}`;
|
|
63867
|
-
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
|
|
63868
|
-
}
|
|
63869
64073
|
async function installClaudeHooks(port) {
|
|
63870
64074
|
const { mkdirSync: mkdirSync9, existsSync: existsSync31, readFileSync: readFileSync29, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
63871
64075
|
const { join: join33 } = await import("node:path");
|
|
@@ -63987,45 +64191,32 @@ async function installCodexHooks(port) {
|
|
|
63987
64191
|
const dir = join33(ROOT, ".codex");
|
|
63988
64192
|
if (!existsSync31(dir)) mkdirSync9(dir, { recursive: true });
|
|
63989
64193
|
const file2 = join33(dir, "config.toml");
|
|
63990
|
-
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
63991
|
-
const END = `# <<< errata hooks`;
|
|
63992
64194
|
let existing = "";
|
|
63993
64195
|
if (existsSync31(file2)) {
|
|
63994
64196
|
existing = readFileSync29(file2, "utf8");
|
|
63995
|
-
const beginIdx = existing.indexOf(
|
|
63996
|
-
const endIdx = existing.indexOf(
|
|
64197
|
+
const beginIdx = existing.indexOf(CODEX_HOOKS_BEGIN);
|
|
64198
|
+
const endIdx = existing.indexOf(CODEX_HOOKS_END);
|
|
63997
64199
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
63998
|
-
existing = existing.slice(0, beginIdx).trimEnd() + existing.slice(endIdx +
|
|
64200
|
+
existing = existing.slice(0, beginIdx).trimEnd() + existing.slice(endIdx + CODEX_HOOKS_END.length).trimStart();
|
|
63999
64201
|
}
|
|
64000
64202
|
}
|
|
64001
|
-
const
|
|
64002
|
-
const block = `${BEGIN}
|
|
64003
|
-
[[hooks.PreToolUse]]
|
|
64004
|
-
matcher = ".*"
|
|
64005
|
-
|
|
64006
|
-
[[hooks.PreToolUse.hooks]]
|
|
64007
|
-
type = "command"
|
|
64008
|
-
command = "${cmd2}"
|
|
64009
|
-
timeout = 10
|
|
64010
|
-
|
|
64011
|
-
[[hooks.PostToolUse]]
|
|
64012
|
-
matcher = ".*"
|
|
64013
|
-
|
|
64014
|
-
[[hooks.PostToolUse.hooks]]
|
|
64015
|
-
type = "command"
|
|
64016
|
-
command = "${cmd2}"
|
|
64017
|
-
timeout = 10
|
|
64018
|
-
${END}
|
|
64019
|
-
`;
|
|
64203
|
+
const block = buildCodexHooksToml(port);
|
|
64020
64204
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
64021
64205
|
|
|
64022
64206
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
64023
64207
|
writeFileSync23(file2, final, "utf8");
|
|
64024
64208
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
64025
|
-
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
64209
|
+
console.log(` endpoint: http://127.0.0.1:${port}/api/hook (+ /api/turn on PostToolUse)`);
|
|
64026
64210
|
console.log("");
|
|
64027
64211
|
console.log(` Codex reads files via the shell, so the virtual graph surface`);
|
|
64028
64212
|
console.log(` works by \`cat .errata/g/<verb>/<seed>\` (e.g. cat .errata/g/burst/foo).`);
|
|
64213
|
+
console.log("");
|
|
64214
|
+
console.log(` Codex has no Stop/SessionEnd hook at this installed version, so`);
|
|
64215
|
+
console.log(` [!\u2026]/(fix:[\u2026]) tags are harvested via the PostToolUse-triggered`);
|
|
64216
|
+
console.log(` /api/turn call above instead \u2014 every turn with a tool call is`);
|
|
64217
|
+
console.log(` covered; a tool-less final turn is picked up on this workspace's`);
|
|
64218
|
+
console.log(` next daemon boot replay. Re-run this after a Codex upgrade in`);
|
|
64219
|
+
console.log(` case a newer version adds a real turn-boundary hook.`);
|
|
64029
64220
|
console.log(` If [features] hooks=false in your config.toml, set it true. Hook`);
|
|
64030
64221
|
console.log(` schemas evolve \u2014 if hooks stop firing after an update, re-run this.`);
|
|
64031
64222
|
}
|