@inerrata-corporation/errata 2.0.8-dev.2929 → 2.0.8-dev.2956

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 +51 -18
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -29506,6 +29506,18 @@ function resolveWorkspaceIdentity(cfg, entry, env2 = process.env) {
29506
29506
  function identityKey(id) {
29507
29507
  return id.profileName ?? "@default";
29508
29508
  }
29509
+ function publicWorkspaceIdentity(identity) {
29510
+ return {
29511
+ profileName: identity.profileName,
29512
+ rule: identity.rule,
29513
+ invalid: identity.invalid,
29514
+ reason: identity.reason,
29515
+ profile: identity.profile ? {
29516
+ installationId: identity.profile.installationId,
29517
+ cloudUrl: identity.profile.cloudUrl
29518
+ } : null
29519
+ };
29520
+ }
29509
29521
  function blockedCloudClient(reason) {
29510
29522
  return new Proxy(
29511
29523
  {},
@@ -74132,18 +74144,21 @@ function readTailWithLosses(path2, maxBytes) {
74132
74144
  try {
74133
74145
  fd = openSync(path2, "r");
74134
74146
  } catch {
74135
- return { text: "", bytesUnreachable: 0, ioFailed: true };
74147
+ return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true };
74136
74148
  }
74137
74149
  try {
74138
74150
  const size = fstatSync(fd).size;
74139
74151
  const start2 = Math.max(0, size - maxBytes);
74140
74152
  const len = size - start2;
74141
- if (len <= 0) return { text: "", bytesUnreachable: 0, ioFailed: false };
74153
+ if (len <= 0) return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: false };
74142
74154
  const buf = Buffer.allocUnsafe(len);
74143
74155
  readSync(fd, buf, 0, len, start2);
74144
- return { text: buf.toString("utf8"), bytesUnreachable: start2, ioFailed: false };
74156
+ const text = buf.toString("utf8");
74157
+ const firstNewline = buf.indexOf(10);
74158
+ const parseStartByte = firstNewline < 0 ? start2 : start2 + firstNewline + 1 - Buffer.byteLength(buf.subarray(0, firstNewline + 1).toString("utf8"));
74159
+ return { text, bytesUnreachable: start2, parseStartByte, ioFailed: false };
74145
74160
  } catch {
74146
- return { text: "", bytesUnreachable: 0, ioFailed: true };
74161
+ return { text: "", bytesUnreachable: 0, parseStartByte: 0, ioFailed: true };
74147
74162
  } finally {
74148
74163
  closeSync(fd);
74149
74164
  }
@@ -74207,7 +74222,7 @@ function isUserTurnBoundary(obj) {
74207
74222
  }
74208
74223
  function readAssistantTurnsWithLosses(transcriptPath, includeThinking = true, maxBytes = 2e6) {
74209
74224
  const tail = readTailWithLosses(transcriptPath, maxBytes);
74210
- const parsed = parseAssistantTurns(tail.text, includeThinking, false);
74225
+ const parsed = parseAssistantTurns(tail.text, includeThinking, false, tail.parseStartByte);
74211
74226
  return {
74212
74227
  turns: parsed.turns,
74213
74228
  losses: {
@@ -74219,7 +74234,8 @@ function readAssistantTurnsWithLosses(transcriptPath, includeThinking = true, ma
74219
74234
  }
74220
74235
  function readAssistantTurnsFrom(transcriptPath, fromByte, includeThinking = true, maxBytes) {
74221
74236
  const { text, nextOffset, more, ioFailed } = readFrom(transcriptPath, fromByte, maxBytes);
74222
- const parsed = parseAssistantTurns(text, includeThinking, fromByte > 0);
74237
+ const startByte = fromByte > 0 && fromByte <= nextOffset ? fromByte : 0;
74238
+ const parsed = parseAssistantTurns(text, includeThinking, fromByte > 0, startByte);
74223
74239
  return {
74224
74240
  turns: parsed.turns,
74225
74241
  nextOffset,
@@ -74255,10 +74271,10 @@ function detectHostHarness(raw2) {
74255
74271
  }
74256
74272
  return "claude_code";
74257
74273
  }
74258
- function parseAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure = false) {
74274
+ function parseAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure = false, startByte = 0) {
74259
74275
  if (!raw2) return { turns: [], parseFailures: 0 };
74260
74276
  const harness = detectHostHarness(raw2);
74261
- if (harness === "codex") return parseCodexAssistantTurns(raw2, skipFirstLineParseFailure);
74277
+ if (harness === "codex") return parseCodexAssistantTurns(raw2, skipFirstLineParseFailure, startByte);
74262
74278
  if (harness === "gemini") return parseGeminiAssistantTurns(raw2, skipFirstLineParseFailure);
74263
74279
  if (harness === "opencode") return parseOpencodeAssistantTurns(raw2, skipFirstLineParseFailure);
74264
74280
  return parseClaudeAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure);
@@ -74349,13 +74365,16 @@ function parseGeminiAssistantTurns(raw2, skipFirstLineParseFailure = false) {
74349
74365
  const turns = [...byId.entries()].sort((a, b) => a[1].order - b[1].order).map(([uuid3, v]) => ({ uuid: uuid3, text: v.text, hostHarness: "gemini" }));
74350
74366
  return { turns, parseFailures };
74351
74367
  }
74352
- function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false) {
74368
+ function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false, startByte = 0) {
74353
74369
  const turns = [];
74354
- const lines = raw2.split(/\r?\n/);
74370
+ const lines = raw2.split("\n");
74355
74371
  let parseFailures = 0;
74372
+ let nextByte = startByte;
74356
74373
  for (let i2 = 0; i2 < lines.length; i2++) {
74357
74374
  const line = lines[i2];
74358
- if (!line) continue;
74375
+ const lineByte = nextByte;
74376
+ nextByte += Buffer.byteLength(line ?? "", "utf8") + 1;
74377
+ if (!line?.trim()) continue;
74359
74378
  let obj;
74360
74379
  try {
74361
74380
  obj = JSON.parse(line);
@@ -74374,7 +74393,9 @@ function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false) {
74374
74393
  }
74375
74394
  if (parts2.length === 0) continue;
74376
74395
  turns.push({
74377
- uuid: typeof payload["id"] === "string" ? payload["id"] : `codex-${i2}`,
74396
+ // Slice-local line numbers repeat on every Stop. Position distinguishes
74397
+ // identical messages; the digest distinguishes a replaced row at that position.
74398
+ uuid: typeof payload["id"] === "string" && payload["id"].length > 0 ? payload["id"] : `codex-${lineByte}-${createHash14("sha256").update(line.trimEnd()).digest("hex")}`,
74378
74399
  text: parts2.join("\n\n"),
74379
74400
  hostHarness: "codex"
74380
74401
  });
@@ -80267,7 +80288,7 @@ function createWatchBreaker(deps) {
80267
80288
  }
80268
80289
 
80269
80290
  // src/engine.ts
80270
- var DAEMON_VERSION = true ? "2.0.8-dev.2929" : "2.0.0-alpha.0";
80291
+ var DAEMON_VERSION = true ? "2.0.8-dev.2956" : "2.0.0-alpha.0";
80271
80292
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
80272
80293
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
80273
80294
  var GIT_OP_MUTE_MS = 4e3;
@@ -86995,11 +87016,17 @@ async function startMultiDaemon(opts = {}) {
86995
87016
  const ANCHOR_PULL_INTERVAL_MS = 10 * 60 * 1e3;
86996
87017
  const anchorPullAll = async () => {
86997
87018
  const c = loadConfig();
86998
- if (!hasCloudCredential(c)) return;
86999
- const client = cloudNow();
87019
+ if (registryCorrupt()) return;
87000
87020
  for (const r of records) {
87001
87021
  const projectId = r.engine.profile.projectId;
87002
87022
  if (!projectId || !effectiveConsent(c, r.engine.profile).sync) continue;
87023
+ const identity = identityFor(liveWorkspaceEntry(r.entry));
87024
+ if (identity.invalid) {
87025
+ noteIdentityBlock(r.id, r.entry.name, identity);
87026
+ continue;
87027
+ }
87028
+ if (identity.rule !== "workspace-binding" && !hasCloudCredential(c)) continue;
87029
+ const client = cloudForIdentity(identity);
87003
87030
  try {
87004
87031
  const { salt } = await resolveProjectSymbolSalt(client, projectId);
87005
87032
  await pullProjectAnchors(r, client, salt);
@@ -87013,11 +87040,17 @@ async function startMultiDaemon(opts = {}) {
87013
87040
  }, ANCHOR_PULL_INTERVAL_MS);
87014
87041
  const ambientLinkAll = async () => {
87015
87042
  const c = loadConfig();
87016
- if (!hasCloudCredential(c)) return;
87017
- const client = cloudNow();
87043
+ if (registryCorrupt()) return;
87018
87044
  for (const r of records) {
87019
87045
  const working = loadProfile(r.root) ?? r.engine.profile;
87020
87046
  if (!effectiveConsent(c, working).sync) continue;
87047
+ const identity = identityFor(liveWorkspaceEntry(r.entry));
87048
+ if (identity.invalid) {
87049
+ noteIdentityBlock(r.id, r.entry.name, identity);
87050
+ continue;
87051
+ }
87052
+ if (identity.rule !== "workspace-binding" && !hasCloudCredential(c)) continue;
87053
+ const client = cloudForIdentity(identity);
87021
87054
  const out2 = await ensureProjectLink(r.root, working, client);
87022
87055
  if (working !== r.engine.profile) adoptLinkFields(r.engine.profile, working);
87023
87056
  if (out2.linked) {
@@ -89615,7 +89648,7 @@ async function cmdWhoami(args2) {
89615
89648
  `note: daemon capture and the MCP server resolve identically; a process with ERRATA_CONFIG_PATH set resolves by rule 1 regardless of binding.`
89616
89649
  ];
89617
89650
  if (args2.includes("--json")) {
89618
- console.log(JSON.stringify({ path: path2, registered: Boolean(entry), ...identity }, null, 2));
89651
+ console.log(JSON.stringify({ path: path2, registered: Boolean(entry), ...publicWorkspaceIdentity(identity) }, null, 2));
89619
89652
  } else {
89620
89653
  for (const l of lines) console.log(l);
89621
89654
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.8-dev.2929",
3
+ "version": "2.0.8-dev.2956",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {