@inerrata-corporation/errata 2.0.18-dev.3596 → 2.0.18-dev.3612
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 +197 -66
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -33461,6 +33461,13 @@ function foreignDaemonNote(lock, selfEntry) {
|
|
|
33461
33461
|
];
|
|
33462
33462
|
return runningInstalled ? [...head2, "this CLI is a different bundle from the daemon it is talking to \u2014 its view may not match what the daemon runs."] : [...head2, "`errata update` does not replace it. To move onto the installed package: errata stop, then errata dash."];
|
|
33463
33463
|
}
|
|
33464
|
+
function daemonVersionNote(lock, selfVersion) {
|
|
33465
|
+
if (!lock.version || lock.version === selfVersion) return null;
|
|
33466
|
+
return [
|
|
33467
|
+
`the running daemon is ${lock.version}, but this CLI is ${selfVersion} \u2014 it was started before the update.`,
|
|
33468
|
+
`restart it onto ${selfVersion}: errata stop, then errata start`
|
|
33469
|
+
];
|
|
33470
|
+
}
|
|
33464
33471
|
function isProcessAlive(pid) {
|
|
33465
33472
|
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
33466
33473
|
try {
|
|
@@ -33500,6 +33507,20 @@ function isDaemonAlive(lockPath) {
|
|
|
33500
33507
|
function daemonLockBlocksStartup(lockPath) {
|
|
33501
33508
|
return daemonLockState(readDaemonLock(lockPath), true) !== "stale";
|
|
33502
33509
|
}
|
|
33510
|
+
async function waitForDaemonExit(lock, timeoutMs, pollMs = 200) {
|
|
33511
|
+
const deadline = Date.now() + timeoutMs;
|
|
33512
|
+
for (; ; ) {
|
|
33513
|
+
if (daemonLockState(lock, true) === "stale") return true;
|
|
33514
|
+
if (Date.now() >= deadline) return false;
|
|
33515
|
+
await new Promise((resolve10) => setTimeout(resolve10, pollMs));
|
|
33516
|
+
}
|
|
33517
|
+
}
|
|
33518
|
+
function releaseOwnLock(lockPath) {
|
|
33519
|
+
try {
|
|
33520
|
+
if (parseDaemonLock(readFileSync12(lockPath, "utf8"))?.pid === process.pid) unlinkSync2(lockPath);
|
|
33521
|
+
} catch {
|
|
33522
|
+
}
|
|
33523
|
+
}
|
|
33503
33524
|
function stopLockedDaemon(lockPath) {
|
|
33504
33525
|
let original;
|
|
33505
33526
|
try {
|
|
@@ -73598,7 +73619,7 @@ var init_report_render = __esm({
|
|
|
73598
73619
|
|
|
73599
73620
|
// src/cli.ts
|
|
73600
73621
|
init_src6();
|
|
73601
|
-
import { closeSync as closeSync2, existsSync as existsSync39, openSync as openSync2, readFileSync as
|
|
73622
|
+
import { closeSync as closeSync2, existsSync as existsSync39, openSync as openSync2, readFileSync as readFileSync41, renameSync as renameSync6, statSync as statSync12 } from "node:fs";
|
|
73602
73623
|
import { join as join48, resolve as pathResolve2 } from "node:path";
|
|
73603
73624
|
import { spawn as spawn5 } from "node:child_process";
|
|
73604
73625
|
|
|
@@ -82685,7 +82706,7 @@ function createWatchBreaker(deps) {
|
|
|
82685
82706
|
}
|
|
82686
82707
|
|
|
82687
82708
|
// src/engine.ts
|
|
82688
|
-
var DAEMON_VERSION = true ? "2.0.18-dev.
|
|
82709
|
+
var DAEMON_VERSION = true ? "2.0.18-dev.3612" : "2.0.0-alpha.0";
|
|
82689
82710
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
82690
82711
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
82691
82712
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -85407,10 +85428,20 @@ async function startDaemon(opts) {
|
|
|
85407
85428
|
};
|
|
85408
85429
|
}
|
|
85409
85430
|
async function listenServer(fetchFn, port) {
|
|
85410
|
-
return new Promise((resolve10) => {
|
|
85431
|
+
return new Promise((resolve10, reject) => {
|
|
85411
85432
|
const server = serve({ fetch: fetchFn, hostname: "127.0.0.1", port }, (info2) => {
|
|
85412
85433
|
resolve10({ server, port: info2.port });
|
|
85413
85434
|
});
|
|
85435
|
+
server.once(
|
|
85436
|
+
"error",
|
|
85437
|
+
(err2) => {
|
|
85438
|
+
reject(
|
|
85439
|
+
err2.code === "EADDRINUSE" ? new Error(
|
|
85440
|
+
`port ${port} is still held by another process \u2014 usually a previous errata daemon that has not finished shutting down. Wait for it to exit (errata stop waits for it), then start again.`
|
|
85441
|
+
) : err2
|
|
85442
|
+
);
|
|
85443
|
+
}
|
|
85444
|
+
);
|
|
85414
85445
|
});
|
|
85415
85446
|
}
|
|
85416
85447
|
|
|
@@ -85531,6 +85562,17 @@ function workspaceCloud(cfg, entry, env2 = process.env) {
|
|
|
85531
85562
|
profileName: name2
|
|
85532
85563
|
};
|
|
85533
85564
|
}
|
|
85565
|
+
function reportedIdentity(cfg, entry, env2 = process.env) {
|
|
85566
|
+
try {
|
|
85567
|
+
const ws = workspaceCloud(cfg, entry, env2);
|
|
85568
|
+
const machineDefault = cfg.activeInstallationProfile;
|
|
85569
|
+
const note = entry && ws.profileName !== machineDefault ? `this workspace pushes as profile "${ws.profileName ?? "top-level credential"}" (${ws.identity.reason}); machine default is "${machineDefault ?? "top-level credential"}"` : null;
|
|
85570
|
+
return { ok: true, config: ws.config, client: ws.client, profileName: ws.profileName, note };
|
|
85571
|
+
} catch (err2) {
|
|
85572
|
+
if (err2 instanceof IdentityBlockedError) return { ok: false, reason: err2.message };
|
|
85573
|
+
throw err2;
|
|
85574
|
+
}
|
|
85575
|
+
}
|
|
85534
85576
|
function configWithDeviceLogin(cfg, input) {
|
|
85535
85577
|
const name2 = input.profileName.trim();
|
|
85536
85578
|
if (!name2 || name2.length > 80) throw new Error("profile name must be 1\u201380 characters");
|
|
@@ -85704,7 +85746,7 @@ function invalidateInstanceReceipt(current, destination, failedId, mirrorLegacy)
|
|
|
85704
85746
|
// src/multi.ts
|
|
85705
85747
|
init_dist();
|
|
85706
85748
|
init_src5();
|
|
85707
|
-
import { existsSync as existsSync34,
|
|
85749
|
+
import { existsSync as existsSync34, writeFileSync as writeFileSync26 } from "node:fs";
|
|
85708
85750
|
import { resolve as pathResolve } from "node:path";
|
|
85709
85751
|
|
|
85710
85752
|
// src/principle-sync.ts
|
|
@@ -89646,6 +89688,7 @@ var SessionAffinity = class {
|
|
|
89646
89688
|
// src/multi.ts
|
|
89647
89689
|
init_checkout_root();
|
|
89648
89690
|
var PROCESS_STARTED_AT = Date.now();
|
|
89691
|
+
var SHUTDOWN_CONNECTION_GRACE_MS = 2e3;
|
|
89649
89692
|
var SELF_ENTRY = process.argv[1] ? pathResolve(process.argv[1]) : "";
|
|
89650
89693
|
var LOCAL_BUILD_ENTRY = SELF_ENTRY && !isInstalledEntry(SELF_ENTRY) ? SELF_ENTRY : void 0;
|
|
89651
89694
|
function withLaunchOrigin(pending) {
|
|
@@ -91468,21 +91511,23 @@ async function startMultiDaemon(opts = {}) {
|
|
|
91468
91511
|
clearInterval(historyRetry);
|
|
91469
91512
|
clearTimeout(codexWakeBoot);
|
|
91470
91513
|
try {
|
|
91471
|
-
const
|
|
91472
|
-
|
|
91473
|
-
|
|
91474
|
-
|
|
91475
|
-
|
|
91476
|
-
(
|
|
91477
|
-
|
|
91478
|
-
|
|
91479
|
-
|
|
91480
|
-
|
|
91481
|
-
|
|
91482
|
-
|
|
91483
|
-
|
|
91484
|
-
|
|
91485
|
-
|
|
91514
|
+
const http = server;
|
|
91515
|
+
const closed = new Promise((res) => http.close(res));
|
|
91516
|
+
http.closeIdleConnections?.();
|
|
91517
|
+
const force = setTimeout(() => http.closeAllConnections?.(), SHUTDOWN_CONNECTION_GRACE_MS);
|
|
91518
|
+
await closed;
|
|
91519
|
+
clearTimeout(force);
|
|
91520
|
+
updatePoller?.stop();
|
|
91521
|
+
healthSentinel.stop();
|
|
91522
|
+
await Promise.allSettled(attaching.values());
|
|
91523
|
+
for (const r of records) await r.engine.stop();
|
|
91524
|
+
if (consolidateWorker) await consolidateWorker.stop();
|
|
91525
|
+
try {
|
|
91526
|
+
sharedStore.close();
|
|
91527
|
+
} catch {
|
|
91528
|
+
}
|
|
91529
|
+
} finally {
|
|
91530
|
+
releaseOwnLock(lockPath);
|
|
91486
91531
|
}
|
|
91487
91532
|
}
|
|
91488
91533
|
};
|
|
@@ -91932,8 +91977,31 @@ function installedHarnessVersion(bin) {
|
|
|
91932
91977
|
return null;
|
|
91933
91978
|
}
|
|
91934
91979
|
}
|
|
91980
|
+
function daemonDoctorCheck(input) {
|
|
91981
|
+
const { lock, state, selfVersion, lockPath } = input;
|
|
91982
|
+
if (!lock || state === "stale") {
|
|
91983
|
+
return { id: "daemon", status: "warn", detail: "Daemon is not running \u2014 start it: errata start" };
|
|
91984
|
+
}
|
|
91985
|
+
if (state === "unknown") {
|
|
91986
|
+
return {
|
|
91987
|
+
id: "daemon",
|
|
91988
|
+
status: "fail",
|
|
91989
|
+
detail: `${lockPath} names pid ${lock.pid}, but that process's identity cannot be verified. If \`ps -p ${lock.pid}\` shows no errata process, delete the lock; otherwise run errata stop.`
|
|
91990
|
+
};
|
|
91991
|
+
}
|
|
91992
|
+
const where = `pid ${lock.pid}${lock.webUiUrl ? ` \xB7 ${lock.webUiUrl}` : ""}`;
|
|
91993
|
+
if (lock.version && lock.version !== selfVersion) {
|
|
91994
|
+
return {
|
|
91995
|
+
id: "daemon",
|
|
91996
|
+
status: "warn",
|
|
91997
|
+
detail: `Running ${lock.version} (${where}), but this CLI is ${selfVersion} \u2014 restart it: errata stop, then errata start`
|
|
91998
|
+
};
|
|
91999
|
+
}
|
|
92000
|
+
return { id: "daemon", status: "pass", detail: `Running${lock.version ? ` ${lock.version}` : ""} \xB7 ${where}` };
|
|
92001
|
+
}
|
|
91935
92002
|
async function diagnoseInstallation(cfg, dependencies) {
|
|
91936
92003
|
const checks = [];
|
|
92004
|
+
if (dependencies.daemon) checks.push(dependencies.daemon());
|
|
91937
92005
|
if (dependencies.codexHooks) checks.push(...await dependencies.codexHooks());
|
|
91938
92006
|
const profileName = cfg.activeInstallationProfile;
|
|
91939
92007
|
const profile = profileName ? cfg.installationProfiles[profileName] : void 0;
|
|
@@ -92030,12 +92098,12 @@ async function diagnoseInstallation(cfg, dependencies) {
|
|
|
92030
92098
|
|
|
92031
92099
|
// src/codex-doctor.ts
|
|
92032
92100
|
import { spawn as spawn4 } from "node:child_process";
|
|
92033
|
-
import { readFileSync as
|
|
92101
|
+
import { readFileSync as readFileSync37, statSync as statSync10 } from "node:fs";
|
|
92034
92102
|
import { join as join44 } from "node:path";
|
|
92035
92103
|
import { createInterface } from "node:readline";
|
|
92036
92104
|
|
|
92037
92105
|
// src/codex-hooks.ts
|
|
92038
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as
|
|
92106
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync36, renameSync as renameSync5, unlinkSync as unlinkSync5, writeFileSync as writeFileSync27 } from "node:fs";
|
|
92039
92107
|
import { homedir as homedir7 } from "node:os";
|
|
92040
92108
|
import { join as join43 } from "node:path";
|
|
92041
92109
|
|
|
@@ -92206,23 +92274,23 @@ function buildCodexRelaySource(workspaceRoot) {
|
|
|
92206
92274
|
init_checkout_root();
|
|
92207
92275
|
var CODEX_HOOK_REVIEW_HELP = "Codex desktop: Settings > Hooks, select this project, expand each event and Trust the Errata hook. CLI users can use /hooks.";
|
|
92208
92276
|
function writeRelay(file2, source) {
|
|
92209
|
-
if (existsSync35(file2) &&
|
|
92277
|
+
if (existsSync35(file2) && readFileSync36(file2, "utf8") === source) return;
|
|
92210
92278
|
const temp = `${file2}.${process.pid}.tmp`;
|
|
92211
92279
|
try {
|
|
92212
92280
|
writeFileSync27(temp, source, { encoding: "utf8", mode: 384 });
|
|
92213
92281
|
renameSync5(temp, file2);
|
|
92214
92282
|
} finally {
|
|
92215
|
-
if (existsSync35(temp))
|
|
92283
|
+
if (existsSync35(temp)) unlinkSync5(temp);
|
|
92216
92284
|
}
|
|
92217
92285
|
}
|
|
92218
92286
|
function refreshCodexRelay(root) {
|
|
92219
92287
|
const config2 = join43(root, ".codex", "config.toml");
|
|
92220
92288
|
if (!existsSync35(config2)) return "absent";
|
|
92221
|
-
const existing =
|
|
92289
|
+
const existing = readFileSync36(config2, "utf8");
|
|
92222
92290
|
if (!existing.includes(CODEX_HOOKS_BEGIN) && !existing.includes(CODEX_HOOKS_END)) return "absent";
|
|
92223
92291
|
replaceCodexHooks(existing, "");
|
|
92224
92292
|
const relay = join43(root, ".codex", "hooks", "errata-relay.mjs");
|
|
92225
|
-
const prior = existsSync35(relay) ?
|
|
92293
|
+
const prior = existsSync35(relay) ? readFileSync36(relay, "utf8") : "";
|
|
92226
92294
|
if (prior && !prior.startsWith("// errata-managed: regenerated by errata install-hooks codex")) {
|
|
92227
92295
|
throw new Error("Codex relay is not Errata-managed; preserved it. Run errata install-hooks codex to explicitly replace it.");
|
|
92228
92296
|
}
|
|
@@ -92253,10 +92321,10 @@ function writeCodexHooks(root, port, nodePath = process.execPath) {
|
|
|
92253
92321
|
const file2 = join43(dir, "config.toml");
|
|
92254
92322
|
const relay = join43(dir, "hooks", "errata-relay.mjs");
|
|
92255
92323
|
const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
|
|
92256
|
-
const final = replaceCodexHooks(existsSync35(file2) ?
|
|
92324
|
+
const final = replaceCodexHooks(existsSync35(file2) ? readFileSync36(file2, "utf8") : "", block);
|
|
92257
92325
|
mkdirSync9(join43(dir, "hooks"), { recursive: true });
|
|
92258
92326
|
writeRelay(relay, buildCodexRelaySource(checkoutRootOf(root)));
|
|
92259
|
-
if (!existsSync35(file2) ||
|
|
92327
|
+
if (!existsSync35(file2) || readFileSync36(file2, "utf8") !== final) writeFileSync27(file2, final, "utf8");
|
|
92260
92328
|
return file2;
|
|
92261
92329
|
}
|
|
92262
92330
|
|
|
@@ -92265,7 +92333,7 @@ init_checkout_root();
|
|
|
92265
92333
|
function inspectCodexRelay(cwd) {
|
|
92266
92334
|
const root = nearestGitRoot(cwd) ?? cwd;
|
|
92267
92335
|
try {
|
|
92268
|
-
const source =
|
|
92336
|
+
const source = readFileSync37(join44(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
|
|
92269
92337
|
if (source === buildCodexRelaySource(checkoutRootOf(root))) {
|
|
92270
92338
|
return { id: "codex_relay", status: "pass", detail: "Installed Codex relay matches this Errata version" };
|
|
92271
92339
|
}
|
|
@@ -92277,7 +92345,7 @@ function inspectCodexContext(cwd) {
|
|
|
92277
92345
|
const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
|
|
92278
92346
|
try {
|
|
92279
92347
|
const file2 = join44(root, ".errata", "context.md");
|
|
92280
|
-
if (statSync10(file2).size <= 128 * 1024 &&
|
|
92348
|
+
if (statSync10(file2).size <= 128 * 1024 && readFileSync37(file2, "utf8").trim()) {
|
|
92281
92349
|
return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
|
|
92282
92350
|
}
|
|
92283
92351
|
} catch {
|
|
@@ -92453,7 +92521,7 @@ function consolidationGapMs(lastPassMs, policy) {
|
|
|
92453
92521
|
|
|
92454
92522
|
// src/codex-hook-refresh.ts
|
|
92455
92523
|
init_checkout_root();
|
|
92456
|
-
import { existsSync as existsSync36, readdirSync as readdirSync13, readFileSync as
|
|
92524
|
+
import { existsSync as existsSync36, readdirSync as readdirSync13, readFileSync as readFileSync38 } from "node:fs";
|
|
92457
92525
|
import { dirname as dirname13, join as join45, resolve as resolve8 } from "node:path";
|
|
92458
92526
|
init_registry();
|
|
92459
92527
|
function codexHookRoots(roots) {
|
|
@@ -92471,7 +92539,7 @@ function codexHookRoots(roots) {
|
|
|
92471
92539
|
}
|
|
92472
92540
|
for (const name2 of names) {
|
|
92473
92541
|
try {
|
|
92474
|
-
const checkout = dirname13(
|
|
92542
|
+
const checkout = dirname13(readFileSync38(join45(dir, name2, "gitdir"), "utf8").trim());
|
|
92475
92543
|
if (mainCheckoutOfWorktree(checkout) === main2) found.add(checkout);
|
|
92476
92544
|
} catch {
|
|
92477
92545
|
}
|
|
@@ -92493,7 +92561,7 @@ function refreshInstalledCodexRelays(roots = listWorkspaceEntries().map((entry)
|
|
|
92493
92561
|
}
|
|
92494
92562
|
|
|
92495
92563
|
// src/claude-statusline.ts
|
|
92496
|
-
import { existsSync as existsSync37, mkdirSync as mkdirSync10, readFileSync as
|
|
92564
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync10, readFileSync as readFileSync39, writeFileSync as writeFileSync28 } from "node:fs";
|
|
92497
92565
|
import { homedir as homedir8 } from "node:os";
|
|
92498
92566
|
import { dirname as dirname14, join as join46 } from "node:path";
|
|
92499
92567
|
var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
|
|
@@ -92554,7 +92622,7 @@ function ensureUserStatusLine(opts) {
|
|
|
92554
92622
|
let settings = {};
|
|
92555
92623
|
if (existsSync37(settingsPath)) {
|
|
92556
92624
|
try {
|
|
92557
|
-
const parsed = JSON.parse(
|
|
92625
|
+
const parsed = JSON.parse(readFileSync39(settingsPath, "utf8"));
|
|
92558
92626
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
|
|
92559
92627
|
settings = parsed;
|
|
92560
92628
|
} catch {
|
|
@@ -92567,7 +92635,7 @@ function ensureUserStatusLine(opts) {
|
|
|
92567
92635
|
const ownRows = keep(settings["subagentStatusLine"]);
|
|
92568
92636
|
if (ownMain && ownRows) return "kept-own";
|
|
92569
92637
|
mkdirSync10(opts.relayDir, { recursive: true });
|
|
92570
|
-
if (!existsSync37(relay) ||
|
|
92638
|
+
if (!existsSync37(relay) || readFileSync39(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
|
|
92571
92639
|
writeFileSync28(relay, STATUSLINE_RELAY_SOURCE, "utf8");
|
|
92572
92640
|
}
|
|
92573
92641
|
const nodePath = opts.nodePath ?? process.execPath;
|
|
@@ -92600,7 +92668,7 @@ function describeStatusLineOutcome(outcome) {
|
|
|
92600
92668
|
|
|
92601
92669
|
// src/claude-mods.ts
|
|
92602
92670
|
import { createHash as createHash20 } from "node:crypto";
|
|
92603
|
-
import { cpSync as cpSync2, existsSync as existsSync38, mkdirSync as mkdirSync11, readFileSync as
|
|
92671
|
+
import { cpSync as cpSync2, existsSync as existsSync38, mkdirSync as mkdirSync11, readFileSync as readFileSync40, readdirSync as readdirSync14, rmSync as rmSync4, statSync as statSync11, writeFileSync as writeFileSync29 } from "node:fs";
|
|
92604
92672
|
import { delimiter as delimiter2, dirname as dirname15, join as join47, relative as relative7, resolve as resolve9, sep as sep5 } from "node:path";
|
|
92605
92673
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
92606
92674
|
var CLAUDE_PLUGIN_DIRS_ENV = "CLAUDE_CODE_PLUGIN_DIRS";
|
|
@@ -92628,7 +92696,7 @@ function modHash(dir) {
|
|
|
92628
92696
|
for (const abs of listFiles(dir).sort()) {
|
|
92629
92697
|
h.update(relative7(dir, abs).split(sep5).join("/"));
|
|
92630
92698
|
h.update("\0");
|
|
92631
|
-
h.update(
|
|
92699
|
+
h.update(readFileSync40(abs));
|
|
92632
92700
|
h.update("\0");
|
|
92633
92701
|
}
|
|
92634
92702
|
return h.digest("hex");
|
|
@@ -92652,7 +92720,7 @@ function off(env2) {
|
|
|
92652
92720
|
function readSettings(path2) {
|
|
92653
92721
|
if (!existsSync38(path2)) return {};
|
|
92654
92722
|
try {
|
|
92655
|
-
const parsed = JSON.parse(
|
|
92723
|
+
const parsed = JSON.parse(readFileSync40(path2, "utf8"));
|
|
92656
92724
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
92657
92725
|
return parsed;
|
|
92658
92726
|
} catch {
|
|
@@ -92703,7 +92771,7 @@ function ensureClaudeMods(opts) {
|
|
|
92703
92771
|
const dest = join47(modsRoot, name2);
|
|
92704
92772
|
const hash2 = modHash(src);
|
|
92705
92773
|
const hashFile = join47(dest, HASH_FILE);
|
|
92706
|
-
if (!existsSync38(hashFile) ||
|
|
92774
|
+
if (!existsSync38(hashFile) || readFileSync40(hashFile, "utf8") !== hash2) {
|
|
92707
92775
|
rmSync4(dest, { recursive: true, force: true });
|
|
92708
92776
|
cpSync2(src, dest, { recursive: true, filter: (p) => !isEngineOwned(relative7(src, p)) });
|
|
92709
92777
|
writeFileSync29(hashFile, hash2, "utf8");
|
|
@@ -92875,6 +92943,8 @@ export const InerrataPlugin = async (input) => {
|
|
|
92875
92943
|
}
|
|
92876
92944
|
|
|
92877
92945
|
// src/cli.ts
|
|
92946
|
+
var STOP_WAIT_MS = 3e4;
|
|
92947
|
+
var SHUTDOWN_DEADLINE_MS = 2e4;
|
|
92878
92948
|
var exitCleanOnEpipe = (err2) => {
|
|
92879
92949
|
if (err2.code === "EPIPE") process.exit(0);
|
|
92880
92950
|
throw err2;
|
|
@@ -92916,6 +92986,10 @@ async function main() {
|
|
|
92916
92986
|
return cmdLogout();
|
|
92917
92987
|
case "link":
|
|
92918
92988
|
return cmdLink(rest);
|
|
92989
|
+
// Moving a workspace to another org/team IS the console link flow (the
|
|
92990
|
+
// page offers every org and team the person is in); `switch` names it.
|
|
92991
|
+
case "switch":
|
|
92992
|
+
return cmdLink(rest.filter((a) => a !== "--local"));
|
|
92919
92993
|
case "unlink":
|
|
92920
92994
|
return cmdUnlink();
|
|
92921
92995
|
case "use":
|
|
@@ -93074,6 +93148,10 @@ Commands:
|
|
|
93074
93148
|
--remote <name> derive the locator from a non-origin remote;
|
|
93075
93149
|
--name <name> mint a locator-less project; no flags = re-resolve now
|
|
93076
93150
|
--skip-hooks leave existing harness configuration unchanged
|
|
93151
|
+
switch Move THIS workspace to another of your orgs or teams (e.g. a
|
|
93152
|
+
company org \u2192 your personal org). Opens the Console to pick;
|
|
93153
|
+
only this workspace changes \u2014 your machine default and other
|
|
93154
|
+
workspaces stay put. Check with \`errata whoami\` from inside it.
|
|
93077
93155
|
unlink Detach from the cloud project + disable ambient re-linking
|
|
93078
93156
|
use [<handle>] Set the sticky session active agent the daemon acts as.
|
|
93079
93157
|
No arg lists the agents you can act as + the current one;
|
|
@@ -93119,7 +93197,7 @@ function resolveHookPort(explicit) {
|
|
|
93119
93197
|
}
|
|
93120
93198
|
const settingsPath = join48(ROOT, ".claude", "settings.json");
|
|
93121
93199
|
try {
|
|
93122
|
-
if (existsSync39(settingsPath)) return installedHookPort(
|
|
93200
|
+
if (existsSync39(settingsPath)) return installedHookPort(readFileSync41(settingsPath, "utf8")) ?? 7891;
|
|
93123
93201
|
} catch {
|
|
93124
93202
|
}
|
|
93125
93203
|
return 7891;
|
|
@@ -93284,6 +93362,8 @@ async function cmdStart() {
|
|
|
93284
93362
|
console.log(`errata: workspace registered; attached to the running daemon`);
|
|
93285
93363
|
console.log(` workspace: ${where}`);
|
|
93286
93364
|
console.log(` daemon: ${running.webUiUrl ?? "(running)"} \xB7 pid ${running.pid}`);
|
|
93365
|
+
const versionNote = daemonVersionNote(running, DAEMON_VERSION);
|
|
93366
|
+
if (versionNote) for (const l of versionNote) console.log(` \u26A0 ${l}`);
|
|
93287
93367
|
let watching = "on the daemon's next restart";
|
|
93288
93368
|
if (running.webUiUrl) {
|
|
93289
93369
|
try {
|
|
@@ -93307,7 +93387,7 @@ async function cmdStart() {
|
|
|
93307
93387
|
if (up) {
|
|
93308
93388
|
console.log(` daemon: running \xB7 pid ${up.pid} \xB7 ${up.webUiUrl ?? "(running)"}`);
|
|
93309
93389
|
console.log(` logs: ${daemonLogPath()}`);
|
|
93310
|
-
console.log(`
|
|
93390
|
+
console.log(` follow it: ${followLogHint()} \xB7 check it: errata status`);
|
|
93311
93391
|
} else {
|
|
93312
93392
|
console.log(` \u26A0 daemon did not come up within 12s.`);
|
|
93313
93393
|
console.log(` run \`errata dash\` in the foreground to see the error.`);
|
|
@@ -93419,8 +93499,10 @@ async function cmdStatus() {
|
|
|
93419
93499
|
const lockPath = globalDaemonLock();
|
|
93420
93500
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
93421
93501
|
console.log(
|
|
93422
|
-
` daemon: ${running ? `running \xB7 pid ${running.pid} \xB7 ${running.webUiUrl ?? "(running)"}` : "not running (run: errata start)"}`
|
|
93502
|
+
` daemon: ${running ? `running \xB7 pid ${running.pid}${running.version ? ` \xB7 ${running.version}` : ""} \xB7 ${running.webUiUrl ?? "(running)"}` : "not running (run: errata start)"}`
|
|
93423
93503
|
);
|
|
93504
|
+
const versionNote = running ? daemonVersionNote(running, DAEMON_VERSION) : null;
|
|
93505
|
+
if (versionNote) for (const l of versionNote) console.log(` \u26A0 ${l}`);
|
|
93424
93506
|
if (running && process.argv[1]) {
|
|
93425
93507
|
const note = foreignDaemonNote(running, pathResolve2(process.argv[1]));
|
|
93426
93508
|
if (note) for (const l of note) console.log(` \u26A0 ${l}`);
|
|
@@ -93479,15 +93561,20 @@ async function cmdStatus() {
|
|
|
93479
93561
|
const shellCloud = describeCloudTarget(cfg, {}, process.env, globalConfigPath());
|
|
93480
93562
|
for (const line of cloudTargetDrift(daemonCloud, shellCloud)) console.log(` \u26A0 ${line}`);
|
|
93481
93563
|
}
|
|
93482
|
-
|
|
93483
|
-
|
|
93564
|
+
const shown = reportedIdentity(cfg, workspaceEntryForPath(ROOT));
|
|
93565
|
+
const ecfg = shown.ok ? shown.config : cfg;
|
|
93566
|
+
console.log(` profile: ${ecfg.activeInstallationProfile ?? "(unbound legacy credential)"}`);
|
|
93567
|
+
if (!shown.ok) console.log(` \u26A0 ${shown.reason} \u2014 this workspace's capture holds locally until fixed`);
|
|
93568
|
+
else if (shown.note) console.log(` \u21B3 ${shown.note}`);
|
|
93569
|
+
const who = shown.ok && shown.note ? "" : ` (${ecfg.email})`;
|
|
93570
|
+
if (!hasCloudCredential(ecfg)) {
|
|
93484
93571
|
console.log(` logged in: no`);
|
|
93485
|
-
} else if (
|
|
93486
|
-
console.log(` logged in: yes
|
|
93572
|
+
} else if (ecfg.accessToken) {
|
|
93573
|
+
console.log(` logged in: yes${who} \u2014 attested daemon, can contribute`);
|
|
93487
93574
|
} else {
|
|
93488
|
-
console.log(` logged in: yes
|
|
93575
|
+
console.log(` logged in: yes${who} \u2014 key capability enforced by Console installation/scopes`);
|
|
93489
93576
|
}
|
|
93490
|
-
const active3 = getActiveAgent(
|
|
93577
|
+
const active3 = getActiveAgent(ecfg);
|
|
93491
93578
|
console.log(
|
|
93492
93579
|
` active agent: ${active3 ? `${active3.handle} (acting-as; \`errata use --none\` to clear)` : "default identity"}`
|
|
93493
93580
|
);
|
|
@@ -93499,7 +93586,7 @@ async function cmdStatus() {
|
|
|
93499
93586
|
console.log(` policy: blocked - ${decision.reason}`);
|
|
93500
93587
|
if (decision.guidance) console.log(` ${decision.guidance}`);
|
|
93501
93588
|
}
|
|
93502
|
-
if (hasCloudCredential(
|
|
93589
|
+
if (hasCloudCredential(ecfg)) {
|
|
93503
93590
|
if (!decision.allowed) {
|
|
93504
93591
|
console.log(
|
|
93505
93592
|
` reachable: ${inspection.reachable ? `yes (${inspection.probe})` : `no (${inspection.error ?? "unreachable"})`}`
|
|
@@ -93508,7 +93595,7 @@ async function cmdStatus() {
|
|
|
93508
93595
|
return;
|
|
93509
93596
|
}
|
|
93510
93597
|
try {
|
|
93511
|
-
const c = authedCloudClient(cfg);
|
|
93598
|
+
const c = shown.ok ? shown.client : authedCloudClient(cfg);
|
|
93512
93599
|
const me = await c.me();
|
|
93513
93600
|
console.log(` reachable: yes \xB7 authenticated as ${me.handle} (${me.tier})`);
|
|
93514
93601
|
} catch (err2) {
|
|
@@ -93603,19 +93690,26 @@ async function cmdWhoami(args2) {
|
|
|
93603
93690
|
if (identity.invalid) process.exitCode = 1;
|
|
93604
93691
|
return;
|
|
93605
93692
|
}
|
|
93606
|
-
|
|
93693
|
+
const shown = reportedIdentity(cfg, workspaceEntryForPath(ROOT));
|
|
93694
|
+
if (!shown.ok) {
|
|
93695
|
+
console.error(`${shown.reason} \u2014 this workspace's capture holds locally (see \`errata whoami --workspace\`)`);
|
|
93696
|
+
process.exitCode = 1;
|
|
93697
|
+
return;
|
|
93698
|
+
}
|
|
93699
|
+
if (!hasCloudCredential(shown.config)) {
|
|
93607
93700
|
console.error("not logged in \u2014 run `errata login` or select an installation profile");
|
|
93608
93701
|
process.exitCode = 1;
|
|
93609
93702
|
return;
|
|
93610
93703
|
}
|
|
93611
93704
|
try {
|
|
93612
|
-
const active3 = getActiveAgent(
|
|
93613
|
-
const response = await resolveWhoami(
|
|
93705
|
+
const active3 = getActiveAgent(shown.config);
|
|
93706
|
+
const response = await resolveWhoami(shown.client, active3?.handle ?? null);
|
|
93614
93707
|
if (args2.includes("--json")) {
|
|
93615
93708
|
console.log(JSON.stringify(response, null, 2));
|
|
93616
93709
|
return;
|
|
93617
93710
|
}
|
|
93618
|
-
|
|
93711
|
+
if (shown.note) console.log(`(${shown.note})`);
|
|
93712
|
+
for (const line of formatWhoami(response, shown.profileName ?? null)) console.log(line);
|
|
93619
93713
|
} catch (err2) {
|
|
93620
93714
|
console.error(`could not resolve context: ${err2 instanceof Error ? err2.message : err2}`);
|
|
93621
93715
|
process.exitCode = 1;
|
|
@@ -93625,6 +93719,11 @@ async function cmdDoctor(args2) {
|
|
|
93625
93719
|
const cfg = loadConfig();
|
|
93626
93720
|
const report = await diagnoseInstallation(cfg, {
|
|
93627
93721
|
...hasCodexConfig(process.cwd()) ? { codexHooks: () => diagnoseCodexHooks(process.cwd()) } : {},
|
|
93722
|
+
daemon: () => {
|
|
93723
|
+
const lockPath = globalDaemonLock();
|
|
93724
|
+
const lock = readDaemonLock(lockPath);
|
|
93725
|
+
return daemonDoctorCheck({ lock, state: daemonLockState(lock, true), selfVersion: DAEMON_VERSION, lockPath });
|
|
93726
|
+
},
|
|
93628
93727
|
inspect: () => inspectCloudEndpoint(cfg.cloudUrl),
|
|
93629
93728
|
authenticate: async () => {
|
|
93630
93729
|
const me = await authedCloudClient(cfg).me();
|
|
@@ -93641,7 +93740,7 @@ async function cmdDoctor(args2) {
|
|
|
93641
93740
|
const marker = check2.status === "pass" ? "\u2713" : check2.status === "warn" ? "!" : "\u2717";
|
|
93642
93741
|
console.log(` ${marker} ${check2.id}: ${check2.detail}`);
|
|
93643
93742
|
}
|
|
93644
|
-
if (
|
|
93743
|
+
if (report.checks.some((check2) => check2.status === "fail" && check2.id !== "daemon")) {
|
|
93645
93744
|
console.log(
|
|
93646
93745
|
" recovery: `errata profile list`, then `errata profile use <name>`; re-login if authentication still fails."
|
|
93647
93746
|
);
|
|
@@ -93707,7 +93806,8 @@ async function cmdUpdate(args2) {
|
|
|
93707
93806
|
}
|
|
93708
93807
|
console.log(`
|
|
93709
93808
|
[OK] updated to ${status.latest}. Restart the daemon to run it:`);
|
|
93710
|
-
console.log(` errata stop (
|
|
93809
|
+
console.log(` errata stop (waits for the old daemon to exit)`);
|
|
93810
|
+
console.log(` errata start (starts the updated one; autostart also relaunches it at next logon)`);
|
|
93711
93811
|
} else {
|
|
93712
93812
|
console.log(`
|
|
93713
93813
|
[X] npm install failed (exit ${code}). Try manually:`);
|
|
@@ -94344,7 +94444,7 @@ async function cmdReview() {
|
|
|
94344
94444
|
console.log("(review queue empty)");
|
|
94345
94445
|
return;
|
|
94346
94446
|
}
|
|
94347
|
-
const queue = JSON.parse(
|
|
94447
|
+
const queue = JSON.parse(readFileSync41(paths.reviewQueue, "utf8"));
|
|
94348
94448
|
if (queue.length === 0) {
|
|
94349
94449
|
console.log("(review queue empty)");
|
|
94350
94450
|
return;
|
|
@@ -95082,8 +95182,20 @@ async function cmdStop() {
|
|
|
95082
95182
|
return;
|
|
95083
95183
|
}
|
|
95084
95184
|
try {
|
|
95185
|
+
const lock = readDaemonLock(lockPath);
|
|
95085
95186
|
const result = stopLockedDaemon(lockPath);
|
|
95086
|
-
if (result === "signaled"
|
|
95187
|
+
if (result === "signaled" && lock) {
|
|
95188
|
+
console.log(`sent SIGTERM to the daemon (pid ${lock.pid}); waiting for it to exit\u2026`);
|
|
95189
|
+
if (await waitForDaemonExit(lock, STOP_WAIT_MS)) {
|
|
95190
|
+
stopLockedDaemon(lockPath);
|
|
95191
|
+
console.log(`daemon stopped \u2014 safe to start it again`);
|
|
95192
|
+
} else {
|
|
95193
|
+
console.warn(
|
|
95194
|
+
`daemon (pid ${lock.pid}) has not exited after ${STOP_WAIT_MS / 1e3}s; it may still hold port 7891 and its stores. Check it with \`ps -p ${lock.pid}\` (Windows: \`Get-Process -Id ${lock.pid}\`) before starting again.`
|
|
95195
|
+
);
|
|
95196
|
+
process.exitCode = 1;
|
|
95197
|
+
}
|
|
95198
|
+
} else if (result === "signaled") console.log(`sent SIGTERM to the verified daemon process`);
|
|
95087
95199
|
else if (result === "stale") console.log(`removed stale daemon lock; no process was signaled`);
|
|
95088
95200
|
else if (result === "missing") console.log(`no daemon lock found \u2014 nothing to stop`);
|
|
95089
95201
|
else throw new Error(`daemon lock ownership is ${result}; no process was signaled and the lock was preserved`);
|
|
@@ -95181,13 +95293,13 @@ async function cmdInstallHooks(args2) {
|
|
|
95181
95293
|
}
|
|
95182
95294
|
}
|
|
95183
95295
|
async function installOpencodePlugin(port) {
|
|
95184
|
-
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync:
|
|
95296
|
+
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync: readFileSync42, writeFileSync: writeFileSync30 } = await import("node:fs");
|
|
95185
95297
|
const { join: join49 } = await import("node:path");
|
|
95186
95298
|
const dir = join49(ROOT, ".opencode", "plugin");
|
|
95187
95299
|
if (!existsSync40(dir)) mkdirSync12(dir, { recursive: true });
|
|
95188
95300
|
const file2 = join49(dir, "inerrata.js");
|
|
95189
95301
|
if (existsSync40(file2)) {
|
|
95190
|
-
const head2 =
|
|
95302
|
+
const head2 = readFileSync42(file2, "utf8").split("\n")[0] ?? "";
|
|
95191
95303
|
if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
|
|
95192
95304
|
console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
|
|
95193
95305
|
process.exit(2);
|
|
@@ -95198,7 +95310,7 @@ async function installOpencodePlugin(port) {
|
|
|
95198
95310
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
95199
95311
|
if (existsSync40(cfgFile)) {
|
|
95200
95312
|
try {
|
|
95201
|
-
cfg = JSON.parse(
|
|
95313
|
+
cfg = JSON.parse(readFileSync42(cfgFile, "utf8"));
|
|
95202
95314
|
} catch {
|
|
95203
95315
|
console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
|
|
95204
95316
|
process.exit(2);
|
|
@@ -95244,7 +95356,7 @@ function installClaudeMods() {
|
|
|
95244
95356
|
}
|
|
95245
95357
|
}
|
|
95246
95358
|
async function installClaudeHooks(port) {
|
|
95247
|
-
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync:
|
|
95359
|
+
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync: readFileSync42, writeFileSync: writeFileSync30 } = await import("node:fs");
|
|
95248
95360
|
const { join: join49 } = await import("node:path");
|
|
95249
95361
|
const dir = join49(ROOT, ".claude");
|
|
95250
95362
|
if (!existsSync40(dir)) mkdirSync12(dir, { recursive: true });
|
|
@@ -95252,7 +95364,7 @@ async function installClaudeHooks(port) {
|
|
|
95252
95364
|
let settings = {};
|
|
95253
95365
|
if (existsSync40(file2)) {
|
|
95254
95366
|
try {
|
|
95255
|
-
settings = JSON.parse(
|
|
95367
|
+
settings = JSON.parse(readFileSync42(file2, "utf8"));
|
|
95256
95368
|
} catch {
|
|
95257
95369
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
95258
95370
|
process.exit(2);
|
|
@@ -95318,7 +95430,7 @@ async function installClaudeHooks(port) {
|
|
|
95318
95430
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
95319
95431
|
}
|
|
95320
95432
|
async function installClaudeMcpConfig() {
|
|
95321
|
-
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync:
|
|
95433
|
+
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync: readFileSync42, writeFileSync: writeFileSync30 } = await import("node:fs");
|
|
95322
95434
|
const { join: join49, dirname: dirname16 } = await import("node:path");
|
|
95323
95435
|
const file2 = join49(ROOT, ".mcp.json");
|
|
95324
95436
|
const dir = dirname16(file2);
|
|
@@ -95326,7 +95438,7 @@ async function installClaudeMcpConfig() {
|
|
|
95326
95438
|
let cfg = {};
|
|
95327
95439
|
if (existsSync40(file2)) {
|
|
95328
95440
|
try {
|
|
95329
|
-
cfg = JSON.parse(
|
|
95441
|
+
cfg = JSON.parse(readFileSync42(file2, "utf8"));
|
|
95330
95442
|
} catch {
|
|
95331
95443
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
95332
95444
|
process.exit(2);
|
|
@@ -95340,7 +95452,7 @@ async function installClaudeMcpConfig() {
|
|
|
95340
95452
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
95341
95453
|
}
|
|
95342
95454
|
async function installCursorMcpConfig() {
|
|
95343
|
-
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync:
|
|
95455
|
+
const { mkdirSync: mkdirSync12, existsSync: existsSync40, readFileSync: readFileSync42, writeFileSync: writeFileSync30 } = await import("node:fs");
|
|
95344
95456
|
const { join: join49 } = await import("node:path");
|
|
95345
95457
|
const dir = join49(ROOT, ".cursor");
|
|
95346
95458
|
if (!existsSync40(dir)) mkdirSync12(dir, { recursive: true });
|
|
@@ -95348,7 +95460,7 @@ async function installCursorMcpConfig() {
|
|
|
95348
95460
|
let cfg = {};
|
|
95349
95461
|
if (existsSync40(file2)) {
|
|
95350
95462
|
try {
|
|
95351
|
-
cfg = JSON.parse(
|
|
95463
|
+
cfg = JSON.parse(readFileSync42(file2, "utf8"));
|
|
95352
95464
|
} catch {
|
|
95353
95465
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
95354
95466
|
process.exit(2);
|
|
@@ -95551,7 +95663,21 @@ function installLogTimestamps() {
|
|
|
95551
95663
|
};
|
|
95552
95664
|
}
|
|
95553
95665
|
}
|
|
95666
|
+
function followLogHint() {
|
|
95667
|
+
const log = daemonLogPath();
|
|
95668
|
+
return process.platform === "win32" ? `Get-Content -Wait "${log}"` : `tail -f "${log}"`;
|
|
95669
|
+
}
|
|
95554
95670
|
async function cmdDash(args2) {
|
|
95671
|
+
const running = readDaemonLock(globalDaemonLock());
|
|
95672
|
+
if (running && daemonLockState(running, true) === "running") {
|
|
95673
|
+
console.log(
|
|
95674
|
+
`errata daemon already running \xB7 pid ${running.pid}${running.version ? ` \xB7 ${running.version}` : ""}${running.webUiUrl ? ` \xB7 ${running.webUiUrl}` : ""}`
|
|
95675
|
+
);
|
|
95676
|
+
console.log(` follow it: ${followLogHint()}`);
|
|
95677
|
+
console.log(` check it: errata status`);
|
|
95678
|
+
console.log(` restart it: errata stop, then errata start`);
|
|
95679
|
+
return;
|
|
95680
|
+
}
|
|
95555
95681
|
process.title = "errata-daemon";
|
|
95556
95682
|
installLogTimestamps();
|
|
95557
95683
|
refreshExistingCodexHooks();
|
|
@@ -95921,6 +96047,11 @@ async function cmdDash(args2) {
|
|
|
95921
96047
|
const shutdown = async (signal) => {
|
|
95922
96048
|
console.log(`
|
|
95923
96049
|
shutting down\u2026 (${signal})`);
|
|
96050
|
+
setTimeout(() => {
|
|
96051
|
+
console.warn(`[errata] shutdown exceeded ${SHUTDOWN_DEADLINE_MS / 1e3}s \u2014 forcing exit`);
|
|
96052
|
+
releaseOwnLock(globalDaemonLock());
|
|
96053
|
+
process.exit(1);
|
|
96054
|
+
}, SHUTDOWN_DEADLINE_MS).unref();
|
|
95924
96055
|
clearInterval(interval);
|
|
95925
96056
|
clearInterval(nightlyInterval);
|
|
95926
96057
|
if (quiesceTimer) clearTimeout(quiesceTimer);
|