@inerrata-corporation/errata 2.0.22-dev.4122 → 2.0.22-dev.4128

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 CHANGED
@@ -23829,6 +23829,7 @@ function parseIntentFences(text) {
23829
23829
  for (const line of lines) {
23830
23830
  const kv = /^\s*intent\s*:\s*(.+?)\s*$/i.exec(line);
23831
23831
  if (kv) parts2.push(kv[1].trim());
23832
+ else if (parts2.length > 0 && FIELD_LINE.test(line)) break;
23832
23833
  else if (parts2.length > 0 && line.trim()) parts2.push(line.trim());
23833
23834
  }
23834
23835
  const intent = parts2.join(" ").trim();
@@ -23843,6 +23844,7 @@ function parseShareFence(text) {
23843
23844
  for (const line of m[1].split(/\r?\n/)) {
23844
23845
  const kv = /^\s*priors\s*:\s*(.*?)\s*$/i.exec(line);
23845
23846
  if (kv) parts2.push(kv[1]);
23847
+ else if (parts2.length > 0 && FIELD_LINE.test(line)) break;
23846
23848
  else if (parts2.length > 0 && line.trim()) parts2.push(line.trim());
23847
23849
  }
23848
23850
  const value = parts2.join(" ").trim();
@@ -23910,12 +23912,13 @@ function recallableCorpus(store) {
23910
23912
  for (const id of cache2.keys()) if (!live3.has(id)) cache2.delete(id);
23911
23913
  return docs;
23912
23914
  }
23913
- var RECALLABLE, MIN_INTENT_TOKENS, DEFAULT_MIN_COVERAGE, RECALL_FILTER_KEYS, bagCache;
23915
+ var FIELD_LINE, RECALLABLE, MIN_INTENT_TOKENS, DEFAULT_MIN_COVERAGE, RECALL_FILTER_KEYS, bagCache;
23914
23916
  var init_intent = __esm({
23915
23917
  "../../packages/local-graph/src/intent.ts"() {
23916
23918
  "use strict";
23917
23919
  init_src();
23918
23920
  init_design_problem();
23921
+ FIELD_LINE = /^\s*[a-z][\w-]*\s*:(\s|$)/i;
23919
23922
  RECALLABLE = ["Problem", "Solution", "RootCause", "Pattern"];
23920
23923
  MIN_INTENT_TOKENS = 2;
23921
23924
  DEFAULT_MIN_COVERAGE = 0.2;
@@ -76390,6 +76393,109 @@ init_webui();
76390
76393
  init_config();
76391
76394
  init_lock();
76392
76395
 
76396
+ // src/activity-feed.ts
76397
+ var LABEL_MAX = 120;
76398
+ var DEFAULT_TAIL = 20;
76399
+ function oneLine(text) {
76400
+ const flat = text.replace(/\s+/g, " ").trim();
76401
+ if (flat.length <= LABEL_MAX) return flat;
76402
+ const points = Array.from(flat);
76403
+ return points.length > LABEL_MAX ? `${points.slice(0, LABEL_MAX - 1).join("")}\u2026` : flat;
76404
+ }
76405
+ var ActivityFeed = class {
76406
+ constructor(capacity = 500) {
76407
+ this.capacity = capacity;
76408
+ }
76409
+ events = [];
76410
+ seq = 0;
76411
+ // The engine harvests a turn twice by design (mid-turn + turn-final) and the
76412
+ // sync lanes can re-decide the same node; one tag must flash once.
76413
+ recentKeys = /* @__PURE__ */ new Map();
76414
+ record(input) {
76415
+ const label = oneLine(input.label);
76416
+ if (!label) return null;
76417
+ const key = input.dedupKey ?? `${input.kind}|${input.workspace ?? ""}|${input.tag ?? ""}|${label}`;
76418
+ if (this.recentKeys.has(key)) return null;
76419
+ const event = {
76420
+ seq: ++this.seq,
76421
+ kind: input.kind,
76422
+ at: input.at ?? Date.now(),
76423
+ label,
76424
+ ...input.workspace ? { workspace: input.workspace } : {},
76425
+ ...input.tag ? { tag: input.tag } : {}
76426
+ };
76427
+ this.events.push(event);
76428
+ this.recentKeys.set(key, event.seq);
76429
+ while (this.events.length > this.capacity) this.events.shift();
76430
+ if (this.recentKeys.size > this.capacity * 2) {
76431
+ const floor = this.events[0]?.seq ?? this.seq;
76432
+ for (const [k, s] of this.recentKeys) if (s < floor) this.recentKeys.delete(k);
76433
+ }
76434
+ return event;
76435
+ }
76436
+ since(seq) {
76437
+ const events = seq === void 0 || !Number.isFinite(seq) || seq > this.seq ? this.events.slice(-DEFAULT_TAIL) : this.events.filter((e) => e.seq > seq);
76438
+ return { seq: this.seq, events };
76439
+ }
76440
+ };
76441
+ var activityFeed = new ActivityFeed();
76442
+ function recordHarvest(feed, plan, ctx) {
76443
+ let n = 0;
76444
+ const put = (tag, label) => {
76445
+ if (!label) return;
76446
+ const ok = feed.record({
76447
+ kind: "captured",
76448
+ tag,
76449
+ label,
76450
+ ...ctx.workspace ? { workspace: ctx.workspace } : {},
76451
+ ...ctx.at !== void 0 ? { at: ctx.at } : {},
76452
+ dedupKey: `captured|${ctx.sessionId}|${tag}|${oneLine(label)}`
76453
+ });
76454
+ if (ok) n++;
76455
+ };
76456
+ for (const p of plan.problems) {
76457
+ const tag = p.kind === "vulnerability" ? p.assessment === "suspected" ? "?vuln" : "vuln" : p.kind === "problem" ? "!" : p.kind;
76458
+ put(tag, p.statement);
76459
+ }
76460
+ for (const f of plan.fixes) put("fix", f.fixNote ?? f.boundStatement ?? (f.problemId ? ctx.describe(f.problemId) : void 0));
76461
+ for (const r of plan.refutes) put("refute", ctx.describe(r.nodeId));
76462
+ for (const c of plan.corroborations) put("confirm", ctx.describe(c.nodeId));
76463
+ for (const a of plan.attempts) put(a.outcome, a.note);
76464
+ for (const t of plan.triages) put("cause", t.causeDescription ?? ctx.describe(t.causeId));
76465
+ return n;
76466
+ }
76467
+ var harvestFeedFailed = false;
76468
+ function recordHarvestSafely(...args2) {
76469
+ try {
76470
+ return recordHarvest(...args2);
76471
+ } catch (err2) {
76472
+ if (!harvestFeedFailed) {
76473
+ harvestFeedFailed = true;
76474
+ console.warn("[errata] activity feed record failed (capture unaffected):", err2 instanceof Error ? err2.message : err2);
76475
+ }
76476
+ return 0;
76477
+ }
76478
+ }
76479
+ function mountActivityRoute(app, feed) {
76480
+ app.get("/api/activity", (c) => {
76481
+ const raw2 = c.req.query("since");
76482
+ return c.json(feed.since(raw2 === void 0 || raw2 === "" ? void 0 : Number(raw2)));
76483
+ });
76484
+ }
76485
+ var KNOWLEDGE_LABELS2 = {
76486
+ Problem: "!",
76487
+ Solution: "fix",
76488
+ RootCause: "cause",
76489
+ Pattern: "pattern",
76490
+ Vulnerability: "vuln",
76491
+ Principle: "principle"
76492
+ };
76493
+ function knowledgeTag(label, attrs) {
76494
+ const tag = KNOWLEDGE_LABELS2[label];
76495
+ if (tag === "!" && typeof attrs["kind"] === "string" && attrs["kind"] !== "problem") return attrs["kind"];
76496
+ return tag;
76497
+ }
76498
+
76393
76499
  // src/engine.ts
76394
76500
  import { execFileSync as execFileSync5 } from "node:child_process";
76395
76501
  import { existsSync as existsSync28, statSync as statSync9, appendFileSync as appendFileSync4, readdirSync as readdirSync11, renameSync as renameSync4, readFileSync as readFileSync32, writeFileSync as writeFileSync23 } from "node:fs";
@@ -85062,7 +85168,7 @@ function createWatchBreaker(deps) {
85062
85168
  }
85063
85169
 
85064
85170
  // src/engine.ts
85065
- var DAEMON_VERSION = true ? "2.0.22-dev.4122" : "2.0.0-alpha.0";
85171
+ var DAEMON_VERSION = true ? "2.0.22-dev.4128" : "2.0.0-alpha.0";
85066
85172
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
85067
85173
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
85068
85174
  var GIT_OP_MUTE_MS = 4e3;
@@ -86289,6 +86395,11 @@ function createWorkspaceEngine(opts) {
86289
86395
  sessionId,
86290
86396
  ...touched.size > 0 ? { sessionTouchedIds: touched } : {}
86291
86397
  });
86398
+ recordHarvestSafely(activityFeed, plan, {
86399
+ workspace: profile.name,
86400
+ sessionId,
86401
+ describe: (id) => store.getNode(id)?.description
86402
+ });
86292
86403
  priorEdges += plan.priorEdges;
86293
86404
  corroboratedEdges += plan.corroboratedEdges;
86294
86405
  citeAnchorsAccrued += plan.citeAnchorsAccrued;
@@ -93764,8 +93875,19 @@ async function startMultiDaemon(opts = {}) {
93764
93875
  const localId = instances.contextNodeSources[decision.canonicalId] ?? decision.canonicalId;
93765
93876
  const owner = owningStore(localId);
93766
93877
  if (!sent || !owner || blocked.has(sent.id)) continue;
93767
- const attrs = acceptedInstanceReceipt(owner.n, sent, decision, destinationKey, owner.s === store) ?? withdrawnInstanceReceipt(owner.n, destinationKey, decision, (key) => store.getMeta?.(key) ?? sharedStore.getMeta?.(key), owner.s === store);
93878
+ const accepted = acceptedInstanceReceipt(owner.n, sent, decision, destinationKey, owner.s === store);
93879
+ const attrs = accepted ?? withdrawnInstanceReceipt(owner.n, destinationKey, decision, (key) => store.getMeta?.(key) ?? sharedStore.getMeta?.(key), owner.s === store);
93768
93880
  if (attrs) owner.s.updateNode(localId, { attrs });
93881
+ const tag = accepted ? knowledgeTag(owner.n.label, owner.n.attrs) : void 0;
93882
+ if (tag) {
93883
+ activityFeed.record({
93884
+ kind: "ingested",
93885
+ tag,
93886
+ label: owner.n.description,
93887
+ workspace: projectName,
93888
+ dedupKey: `ingested|${localId}|${owner.n.description}`
93889
+ });
93890
+ }
93769
93891
  }
93770
93892
  noteFlushProgress(p.accepted, p.nodeIds.length, `instances ${p.chunkIndex}/${p.totalChunks}`);
93771
93893
  }
@@ -93836,6 +93958,19 @@ async function startMultiDaemon(opts = {}) {
93836
93958
  };
93837
93959
  for (const id of blocked) noteRefused(id, "blocked-gzip", () => blockedRepeat++);
93838
93960
  for (const [id, why] of rejected) noteRefused(id, why, () => rejectedRepeat++);
93961
+ for (const { id, reason } of nowHeld) {
93962
+ const owner = owningStore(id);
93963
+ const tag = owner ? knowledgeTag(owner.n.label, owner.n.attrs) : void 0;
93964
+ if (owner && tag) {
93965
+ activityFeed.record({
93966
+ kind: "rejected",
93967
+ tag,
93968
+ label: `${owner.n.description} \u2014 ${reason}`,
93969
+ workspace: projectName,
93970
+ dedupKey: `rejected|${id}|${owner.n.description}`
93971
+ });
93972
+ }
93973
+ }
93839
93974
  if (nowHeld.length > 0) {
93840
93975
  console.warn(
93841
93976
  `[sync\u2192cloud] [${projectName}] instances: HOLDING ${nowHeld.length} node(s) \u2014 refused identically ${SHIP_TERMINAL_REFUSALS}\xD7 on unchanged text; not re-sent until the text changes: ` + nowHeld.map(({ id, reason }) => `${id} "${owningStore(id)?.n.description.slice(0, 60) ?? ""}": ${reason}`).join(" | ")
@@ -94097,6 +94232,7 @@ async function startMultiDaemon(opts = {}) {
94097
94232
  return c.json({ error: err2 instanceof Error ? err2.message : String(err2) }, 503);
94098
94233
  }
94099
94234
  });
94235
+ mountActivityRoute(app, activityFeed);
94100
94236
  app.post("/api/tick", async (c) => {
94101
94237
  try {
94102
94238
  return c.json({ reports: Object.fromEntries(await daemon.tickAll()) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.22-dev.4122",
3
+ "version": "2.0.22-dev.4128",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "errata-context",
3
- "version": "2.0.22-dev.4122",
3
+ "version": "2.0.22-dev.4128",
4
4
  "description": "A minimal 3D view of loaded Errata priors and recent graph bursts.",
5
5
  "author": {
6
6
  "name": "inErrata"
@@ -1,4 +1,4 @@
1
- 5ba58327da38d3a9b52ab2bc97c6999d2015ca1e410205e55f10e0e24a197693 .codex-plugin/plugin.json
1
+ 7df6ba4eca83c1c8e6b452e826aa8d4b6c59ed63ded7cf6267d007634a087605 .codex-plugin/plugin.json
2
2
  a7bebae9fb01c838d6c75fc784129e28be571233fa66ff5ee8039b574f35ccf7 assets/icon.png
3
3
  fc38b64e4df1e0b72c35764bef6c4c05430d97c9009ad0ecc8a9e75b4deab232 configure-local.mjs
4
4
  73dc6028b3b070257c7c31f252d11e55a9e096f4aed0f187f10cb21716e1e6d7 dist/client.js