@inerrata-corporation/errata 2.0.2-dev.145 → 2.0.2-dev.151

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 +109 -10
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -49707,10 +49707,13 @@ init_src4();
49707
49707
  import { readFileSync as readFileSync10, writeFileSync as writeFileSync10 } from "node:fs";
49708
49708
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
49709
49709
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
49710
- var HANDLE_RE = /\[([a-z0-9][\w-]{0,40})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
49710
+ var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
49711
49711
  var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
49712
49712
  var CONSTRAINT_RE = /\(\s*constraint:\s*([^()\n]{8,}?)\s*\)/gi;
49713
49713
  var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
49714
+ var NEST2_UNIT = String.raw`(?:[^()\n]|\((?:[^()\n]|\([^()\n]*\))*\))`;
49715
+ var FIX_LONG_RE = new RegExp(String.raw`\(\s*fix:(?:#([a-z][\w-]{0,63}))?\s*(${NEST2_UNIT}{12,}?)\s*\)`, "gi");
49716
+ var CAUSE_LONG_RE = new RegExp(String.raw`\(\s*cause:(?:#([a-z][\w-]{0,63}))?\s*(${NEST2_UNIT}{8,}?)\s*\)`, "gi");
49714
49717
  var CAUSE_ARROW = /\s+(?:<-|←)\s+/;
49715
49718
  var ATTEMPT_RE = /\(\s*(tried|failed):(?:#([a-z][\w-]{0,63}))?\s*((?:[^()\n]|\([^()\n]*\)){8,}?)\s*\)/gi;
49716
49719
  var AIDS_PREFIX = /^\s*aids:(?:#([a-z][\w-]{0,63}))?\s*/i;
@@ -49723,7 +49726,7 @@ var DOMAIN_RE = /\(\s*domain:\s*([^()\n]{3,}?)\s*\)/gi;
49723
49726
  var PACKAGE_RE = /\(\s*package:\s*([^()\n]{2,}?)\s*\)/gi;
49724
49727
  var COMPONENT_RE = /\(\s*component:\s*([^()\n]{2,}?)\s*\)/gi;
49725
49728
  var CAUSE_TEXT_MIN = 8;
49726
- var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*([^\]\n]{8,}?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
49729
+ var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*((?:\[[^\]\n]*\]|[^\]\n]){8,}?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
49727
49730
  var CONSTRAINT_MIN = 8;
49728
49731
  function clauseBefore(sentence, idx) {
49729
49732
  const win = sentence.slice(Math.max(0, idx - 80), idx);
@@ -49738,6 +49741,17 @@ function fixRationaleBefore(sentence, idx) {
49738
49741
  const clause = m ? win.slice(m.index + 1) : win;
49739
49742
  return clause.replace(/\s+/g, " ").trim();
49740
49743
  }
49744
+ function fixRationaleAfter(sentence, endIdx) {
49745
+ const win = sentence.slice(endIdx, endIdx + FIX_RATIONALE_WINDOW).replace(new RegExp(CITE_GROUP_RE.source, "g"), " ").replace(new RegExp(FLAG_RE.source, "g"), " ");
49746
+ const stripped = win.replace(/^[\s—:–,-]+/, "");
49747
+ const m = /^[^.;!?—]*/.exec(stripped);
49748
+ return (m ? m[0] : stripped).replace(/\s+/g, " ").trim();
49749
+ }
49750
+ function deriveFixRationale(sentence, startIdx, endIdx) {
49751
+ const before = fixRationaleBefore(sentence, startIdx);
49752
+ if (before.length >= FIX_RATIONALE_MIN) return before;
49753
+ return fixRationaleAfter(sentence, endIdx);
49754
+ }
49741
49755
  function parseInlineTags(text) {
49742
49756
  const out2 = [];
49743
49757
  const deFenced = text.replace(/```[\s\S]*?```/g, " ");
@@ -49751,9 +49765,11 @@ function parseInlineTags(text) {
49751
49765
  (m) => /\[[!?]|\((?:fix|cause|constraint|tried|failed):|\(\[/.test(m) ? " " : m
49752
49766
  );
49753
49767
  const sfield = sentence.replace(/\s+/g, " ").trim().slice(0, 160);
49768
+ const citeMatched = /* @__PURE__ */ new Set();
49754
49769
  CITE_GROUP_RE.lastIndex = 0;
49755
49770
  let g;
49756
49771
  while ((g = CITE_GROUP_RE.exec(sentence)) !== null) {
49772
+ citeMatched.add(g.index);
49757
49773
  let content = g[1];
49758
49774
  if (/^\s*pattern:/i.test(content)) continue;
49759
49775
  const fixM = FIX_PREFIX.exec(content);
@@ -49807,7 +49823,7 @@ function parseInlineTags(text) {
49807
49823
  if (!isFix && NEG.test(clauseBefore(sentence, g.index))) continue;
49808
49824
  let fixRationale;
49809
49825
  if (isFix) {
49810
- const r = fixRationaleBefore(sentence, g.index);
49826
+ const r = deriveFixRationale(sentence, g.index, g.index + g[0].length);
49811
49827
  if (r.length >= FIX_RATIONALE_MIN) fixRationale = r;
49812
49828
  }
49813
49829
  HANDLE_RE.lastIndex = 0;
@@ -49832,6 +49848,55 @@ function parseInlineTags(text) {
49832
49848
  out2.push({ kind: "fix", fixRationale: note, sentence: sfield, ...verbThread ? { threadId: verbThread } : {} });
49833
49849
  }
49834
49850
  }
49851
+ for (const pass of [
49852
+ { re: FIX_LONG_RE, isFix: true },
49853
+ { re: CAUSE_LONG_RE, isFix: false }
49854
+ ]) {
49855
+ pass.re.lastIndex = 0;
49856
+ let lm;
49857
+ while ((lm = pass.re.exec(sentence)) !== null) {
49858
+ if (citeMatched.has(lm.index)) continue;
49859
+ const verbThread = lm[1] ?? void 0;
49860
+ const content = lm[2];
49861
+ HANDLE_RE.lastIndex = 0;
49862
+ const h = HANDLE_RE.exec(content);
49863
+ const handle2 = h ? h[1] ?? h[2] : void 0;
49864
+ if (!pass.isFix) {
49865
+ if (handle2) {
49866
+ out2.push({ kind: "triage", handle: handle2, sentence: sfield, ...verbThread ? { threadId: verbThread } : {} });
49867
+ } else {
49868
+ const causeText = content.replace(/\s+/g, " ").trim();
49869
+ if (causeText.length >= CAUSE_TEXT_MIN)
49870
+ out2.push({ kind: "triage", causeText, sentence: sfield, ...verbThread ? { threadId: verbThread } : {} });
49871
+ }
49872
+ continue;
49873
+ }
49874
+ if (handle2) {
49875
+ const inGroup = content.replace(new RegExp(HANDLE_RE.source, "gi"), " ").replace(/\s+/g, " ").trim();
49876
+ const r = inGroup.length >= FIX_RATIONALE_MIN ? inGroup : deriveFixRationale(sentence, lm.index, lm.index + lm[0].length);
49877
+ let emitted = false;
49878
+ HANDLE_RE.lastIndex = 0;
49879
+ let hh;
49880
+ while ((hh = HANDLE_RE.exec(content)) !== null) {
49881
+ const hcap = hh[1] ?? hh[2];
49882
+ if (hcap) {
49883
+ emitted = true;
49884
+ out2.push({
49885
+ kind: "fix",
49886
+ handle: hcap,
49887
+ sentence: sfield,
49888
+ ...r.length >= FIX_RATIONALE_MIN ? { fixRationale: r } : {},
49889
+ ...verbThread ? { threadId: verbThread } : {}
49890
+ });
49891
+ }
49892
+ }
49893
+ if (emitted) continue;
49894
+ }
49895
+ const note = content.replace(/\s+/g, " ").trim();
49896
+ if (note.length >= FIX_RATIONALE_MIN)
49897
+ out2.push({ kind: "fix", fixRationale: note, sentence: sfield, ...verbThread ? { threadId: verbThread } : {} });
49898
+ }
49899
+ }
49835
49900
  FLAG_RE.lastIndex = 0;
49836
49901
  let f;
49837
49902
  while ((f = FLAG_RE.exec(sentence)) !== null) {
@@ -51869,7 +51934,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
51869
51934
  }
51870
51935
 
51871
51936
  // src/engine.ts
51872
- var DAEMON_VERSION = true ? "2.0.2-dev.145" : "2.0.0-alpha.0";
51937
+ var DAEMON_VERSION = true ? "2.0.2-dev.151" : "2.0.0-alpha.0";
51873
51938
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
51874
51939
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
51875
51940
  var GIT_OP_MUTE_MS = 4e3;
@@ -54319,6 +54384,20 @@ async function startMultiDaemon(opts = {}) {
54319
54384
  let serverPending = null;
54320
54385
  const boundaryListeners = [];
54321
54386
  let boundaryFlushing = false;
54387
+ let boundaryFlushStartedAt = 0;
54388
+ let boundaryFlushStage = "";
54389
+ const beginFlush = (stage) => {
54390
+ boundaryFlushing = true;
54391
+ boundaryFlushStartedAt = Date.now();
54392
+ boundaryFlushStage = stage;
54393
+ };
54394
+ const flushStage = (stage) => {
54395
+ boundaryFlushStage = stage;
54396
+ };
54397
+ const endFlush = () => {
54398
+ boundaryFlushing = false;
54399
+ boundaryFlushStage = "";
54400
+ };
54322
54401
  const fireBoundary = () => {
54323
54402
  for (const l of boundaryListeners) {
54324
54403
  try {
@@ -55023,12 +55102,14 @@ async function startMultiDaemon(opts = {}) {
55023
55102
  },
55024
55103
  async sessionBoundaryFlush() {
55025
55104
  if (boundaryFlushing) return { uploaded: 0, written: 0, pruned: 0, skipped: "in-flight" };
55026
- boundaryFlushing = true;
55105
+ beginFlush("embed");
55027
55106
  try {
55028
55107
  for (const r of records) {
55029
55108
  await r.engine.embedSettled();
55030
55109
  }
55110
+ flushStage("instances");
55031
55111
  const inst = await daemon.syncInstancesPublic();
55112
+ flushStage("skills");
55032
55113
  const skills = await daemon.syncSkillsAll();
55033
55114
  return {
55034
55115
  uploaded: inst.uploaded,
@@ -55037,7 +55118,7 @@ async function startMultiDaemon(opts = {}) {
55037
55118
  ...inst.errors ? { errors: inst.errors } : {}
55038
55119
  };
55039
55120
  } finally {
55040
- boundaryFlushing = false;
55121
+ endFlush();
55041
55122
  }
55042
55123
  },
55043
55124
  onSessionBoundary(cb) {
@@ -55062,18 +55143,25 @@ async function startMultiDaemon(opts = {}) {
55062
55143
  }
55063
55144
  };
55064
55145
  app.post("/api/sync", async (c) => {
55065
- if (boundaryFlushing) return c.json({ skipped: "in-flight" }, 409);
55066
- boundaryFlushing = true;
55146
+ if (boundaryFlushing)
55147
+ return c.json(
55148
+ { skipped: "in-flight", stage: boundaryFlushStage, ageMs: Date.now() - boundaryFlushStartedAt },
55149
+ 409
55150
+ );
55151
+ beginFlush("principles");
55067
55152
  try {
55068
55153
  const principles = await daemon.syncPrinciplesPublic();
55154
+ flushStage("triage");
55069
55155
  const triage = await daemon.syncTriagePublic();
55156
+ flushStage("instances");
55070
55157
  const instances = await daemon.syncInstancesPublic();
55158
+ flushStage("edge-backfill");
55071
55159
  const edgeBackfill = await daemon.backfillCausalEdges();
55072
55160
  return c.json({ principles, triage, instances, edgeBackfill });
55073
55161
  } catch (err2) {
55074
55162
  return c.json({ error: err2 instanceof Error ? err2.message : String(err2) }, 500);
55075
55163
  } finally {
55076
- boundaryFlushing = false;
55164
+ endFlush();
55077
55165
  }
55078
55166
  });
55079
55167
  app.post("/api/tick", async (c) => {
@@ -57900,7 +57988,18 @@ async function cmdSync(arg) {
57900
57988
  signal: AbortSignal.timeout(15 * 6e4)
57901
57989
  });
57902
57990
  if (res.status === 409) {
57903
- console.log("sync already running: the daemon is mid-drain \u2014 it will finish on its own. Nothing new was started.");
57991
+ const body2 = await res.json().catch(() => null);
57992
+ const ageMs = typeof body2?.ageMs === "number" ? body2.ageMs : 0;
57993
+ const dur = ageMs >= 6e4 ? `${Math.floor(ageMs / 6e4)}m` : `${Math.max(1, Math.round(ageMs / 1e3))}s`;
57994
+ const stage = body2?.stage ? ` \u2014 stage: ${body2.stage}` : "";
57995
+ console.log(
57996
+ ageMs > 0 ? `sync already running: the daemon has been draining for ${dur}${stage}. It will finish on its own; nothing new was started.` : "sync already running: the daemon is mid-drain \u2014 it will finish on its own. Nothing new was started."
57997
+ );
57998
+ if (ageMs > 30 * 6e4) {
57999
+ console.log(
58000
+ " \u26A0 this pass has run past 30 min \u2014 if daemon.log shows no upload progress it may be stranded (a sleep/resume can do this). Restart with: errata stop && errata start"
58001
+ );
58002
+ }
57904
58003
  return;
57905
58004
  }
57906
58005
  if (!res.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.145",
3
+ "version": "2.0.2-dev.151",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {