@inerrata-corporation/errata 2.0.2-dev.1066 → 2.0.2-dev.1097

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.
Files changed (2) hide show
  1. package/errata.mjs +116 -37
  2. 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 } : {},
@@ -56442,7 +56501,7 @@ function createLivenessWatch(deps) {
56442
56501
  }
56443
56502
 
56444
56503
  // src/engine.ts
56445
- var DAEMON_VERSION = true ? "2.0.2-dev.1066" : "2.0.0-alpha.0";
56504
+ var DAEMON_VERSION = true ? "2.0.2-dev.1097" : "2.0.0-alpha.0";
56446
56505
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
56447
56506
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
56448
56507
  var GIT_OP_MUTE_MS = 4e3;
@@ -57308,7 +57367,8 @@ function createWorkspaceEngine(opts) {
57308
57367
  const r = ingestDesignProblem(store, flag, {
57309
57368
  workspaceId: profile.id,
57310
57369
  source: sessionId,
57311
- ts: t
57370
+ ts: t,
57371
+ hostHarness: turn.hostHarness
57312
57372
  });
57313
57373
  if (r.created || r.corroborated) minted++;
57314
57374
  else if (r.rejected) tagsRejected++;
@@ -57427,7 +57487,8 @@ function createWorkspaceEngine(opts) {
57427
57487
  const r = ingestDesignProblem(store, { problem: p.statement, kind: p.kind }, {
57428
57488
  workspaceId: profile.id,
57429
57489
  source: sessionId,
57430
- ts: t
57490
+ ts: t,
57491
+ hostHarness: turn.hostHarness
57431
57492
  });
57432
57493
  if (r.created || r.corroborated) {
57433
57494
  minted++;
@@ -61767,6 +61828,45 @@ function consolidationGapMs(lastPassMs, policy) {
61767
61828
  return Math.max(policy.baseFloorMs, lastPassMs * policy.dutyFactor);
61768
61829
  }
61769
61830
 
61831
+ // src/hook-commands.ts
61832
+ function hookCurlCommand(port, path2 = "/api/hook") {
61833
+ const url2 = `http://127.0.0.1:${port}${path2}`;
61834
+ 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`;
61835
+ }
61836
+ function hookRelayCommand(port, path2) {
61837
+ const url2 = `http://127.0.0.1:${port}${path2}`;
61838
+ 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 '{}'`;
61839
+ }
61840
+ var CODEX_HOOKS_BEGIN = `# >>> errata hooks (errata-managed)`;
61841
+ var CODEX_HOOKS_END = `# <<< errata hooks`;
61842
+ function buildCodexHooksToml(port) {
61843
+ const cmd2 = hookCurlCommand(port).replace(/"/g, '\\"');
61844
+ const turnCmd = hookCurlCommand(port, "/api/turn").replace(/"/g, '\\"');
61845
+ return `${CODEX_HOOKS_BEGIN}
61846
+ [[hooks.PreToolUse]]
61847
+ matcher = ".*"
61848
+
61849
+ [[hooks.PreToolUse.hooks]]
61850
+ type = "command"
61851
+ command = "${cmd2}"
61852
+ timeout = 10
61853
+
61854
+ [[hooks.PostToolUse]]
61855
+ matcher = ".*"
61856
+
61857
+ [[hooks.PostToolUse.hooks]]
61858
+ type = "command"
61859
+ command = "${cmd2}"
61860
+ timeout = 10
61861
+
61862
+ [[hooks.PostToolUse.hooks]]
61863
+ type = "command"
61864
+ command = "${turnCmd}"
61865
+ timeout = 10
61866
+ ${CODEX_HOOKS_END}
61867
+ `;
61868
+ }
61869
+
61770
61870
  // src/cli.ts
61771
61871
  var exitCleanOnEpipe = (err2) => {
61772
61872
  if (err2.code === "EPIPE") process.exit(0);
@@ -63858,14 +63958,6 @@ function errataMcpInvocation() {
63858
63958
  const { cmd: cmd2, args: args2 } = selfArgv("mcp");
63859
63959
  return { command: cmd2, args: args2 };
63860
63960
  }
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
63961
  async function installClaudeHooks(port) {
63870
63962
  const { mkdirSync: mkdirSync9, existsSync: existsSync31, readFileSync: readFileSync29, writeFileSync: writeFileSync23 } = await import("node:fs");
63871
63963
  const { join: join33 } = await import("node:path");
@@ -63987,45 +64079,32 @@ async function installCodexHooks(port) {
63987
64079
  const dir = join33(ROOT, ".codex");
63988
64080
  if (!existsSync31(dir)) mkdirSync9(dir, { recursive: true });
63989
64081
  const file2 = join33(dir, "config.toml");
63990
- const BEGIN = `# >>> errata hooks (errata-managed)`;
63991
- const END = `# <<< errata hooks`;
63992
64082
  let existing = "";
63993
64083
  if (existsSync31(file2)) {
63994
64084
  existing = readFileSync29(file2, "utf8");
63995
- const beginIdx = existing.indexOf(BEGIN);
63996
- const endIdx = existing.indexOf(END);
64085
+ const beginIdx = existing.indexOf(CODEX_HOOKS_BEGIN);
64086
+ const endIdx = existing.indexOf(CODEX_HOOKS_END);
63997
64087
  if (beginIdx >= 0 && endIdx > beginIdx) {
63998
- existing = existing.slice(0, beginIdx).trimEnd() + existing.slice(endIdx + END.length).trimStart();
64088
+ existing = existing.slice(0, beginIdx).trimEnd() + existing.slice(endIdx + CODEX_HOOKS_END.length).trimStart();
63999
64089
  }
64000
64090
  }
64001
- const cmd2 = hookCurlCommand(port).replace(/"/g, '\\"');
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
- `;
64091
+ const block = buildCodexHooksToml(port);
64020
64092
  const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
64021
64093
 
64022
64094
  ${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
64023
64095
  writeFileSync23(file2, final, "utf8");
64024
64096
  console.log(`installed Codex hooks \u2192 ${file2}`);
64025
- console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
64097
+ console.log(` endpoint: http://127.0.0.1:${port}/api/hook (+ /api/turn on PostToolUse)`);
64026
64098
  console.log("");
64027
64099
  console.log(` Codex reads files via the shell, so the virtual graph surface`);
64028
64100
  console.log(` works by \`cat .errata/g/<verb>/<seed>\` (e.g. cat .errata/g/burst/foo).`);
64101
+ console.log("");
64102
+ console.log(` Codex has no Stop/SessionEnd hook at this installed version, so`);
64103
+ console.log(` [!\u2026]/(fix:[\u2026]) tags are harvested via the PostToolUse-triggered`);
64104
+ console.log(` /api/turn call above instead \u2014 every turn with a tool call is`);
64105
+ console.log(` covered; a tool-less final turn is picked up on this workspace's`);
64106
+ console.log(` next daemon boot replay. Re-run this after a Codex upgrade in`);
64107
+ console.log(` case a newer version adds a real turn-boundary hook.`);
64029
64108
  console.log(` If [features] hooks=false in your config.toml, set it true. Hook`);
64030
64109
  console.log(` schemas evolve \u2014 if hooks stop firing after an update, re-run this.`);
64031
64110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.1066",
3
+ "version": "2.0.2-dev.1097",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {