@inerrata-corporation/errata 2.0.7-dev.2821 → 2.0.7-dev.2829

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 +55 -4
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -79931,7 +79931,7 @@ function createWatchBreaker(deps) {
79931
79931
  }
79932
79932
 
79933
79933
  // src/engine.ts
79934
- var DAEMON_VERSION = true ? "2.0.7-dev.2821" : "2.0.0-alpha.0";
79934
+ var DAEMON_VERSION = true ? "2.0.7-dev.2829" : "2.0.0-alpha.0";
79935
79935
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
79936
79936
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
79937
79937
  var GIT_OP_MUTE_MS = 4e3;
@@ -82219,6 +82219,14 @@ B: ${b}`,
82219
82219
  const pending = existsSync25(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
82220
82220
  return { uploaded: 0, failed: 0, remaining: pending };
82221
82221
  }
82222
+ const onDisk = loadProfile(opts.workspaceRoot);
82223
+ if (!onDisk?.projectId && onDisk?.projectLinkHold) {
82224
+ console.log(
82225
+ "[errata] sync held \u2014 this repo is already on errata in another workspace; run `errata link` to join it or create your own project"
82226
+ );
82227
+ const pending = existsSync25(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
82228
+ return { uploaded: 0, failed: 0, remaining: pending };
82229
+ }
82222
82230
  try {
82223
82231
  const ignorePatterns = loadClaimIgnorePatterns(opts.workspaceRoot);
82224
82232
  const claimPayload = buildClaimIngest(store, profile, DAEMON_VERSION, 1, ignorePatterns);
@@ -83715,6 +83723,11 @@ init_profile2();
83715
83723
  import { execFile as execFile3 } from "node:child_process";
83716
83724
  import { promisify } from "node:util";
83717
83725
  var execFileAsync = promisify(execFile3);
83726
+ function isClaimedElsewhere(err2) {
83727
+ if (!err2 || typeof err2 !== "object") return false;
83728
+ const e = err2;
83729
+ return e.status === 409 && e.code === "claimed_elsewhere";
83730
+ }
83718
83731
  async function readRootCommit(root) {
83719
83732
  try {
83720
83733
  const { stdout } = await execFileAsync("git", ["rev-list", "--max-parents=0", "HEAD"], {
@@ -83753,9 +83766,21 @@ async function ensureProjectLink(root, profile, client, rootCommit = readRootCom
83753
83766
  profile.projectId = res.project.id;
83754
83767
  profile.projectLocator = locator;
83755
83768
  if (sha2) profile.rootCommitReportedFor = res.project.id;
83769
+ delete profile.projectLinkHold;
83756
83770
  saveProfile(root, profile);
83757
83771
  return { linked: true, projectId: res.project.id, created: res.created };
83758
83772
  } catch (err2) {
83773
+ if (isClaimedElsewhere(err2)) {
83774
+ if (profile.projectLinkHold?.locator !== locator) {
83775
+ profile.projectLinkHold = { reason: "claimed-elsewhere", locator, since: Date.now() };
83776
+ saveProfile(root, profile);
83777
+ }
83778
+ return {
83779
+ linked: false,
83780
+ reason: "held",
83781
+ detail: "this repo is already on errata in another workspace \u2014 run `errata link` to join it or create your own project"
83782
+ };
83783
+ }
83759
83784
  return {
83760
83785
  linked: false,
83761
83786
  reason: "error",
@@ -84930,6 +84955,13 @@ function throttledPoll(res, intervalMs) {
84930
84955
  waitMs: Math.max(next, retryAfterMs(res.headers) ?? 0, THROTTLED_POLL_MIN_WAIT_MS)
84931
84956
  };
84932
84957
  }
84958
+ async function fetchDevicePoll(fetchFn, url2, init2) {
84959
+ try {
84960
+ return await fetchFn(url2, init2);
84961
+ } catch {
84962
+ return null;
84963
+ }
84964
+ }
84933
84965
  function retryAfterMs(headers, now = Date.now()) {
84934
84966
  for (const name2 of ["retry-after", "x-retry-after"]) {
84935
84967
  const raw2 = headers.get(name2)?.trim();
@@ -85001,7 +85033,7 @@ async function loginOAuthDevice(opts) {
85001
85033
  while (Date.now() < deadline) {
85002
85034
  await (opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))))(waitMs);
85003
85035
  waitMs = intervalMs;
85004
- const poll = await fetchFn(device.token, {
85036
+ const poll = await fetchDevicePoll(fetchFn, device.token, {
85005
85037
  method: "POST",
85006
85038
  headers: { "content-type": "application/json", accept: "application/json" },
85007
85039
  body: JSON.stringify({
@@ -85010,6 +85042,7 @@ async function loginOAuthDevice(opts) {
85010
85042
  client_id: clientId
85011
85043
  })
85012
85044
  });
85045
+ if (!poll) continue;
85013
85046
  const payload = await poll.json().catch(() => null);
85014
85047
  if (!poll.ok) {
85015
85048
  const throttle = throttledPoll(poll, intervalMs);
@@ -85249,7 +85282,7 @@ async function linkThroughConsole(opts) {
85249
85282
  while (Date.now() < deadline) {
85250
85283
  await sleep(waitMs);
85251
85284
  waitMs = intervalMs;
85252
- const poll = await fetchFn(device.token, {
85285
+ const poll = await fetchDevicePoll(fetchFn, device.token, {
85253
85286
  method: "POST",
85254
85287
  headers: { "content-type": "application/json", accept: "application/json" },
85255
85288
  body: JSON.stringify({
@@ -85258,6 +85291,7 @@ async function linkThroughConsole(opts) {
85258
85291
  client_id: clientId
85259
85292
  })
85260
85293
  });
85294
+ if (!poll) continue;
85261
85295
  const payload = await poll.json().catch(() => null);
85262
85296
  if (!poll.ok) {
85263
85297
  const throttle = throttledPoll(poll, intervalMs);
@@ -86477,6 +86511,8 @@ async function startMultiDaemon(opts = {}) {
86477
86511
  );
86478
86512
  } else if (out2.reason === "error") {
86479
86513
  console.warn(`[errata] project link failed for ${r.engine.profile.name}: ${out2.detail}`);
86514
+ } else if (out2.reason === "held") {
86515
+ noteProjectHold(r.id, r.engine.profile.name, out2.detail);
86480
86516
  }
86481
86517
  let primeSalt = null;
86482
86518
  if (r.engine.profile.projectId && !r.engine.profile.projectHydratedAt) {
@@ -86934,7 +86970,16 @@ async function startMultiDaemon(opts = {}) {
86934
86970
  const client = poolFor(recordIdentity);
86935
86971
  const store = r.engine.store;
86936
86972
  const projectName = r.engine.profile.name ?? r.engine.profile.id;
86937
- const onDiskProjectId = loadProfile(r.root)?.projectId;
86973
+ const onDisk = loadProfile(r.root);
86974
+ const onDiskProjectId = onDisk?.projectId;
86975
+ if (!onDiskProjectId && onDisk?.projectLinkHold) {
86976
+ noteProjectHold(
86977
+ r.id,
86978
+ r.entry.name,
86979
+ "this repo is already on errata in another workspace \u2014 run `errata link` to join it or create your own project"
86980
+ );
86981
+ continue;
86982
+ }
86938
86983
  if (onDiskProjectId !== r.engine.profile.projectId) {
86939
86984
  if (onDiskProjectId) r.engine.profile.projectId = onDiskProjectId;
86940
86985
  else delete r.engine.profile.projectId;
@@ -88694,6 +88739,11 @@ async function cmdStatus() {
88694
88739
  console.log(
88695
88740
  ` repo: ${profile.repoLocator ? `${profile.repoLocator}${link}` : "(no git remote \u2014 unlinked)"}`
88696
88741
  );
88742
+ if (!profile.projectId && profile.projectLinkHold) {
88743
+ console.log(
88744
+ ` HELD: this repo is already on errata in another workspace. Nothing syncs until you decide: run \`errata link\` to join it or create your own project.`
88745
+ );
88746
+ }
88697
88747
  for (const h of await daemonHolds()) {
88698
88748
  if (h.workspace !== profile.name && h.workspace !== profile.id) continue;
88699
88749
  console.log(
@@ -89339,6 +89389,7 @@ async function cmdLink(args2) {
89339
89389
  return;
89340
89390
  }
89341
89391
  delete profile.projectLinkDisabled;
89392
+ delete profile.projectLinkHold;
89342
89393
  const remote = flag("--remote");
89343
89394
  if (remote) {
89344
89395
  const loc = detectRepoLocator(ROOT, remote);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.7-dev.2821",
3
+ "version": "2.0.7-dev.2829",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {