@inerrata-corporation/errata 2.0.0-dev.46 → 2.0.0-dev.47

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 +121 -5
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -20936,6 +20936,16 @@ var init_client = __esm({
20936
20936
  async resolveProject(locator, name2) {
20937
20937
  return this.json("POST", "/api/gate/projects/resolve", name2 ? { locator, name: name2 } : { locator });
20938
20938
  }
20939
+ /** Attach this repo's locator to an EXISTING project (fork adopt / alias
20940
+ * accrual) — `errata link --project`. Org-scoped; foreign ids 404. */
20941
+ async attachProject(projectId, locator) {
20942
+ return this.json("POST", "/api/gate/projects/attach", { projectId, locator });
20943
+ }
20944
+ /** Create a locator-less project — `errata link --name` for repos without a
20945
+ * usable remote. Discovery can't find it; the caller stamps the id locally. */
20946
+ async createProject(name2) {
20947
+ return this.json("POST", "/api/gate/projects/create", { name: name2 });
20948
+ }
20939
20949
  // ─── ingest ────────────────────────────────────────────────────────
20940
20950
  /** Upload one outbox batch (projected onto the reconciled wire) and fold
20941
20951
  * the per-decision response into flush accounting.
@@ -42430,10 +42440,10 @@ function readRemotes(root) {
42430
42440
  }
42431
42441
  return out2;
42432
42442
  }
42433
- function detectRepoLocator(root) {
42443
+ function detectRepoLocator(root, remote) {
42434
42444
  const remotes = readRemotes(root);
42435
42445
  if (remotes.length === 0) return null;
42436
- const pick2 = remotes.find((r) => r.name === "origin") ?? (remotes.length === 1 ? remotes[0] : null);
42446
+ const pick2 = remote ? remotes.find((r) => r.name === remote) ?? null : remotes.find((r) => r.name === "origin") ?? (remotes.length === 1 ? remotes[0] : null);
42437
42447
  return pick2 ? normalizeRepoLocator(pick2.url) : null;
42438
42448
  }
42439
42449
 
@@ -42442,7 +42452,7 @@ function workspaceId(root) {
42442
42452
  return "wp_" + createHash12("sha256").update(root).digest("hex").slice(0, 12);
42443
42453
  }
42444
42454
  function refreshRepoLocator(root, profile) {
42445
- const detected = detectRepoLocator(root);
42455
+ const detected = detectRepoLocator(root, profile.repoRemote);
42446
42456
  if (!detected || detected === profile.repoLocator) return false;
42447
42457
  profile.repoLocator = detected;
42448
42458
  saveProfile(root, profile);
@@ -42669,7 +42679,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
42669
42679
  }
42670
42680
 
42671
42681
  // src/engine.ts
42672
- var DAEMON_VERSION = true ? "2.0.0-dev.46" : "2.0.0-alpha.0";
42682
+ var DAEMON_VERSION = true ? "2.0.0-dev.47" : "2.0.0-alpha.0";
42673
42683
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
42674
42684
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
42675
42685
  var GIT_OP_MUTE_MS = 4e3;
@@ -44730,6 +44740,7 @@ init_cloud_auth();
44730
44740
 
44731
44741
  // src/project-link.ts
44732
44742
  async function ensureProjectLink(root, profile, client) {
44743
+ if (profile.projectLinkDisabled) return { linked: false, reason: "disabled" };
44733
44744
  const locator = profile.repoLocator;
44734
44745
  if (!locator) return { linked: false, reason: "no-locator" };
44735
44746
  if (profile.projectId && profile.projectLocator === locator) {
@@ -45807,6 +45818,10 @@ async function main() {
45807
45818
  return cmdLogin();
45808
45819
  case "logout":
45809
45820
  return cmdLogout();
45821
+ case "link":
45822
+ return cmdLink(rest);
45823
+ case "unlink":
45824
+ return cmdUnlink();
45810
45825
  case "use":
45811
45826
  return cmdUse(rest);
45812
45827
  case "review":
@@ -45933,6 +45948,11 @@ Commands:
45933
45948
  surface (navigation, problems, claims, burst, health)
45934
45949
  login Sign in with the cloud (OAuth by default; --device for legacy device-code)
45935
45950
  logout Clear local cloud credentials
45951
+ link Corrective project link (ambient linking covers the happy path).
45952
+ Flags: --project <id> adopt an existing project (fork\u2192upstream);
45953
+ --remote <name> derive the locator from a non-origin remote;
45954
+ --name <name> mint a locator-less project; no flags = re-resolve now
45955
+ unlink Detach from the cloud project + disable ambient re-linking
45936
45956
  use [<handle>] Set the sticky session active agent the daemon acts as.
45937
45957
  No arg lists the agents you can act as + the current one;
45938
45958
  --none (or --clear) reverts to your default identity.
@@ -46033,7 +46053,25 @@ async function cmdInit() {
46033
46053
  console.log("");
46034
46054
  console.log("Notifications: desktop toasts (flagged/resolved problems, learned skills)");
46035
46055
  console.log("are ON \u2014 silence with `errata notifications off`; verify with `errata notify-test`.");
46036
- const cfgNow = loadConfig();
46056
+ let cfgNow = loadConfig();
46057
+ if (!hasCloudCredential(cfgNow) && !rest.includes("--no-login")) {
46058
+ if (!process.stdout.isTTY) {
46059
+ console.error("");
46060
+ console.error("errata init requires login (or pass --no-login for a headless, unlinked init).");
46061
+ console.error(" interactive: errata init headless: errata init --no-login && errata login --token <key>");
46062
+ process.exitCode = 1;
46063
+ return;
46064
+ }
46065
+ console.log("");
46066
+ console.log("connecting your cloud account (init links this repo to its project)...");
46067
+ await cmdLoginOAuth(cfgNow);
46068
+ cfgNow = loadConfig();
46069
+ if (!hasCloudCredential(cfgNow)) {
46070
+ console.error("init requires login \u2014 re-run `errata init`, or `errata init --no-login` to stay unlinked.");
46071
+ process.exitCode = 1;
46072
+ return;
46073
+ }
46074
+ }
46037
46075
  console.log("");
46038
46076
  console.log("Next:");
46039
46077
  console.log(" errata start # observe this repo");
@@ -46347,6 +46385,84 @@ async function linkRegisteredWorkspaces(cfg) {
46347
46385
  }
46348
46386
  }
46349
46387
  }
46388
+ async function cmdLink(args2) {
46389
+ const flag = (name2) => {
46390
+ const i2 = args2.indexOf(name2);
46391
+ return i2 >= 0 ? args2[i2 + 1] : void 0;
46392
+ };
46393
+ const profile = loadProfile(ROOT);
46394
+ if (!profile) {
46395
+ console.error("not an errata workspace \u2014 run `errata init` first");
46396
+ process.exitCode = 1;
46397
+ return;
46398
+ }
46399
+ const cfg = loadConfig();
46400
+ if (!hasCloudCredential(cfg)) {
46401
+ console.error("not logged in \u2014 run `errata login` first (linking needs your cloud identity)");
46402
+ process.exitCode = 1;
46403
+ return;
46404
+ }
46405
+ const client = authedCloudClient(cfg);
46406
+ delete profile.projectLinkDisabled;
46407
+ const remote = flag("--remote");
46408
+ if (remote) {
46409
+ const loc = detectRepoLocator(ROOT, remote);
46410
+ if (!loc) {
46411
+ console.error(`remote '${remote}' not found or its URL isn't linkable`);
46412
+ process.exitCode = 1;
46413
+ return;
46414
+ }
46415
+ profile.repoRemote = remote;
46416
+ profile.repoLocator = loc;
46417
+ }
46418
+ const adoptId = flag("--project");
46419
+ if (adoptId) {
46420
+ if (!profile.repoLocator) {
46421
+ console.error("this workspace has no repo locator to attach \u2014 use --remote or --name");
46422
+ process.exitCode = 1;
46423
+ return;
46424
+ }
46425
+ const res = await client.attachProject(adoptId, profile.repoLocator);
46426
+ profile.projectId = res.project.id;
46427
+ profile.projectLocator = profile.repoLocator;
46428
+ saveProfile(ROOT, profile);
46429
+ console.log(`linked (adopted): ${profile.repoLocator} \u2192 project ${res.project.id} (${res.project.name})`);
46430
+ return;
46431
+ }
46432
+ const bareName = flag("--name");
46433
+ if (bareName) {
46434
+ const res = await client.createProject(bareName);
46435
+ profile.projectId = res.project.id;
46436
+ delete profile.projectLocator;
46437
+ saveProfile(ROOT, profile);
46438
+ console.log(`linked (locator-less): project ${res.project.id} (${res.project.name})`);
46439
+ return;
46440
+ }
46441
+ saveProfile(ROOT, profile);
46442
+ delete profile.projectId;
46443
+ delete profile.projectLocator;
46444
+ const out2 = await ensureProjectLink(ROOT, profile, client);
46445
+ if (out2.linked) {
46446
+ console.log(`linked: ${profile.repoLocator} \u2192 project ${out2.projectId}${out2.created ? " (created)" : ""}`);
46447
+ } else {
46448
+ console.error(`link failed (${out2.reason})${out2.detail ? `: ${out2.detail}` : ""}`);
46449
+ process.exitCode = 1;
46450
+ }
46451
+ }
46452
+ async function cmdUnlink() {
46453
+ const profile = loadProfile(ROOT);
46454
+ if (!profile) {
46455
+ console.error("not an errata workspace \u2014 run `errata init` first");
46456
+ process.exitCode = 1;
46457
+ return;
46458
+ }
46459
+ const had = profile.projectId;
46460
+ delete profile.projectId;
46461
+ delete profile.projectLocator;
46462
+ profile.projectLinkDisabled = true;
46463
+ saveProfile(ROOT, profile);
46464
+ console.log(had ? `unlinked from project ${had} (ambient linking disabled \u2014 re-enable with \`errata link\`)` : "already unlinked (ambient linking disabled)");
46465
+ }
46350
46466
  async function cmdLogin() {
46351
46467
  const cfg = loadConfig();
46352
46468
  const flags2 = parseFlags(rest);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.46",
3
+ "version": "2.0.0-dev.47",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {