@inerrata-corporation/errata 2.0.0-dev.25 → 2.0.0-dev.27

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 +117 -37
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -18827,7 +18827,41 @@ function communitySeeds(store, opts = {}) {
18827
18827
  }
18828
18828
  return seeds;
18829
18829
  }
18830
- var JOINT_COMMUNITY_LABELS, JOINT_COMMUNITY_EDGES, DEFAULT_MIN_COMMUNITY_SIZE;
18830
+ function communityInductionRequests(store, opts = {}) {
18831
+ const maxCommunities = opts.maxCommunities ?? 2;
18832
+ const byCommunity = /* @__PURE__ */ new Map();
18833
+ for (const label of JOINT_COMMUNITY_LABELS) {
18834
+ for (const n of store.findNodesByLabel(label)) {
18835
+ const cid = n.attrs["localCommunity"];
18836
+ if (typeof cid !== "string") continue;
18837
+ const cloudId = n.attrs["cloudNodeId"];
18838
+ const l = byCommunity.get(cid) ?? [];
18839
+ l.push({
18840
+ id: n.id,
18841
+ pulled: n.attrs["source"] === "cloud",
18842
+ cloudId: typeof cloudId === "string" && cloudId !== n.id ? cloudId : null,
18843
+ ts: n.lastUpdatedAt,
18844
+ description: n.description
18845
+ });
18846
+ byCommunity.set(cid, l);
18847
+ }
18848
+ }
18849
+ if (byCommunity.size === 0) return [];
18850
+ return [...byCommunity.entries()].map(([cid, mem]) => ({ cid, mem, fresh: Math.max(...mem.map((m) => m.ts)) })).sort((a, b) => b.fresh - a.fresh).map(({ cid, mem }) => {
18851
+ const ids = /* @__PURE__ */ new Set();
18852
+ for (const m of mem) {
18853
+ ids.add(m.id);
18854
+ if (m.cloudId) ids.add(m.cloudId);
18855
+ }
18856
+ const freshestLocal = [...mem].filter((m) => !m.pulled).sort((a, b) => b.ts - a.ts)[0];
18857
+ return {
18858
+ communityId: cid,
18859
+ members: [...ids].slice(0, 64),
18860
+ context: (freshestLocal?.description ?? "recurring workspace problem cluster").slice(0, 200)
18861
+ };
18862
+ }).filter((r) => r.members.length >= MIN_INDUCTION_MEMBERS).slice(0, maxCommunities);
18863
+ }
18864
+ var JOINT_COMMUNITY_LABELS, JOINT_COMMUNITY_EDGES, DEFAULT_MIN_COMMUNITY_SIZE, MIN_INDUCTION_MEMBERS;
18831
18865
  var init_community2 = __esm({
18832
18866
  "../../packages/local-graph/src/community.ts"() {
18833
18867
  "use strict";
@@ -18853,6 +18887,7 @@ var init_community2 = __esm({
18853
18887
  "RELATES_TO"
18854
18888
  ];
18855
18889
  DEFAULT_MIN_COMMUNITY_SIZE = 2;
18890
+ MIN_INDUCTION_MEMBERS = 3;
18856
18891
  }
18857
18892
  });
18858
18893
 
@@ -19496,6 +19531,7 @@ __export(src_exports, {
19496
19531
  causalChain: () => causalChain,
19497
19532
  claimId: () => claimId,
19498
19533
  clearRevisit: () => clearRevisit,
19534
+ communityInductionRequests: () => communityInductionRequests,
19499
19535
  communitySeeds: () => communitySeeds,
19500
19536
  compareSemver: () => compareSemver,
19501
19537
  corroborateClaim: () => corroborateClaim,
@@ -20344,6 +20380,13 @@ var init_client = __esm({
20344
20380
  if (seed && seed.length > 0) qs.set("seed", seed.join(","));
20345
20381
  return this.json("GET", `/v2/skills?${qs.toString()}`);
20346
20382
  }
20383
+ /** CL-induce: request a skill for a locally-detected community's cloud-
20384
+ * resolvable member ids. AUTHED. Always HTTP 200 — the `status` field
20385
+ * discriminates outcomes (incl. the autophagy-floor refusal, which is a
20386
+ * normal "not enough collective grounding yet" result, not an error). */
20387
+ async induceSkill(body2) {
20388
+ return this.json("POST", "/v2/skills/induce", body2);
20389
+ }
20347
20390
  /** Dependency-spine neighborhood. Accepts purls (Package canonicalId = purl)
20348
20391
  * or bare name@version slugs. A miss 404s AND registers demand (Stream B). */
20349
20392
  async packages(purlOrSlug, limit) {
@@ -20585,7 +20628,7 @@ import { randomUUID as randomUUID2 } from "node:crypto";
20585
20628
  function defaultConfig() {
20586
20629
  return {
20587
20630
  version: 1,
20588
- cloudUrl: process.env["ERRATA_CLOUD_URL"] ?? "http://localhost:8787",
20631
+ cloudUrl: process.env["ERRATA_CLOUD_URL"] ?? DEFAULT_CLOUD_URL,
20589
20632
  apiKey: null,
20590
20633
  accessToken: null,
20591
20634
  refreshToken: null,
@@ -20631,10 +20674,12 @@ function machineId() {
20631
20674
  saveConfig({ ...cfg, machineId: id });
20632
20675
  return id;
20633
20676
  }
20677
+ var DEFAULT_CLOUD_URL;
20634
20678
  var init_config = __esm({
20635
20679
  "src/config.ts"() {
20636
20680
  "use strict";
20637
20681
  init_paths();
20682
+ DEFAULT_CLOUD_URL = "https://inerrata-gateway.onrender.com";
20638
20683
  }
20639
20684
  });
20640
20685
 
@@ -20708,7 +20753,7 @@ function assertDeviceCodeEndpointAllowed(url2, inspection) {
20708
20753
  allowed: false,
20709
20754
  label: "gateway device-code blocked",
20710
20755
  reason: "device-code login mints legacy v1 keys, while gateway launch uses console-issued keys/JWTs",
20711
- guidance: "Use `errata login --token <console errk_...>` or `errata login --oauth`."
20756
+ guidance: "Use `errata login` for OAuth or `errata login --token <console errk_...>`."
20712
20757
  };
20713
20758
  throw new CloudEndpointPolicyError(formatCloudEndpointBlock(url2, decision), decision);
20714
20759
  }
@@ -20852,6 +20897,7 @@ function authedCloudClient(cfg, opts = {}) {
20852
20897
  accessToken: cfg.accessToken,
20853
20898
  ...cfg.refreshToken ? { refreshToken: cfg.refreshToken } : {},
20854
20899
  fetchFn,
20900
+ ...opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {},
20855
20901
  ...tokenEndpoint && cfg.refreshToken ? {
20856
20902
  refreshFn: (rt) => refreshAccessToken(opts.fetchFn ?? fetch, tokenEndpoint, {
20857
20903
  refreshToken: rt,
@@ -20870,9 +20916,13 @@ function authedCloudClient(cfg, opts = {}) {
20870
20916
  return new CloudClient({
20871
20917
  baseUrl,
20872
20918
  ...cfg.apiKey ? { apiKey: cfg.apiKey } : {},
20873
- fetchFn
20919
+ fetchFn,
20920
+ ...opts.timeoutMs ? { timeoutMs: opts.timeoutMs } : {}
20874
20921
  });
20875
20922
  }
20923
+ function hasCloudCredential(cfg) {
20924
+ return Boolean(cfg.accessToken || cfg.apiKey);
20925
+ }
20876
20926
  var init_cloud_auth = __esm({
20877
20927
  "src/cloud-auth.ts"() {
20878
20928
  "use strict";
@@ -34439,7 +34489,7 @@ function createMcpHandler(store, ctx = {}) {
34439
34489
  function buildToolContext() {
34440
34490
  try {
34441
34491
  const cfg = loadConfig();
34442
- if (cfg.consent.sync && cfg.apiKey && cfg.cloudUrl) {
34492
+ if (cfg.consent.sync && hasCloudCredential(cfg) && cfg.cloudUrl) {
34443
34493
  return { cloud: authedCloudClient(cfg) };
34444
34494
  }
34445
34495
  } catch {
@@ -40815,11 +40865,11 @@ var TelemetryRecorder = class {
40815
40865
  return out2;
40816
40866
  }
40817
40867
  /**
40818
- * Flush to the cloud iff consent + apiKey are present. Returns how many were
40868
+ * Flush to the cloud iff consent + a cloud credential are present. Returns how many were
40819
40869
  * accepted (0 when skipped). On network failure the batch is re-queued.
40820
40870
  */
40821
40871
  async flush(cloud, opts) {
40822
- if (!opts.consent || !opts.apiKey) {
40872
+ if (!opts.consent || !opts.credentialPresent) {
40823
40873
  this.drain();
40824
40874
  return { sent: 0, skipped: true };
40825
40875
  }
@@ -41113,6 +41163,7 @@ function autodetectProfile(root) {
41113
41163
 
41114
41164
  // src/engine.ts
41115
41165
  init_config();
41166
+ init_cloud_auth();
41116
41167
 
41117
41168
  // src/notify.ts
41118
41169
  init_config();
@@ -41231,7 +41282,7 @@ function maybeFlushDigests() {
41231
41282
  }
41232
41283
 
41233
41284
  // src/engine.ts
41234
- var DAEMON_VERSION = true ? "2.0.0-dev.25" : "2.0.0-alpha.0";
41285
+ var DAEMON_VERSION = true ? "2.0.0-dev.27" : "2.0.0-alpha.0";
41235
41286
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
41236
41287
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
41237
41288
  var GIT_OP_MUTE_MS = 4e3;
@@ -42036,7 +42087,19 @@ function createWorkspaceEngine(opts) {
42036
42087
  }
42037
42088
  });
42038
42089
  }
42039
- const pullSkills = () => {
42090
+ const pullSkills = async () => {
42091
+ if ((opts.syncConsent ?? loadConfig().consent.sync) === true) {
42092
+ for (const req of communityInductionRequests(store)) {
42093
+ try {
42094
+ const r = await cloud.induceSkill({ members: req.members, context: req.context });
42095
+ if (r.status === "induced" || r.status === "refreshed") {
42096
+ console.log(`[errata] skill ${r.status} for community ${req.communityId}: ${r.title ?? r.skillId}`);
42097
+ }
42098
+ } catch {
42099
+ break;
42100
+ }
42101
+ }
42102
+ }
42040
42103
  const communitySeed = communitySeeds(store);
42041
42104
  const skillSeed = communitySeed.length > 0 ? communitySeed : store.findNodesByLabel("Problem").sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, 6).flatMap((p) => {
42042
42105
  const cloudId = p.attrs["cloudNodeId"];
@@ -42222,7 +42285,7 @@ function createWorkspaceEngine(opts) {
42222
42285
  }
42223
42286
  const t = await telemetry.flush(cloud, {
42224
42287
  consent: freshCfg.consent.telemetry,
42225
- apiKey: opts.apiKey ?? freshCfg.apiKey
42288
+ credentialPresent: Boolean(opts.apiKey) || hasCloudCredential(freshCfg)
42226
42289
  });
42227
42290
  if (t.sent > 0) {
42228
42291
  console.log(`[errata] telemetry: ${t.sent} events sent`);
@@ -42259,6 +42322,8 @@ async function startDaemon(opts) {
42259
42322
  if (opts.apiKey) {
42260
42323
  merged.apiKey = opts.apiKey;
42261
42324
  merged.accessToken = null;
42325
+ merged.refreshToken = null;
42326
+ merged.tokenEndpoint = null;
42262
42327
  }
42263
42328
  const cloud = authedCloudClient(merged);
42264
42329
  let webUiUrl = "";
@@ -42408,7 +42473,6 @@ function pidAlive(pid) {
42408
42473
 
42409
42474
  // src/multi.ts
42410
42475
  init_dist();
42411
- init_src6();
42412
42476
  init_src4();
42413
42477
  import { readFileSync as readFileSync17, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "node:fs";
42414
42478
 
@@ -43009,6 +43073,7 @@ function isDaemonAlive(lockPath) {
43009
43073
  // src/multi.ts
43010
43074
  init_config();
43011
43075
  init_cloud_endpoint_policy();
43076
+ init_cloud_auth();
43012
43077
  function normPath(p) {
43013
43078
  return p.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
43014
43079
  }
@@ -43043,21 +43108,25 @@ async function startMultiDaemon(opts = {}) {
43043
43108
  const cfg = loadConfig();
43044
43109
  const CLOUD_TIMEOUT_MS = 12e4;
43045
43110
  const initialCloudUrl = normalizeCloudUrl(opts.cloudUrl ?? cfg.cloudUrl);
43046
- const cloud = new CloudClient({
43047
- baseUrl: initialCloudUrl,
43048
- timeoutMs: CLOUD_TIMEOUT_MS,
43049
- fetchFn: guardCloudFetch(initialCloudUrl),
43050
- ...opts.apiKey ?? cfg.apiKey ? { apiKey: opts.apiKey ?? cfg.apiKey ?? void 0 } : {}
43051
- });
43111
+ const initialCfg = { ...cfg, cloudUrl: initialCloudUrl };
43112
+ if (opts.apiKey) {
43113
+ initialCfg.apiKey = opts.apiKey;
43114
+ initialCfg.accessToken = null;
43115
+ initialCfg.refreshToken = null;
43116
+ initialCfg.tokenEndpoint = null;
43117
+ }
43118
+ const cloud = authedCloudClient(initialCfg, { timeoutMs: CLOUD_TIMEOUT_MS });
43052
43119
  const cloudNow = () => {
43053
43120
  const c = loadConfig();
43054
43121
  const baseUrl2 = normalizeCloudUrl(opts.cloudUrl ?? c.cloudUrl);
43055
- return new CloudClient({
43056
- baseUrl: baseUrl2,
43057
- timeoutMs: CLOUD_TIMEOUT_MS,
43058
- fetchFn: guardCloudFetch(baseUrl2),
43059
- ...opts.apiKey ?? c.apiKey ? { apiKey: opts.apiKey ?? c.apiKey ?? void 0 } : {}
43060
- });
43122
+ const current = { ...c, cloudUrl: baseUrl2 };
43123
+ if (opts.apiKey) {
43124
+ current.apiKey = opts.apiKey;
43125
+ current.accessToken = null;
43126
+ current.refreshToken = null;
43127
+ current.tokenEndpoint = null;
43128
+ }
43129
+ return authedCloudClient(current, { timeoutMs: CLOUD_TIMEOUT_MS });
43061
43130
  };
43062
43131
  const sharedDbPath = sharedStorePath();
43063
43132
  ensureParent(sharedDbPath);
@@ -43758,7 +43827,7 @@ async function loginOAuthLoopback(opts) {
43758
43827
  if (opts.timeoutMs) {
43759
43828
  setTimeout(() => {
43760
43829
  server.close();
43761
- reject(new Error("login timed out \u2014 run `errata login --oauth` again"));
43830
+ reject(new Error("login timed out \u2014 run `errata login` again"));
43762
43831
  }, opts.timeoutMs).unref?.();
43763
43832
  }
43764
43833
  }
@@ -44032,8 +44101,8 @@ Commands:
44032
44101
  Flags: --port N (default 7891)
44033
44102
  mcp Run the MCP stdio server \u2014 the agent's full errata tool
44034
44103
  surface (navigation, problems, claims, burst, health)
44035
- login Register or sign in with the cloud
44036
- logout Clear local API key
44104
+ login Sign in with the cloud (OAuth by default; --device for legacy)
44105
+ logout Clear local cloud credentials
44037
44106
  sync now Flush outbox to the cloud once
44038
44107
  privacy Show what is collected/scrubbed + your consent state
44039
44108
  consent <channel> <on|off>
@@ -44045,7 +44114,7 @@ Commands:
44045
44114
  Desktop toasts on problem open/resolve + review ready
44046
44115
 
44047
44116
  Environment:
44048
- ERRATA_CLOUD_URL Cloud base URL (default http://localhost:8787)
44117
+ ERRATA_CLOUD_URL Cloud base URL (default ${DEFAULT_CLOUD_URL})
44049
44118
  ERRATA_ALLOW_DIRECT_V1_CLOUD=1 Allow non-local legacy v1 cloud testing
44050
44119
  `);
44051
44120
  }
@@ -44133,7 +44202,7 @@ async function cmdInit() {
44133
44202
  console.log("");
44134
44203
  console.log("Next:");
44135
44204
  console.log(" errata start # observe this repo");
44136
- if (!cfgNow.apiKey) {
44205
+ if (!hasCloudCredential(cfgNow)) {
44137
44206
  console.log(" errata login # connect a cloud account (or: --token <key>)");
44138
44207
  }
44139
44208
  if (!cfgNow.consent.sync) {
@@ -44233,7 +44302,7 @@ async function cmdStatus() {
44233
44302
  );
44234
44303
  console.log(` cloud:`);
44235
44304
  console.log(` url: ${cfg.cloudUrl}`);
44236
- console.log(` logged in: ${cfg.apiKey || cfg.accessToken ? `yes (${cfg.email})` : "no"}`);
44305
+ console.log(` logged in: ${hasCloudCredential(cfg) ? `yes (${cfg.email})` : "no"}`);
44237
44306
  const inspection = await inspectCloudEndpoint(cfg.cloudUrl);
44238
44307
  const decision = evaluateCloudEndpoint(cfg.cloudUrl, inspection);
44239
44308
  const service = inspection.service ? ` \xB7 service ${inspection.service}` : "";
@@ -44242,7 +44311,7 @@ async function cmdStatus() {
44242
44311
  console.log(` policy: blocked - ${decision.reason}`);
44243
44312
  if (decision.guidance) console.log(` ${decision.guidance}`);
44244
44313
  }
44245
- if (cfg.apiKey || cfg.accessToken) {
44314
+ if (hasCloudCredential(cfg)) {
44246
44315
  if (!decision.allowed) {
44247
44316
  console.log(
44248
44317
  ` reachable: ${inspection.reachable ? `yes (${inspection.probe})` : `no (${inspection.error ?? "unreachable"})`}`
@@ -44326,6 +44395,7 @@ function parseFlags(args2) {
44326
44395
  else if (a === "--token") out2.token = args2[++i2];
44327
44396
  else if (a.startsWith("--token=")) out2.token = a.slice("--token=".length);
44328
44397
  else if (a === "--oauth") out2.oauth = true;
44398
+ else if (a === "--device") out2.device = true;
44329
44399
  else if (!a.startsWith("--")) out2._.push(a);
44330
44400
  }
44331
44401
  return out2;
@@ -44351,6 +44421,9 @@ async function applyToken(cfg, token) {
44351
44421
  try {
44352
44422
  const me = await c.me();
44353
44423
  cfg.apiKey = token;
44424
+ cfg.accessToken = null;
44425
+ cfg.refreshToken = null;
44426
+ cfg.tokenEndpoint = null;
44354
44427
  cfg.userId = me.agentId;
44355
44428
  cfg.email = me.handle;
44356
44429
  saveConfig(cfg);
@@ -44387,7 +44460,7 @@ async function cmdLoginOAuth(cfg) {
44387
44460
  result = await loginOAuthLoopback({ cloudUrl: cfg.cloudUrl, timeoutMs: 5 * 6e4 });
44388
44461
  } catch (err2) {
44389
44462
  console.error(`oauth login failed: ${err2 instanceof Error ? err2.message : err2}`);
44390
- console.error(` fall back to device code: errata login`);
44463
+ console.error(` fall back to device code: errata login --device`);
44391
44464
  console.error(` or paste a key: errata login --token <key>`);
44392
44465
  process.exitCode = 1;
44393
44466
  return;
@@ -44395,6 +44468,7 @@ async function cmdLoginOAuth(cfg) {
44395
44468
  cfg.accessToken = result.tokens.accessToken;
44396
44469
  cfg.refreshToken = result.tokens.refreshToken ?? null;
44397
44470
  cfg.tokenEndpoint = result.tokenEndpoint;
44471
+ cfg.apiKey = null;
44398
44472
  saveConfig(cfg);
44399
44473
  try {
44400
44474
  const me = await authedCloudClient(cfg).me();
@@ -44414,7 +44488,7 @@ async function cmdLogin() {
44414
44488
  await applyToken(cfg, flags2.token);
44415
44489
  return;
44416
44490
  }
44417
- if (flags2.oauth) {
44491
+ if (flags2.oauth || !flags2.device) {
44418
44492
  await cmdLoginOAuth(cfg);
44419
44493
  return;
44420
44494
  }
@@ -44462,6 +44536,9 @@ async function cmdLogin() {
44462
44536
  if (poll.status === "pending") continue;
44463
44537
  if (poll.status === "authorized" && poll.apiKey) {
44464
44538
  cfg.apiKey = poll.apiKey;
44539
+ cfg.accessToken = null;
44540
+ cfg.refreshToken = null;
44541
+ cfg.tokenEndpoint = null;
44465
44542
  cfg.userId = poll.agentId ?? null;
44466
44543
  cfg.email = poll.handle ?? handle2;
44467
44544
  saveConfig(cfg);
@@ -44486,6 +44563,9 @@ async function cmdLogin() {
44486
44563
  async function cmdLogout() {
44487
44564
  const cfg = loadConfig();
44488
44565
  cfg.apiKey = null;
44566
+ cfg.accessToken = null;
44567
+ cfg.refreshToken = null;
44568
+ cfg.tokenEndpoint = null;
44489
44569
  cfg.userId = null;
44490
44570
  cfg.email = null;
44491
44571
  saveConfig(cfg);
@@ -44849,7 +44929,7 @@ async function cmdBurst(args2) {
44849
44929
  let ctx = {};
44850
44930
  if (!local) {
44851
44931
  const cfg = loadConfig();
44852
- if (cfg.apiKey || cfg.accessToken) ctx = { cloud: authedCloudClient(cfg) };
44932
+ if (hasCloudCredential(cfg)) ctx = { cloud: authedCloudClient(cfg) };
44853
44933
  }
44854
44934
  await withStore(async (store) => {
44855
44935
  const result = await runTool2(
@@ -45441,7 +45521,7 @@ async function cmdPrivacy() {
45441
45521
  sync: ${onoff(cfg.consent.sync)}
45442
45522
  telemetry: ${onoff(cfg.consent.telemetry)}
45443
45523
  packages: ${onoff(cfg.consent.contributePackages)}
45444
- logged in: ${cfg.apiKey ? `yes (${cfg.email})` : "no"}
45524
+ logged in: ${hasCloudCredential(cfg) ? `yes (${cfg.email})` : "no"}
45445
45525
 
45446
45526
  Change it: errata consent sync on | errata consent telemetry off
45447
45527
  Kill switch: errata consent all off (or errata logout to drop your key)
@@ -45464,8 +45544,8 @@ async function cmdConsent(args2) {
45464
45544
  console.log(
45465
45545
  `consent updated \u2192 sync=${cfg.consent.sync ? "on" : "off"} telemetry=${cfg.consent.telemetry ? "on" : "off"} packages=${cfg.consent.contributePackages ? "on" : "off"}`
45466
45546
  );
45467
- if ((channel === "sync" || channel === "all") && value && !cfg.apiKey) {
45468
- console.log(" note: run `errata login` to actually upload (no API key yet).");
45547
+ if ((channel === "sync" || channel === "all") && value && !hasCloudCredential(cfg)) {
45548
+ console.log(" note: run `errata login` to actually upload (no cloud credential yet).");
45469
45549
  }
45470
45550
  }
45471
45551
  async function cmdDash(args2) {
@@ -45757,7 +45837,7 @@ async function cmdNotifications(state) {
45757
45837
  }
45758
45838
  async function cmdFeedback(args2) {
45759
45839
  const cfg = loadConfig();
45760
- if (!cfg.apiKey) {
45840
+ if (!hasCloudCredential(cfg)) {
45761
45841
  console.error("not logged in \u2014 run `errata login` first.");
45762
45842
  process.exit(2);
45763
45843
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.25",
3
+ "version": "2.0.0-dev.27",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {