@inerrata-corporation/errata 2.0.0-dev.47 → 2.0.0-dev.49
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 +143 -45
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -20946,6 +20946,20 @@ var init_client = __esm({
|
|
|
20946
20946
|
async createProject(name2) {
|
|
20947
20947
|
return this.json("POST", "/api/gate/projects/create", { name: name2 });
|
|
20948
20948
|
}
|
|
20949
|
+
/** Read-only discovery (PJ-attach clone tripwire): the org's claim on a
|
|
20950
|
+
* locator, or null. NEVER creates — 404 means the org hasn't linked it. */
|
|
20951
|
+
async lookupProject(locator) {
|
|
20952
|
+
try {
|
|
20953
|
+
const res = await this.json(
|
|
20954
|
+
"GET",
|
|
20955
|
+
`/api/gate/projects/lookup?locator=${encodeURIComponent(locator)}`
|
|
20956
|
+
);
|
|
20957
|
+
return res.project;
|
|
20958
|
+
} catch (err2) {
|
|
20959
|
+
if (err2 instanceof CloudError && err2.status === 404) return null;
|
|
20960
|
+
throw err2;
|
|
20961
|
+
}
|
|
20962
|
+
}
|
|
20949
20963
|
// ─── ingest ────────────────────────────────────────────────────────
|
|
20950
20964
|
/** Upload one outbox batch (projected onto the reconciled wire) and fold
|
|
20951
20965
|
* the per-decision response into flush accounting.
|
|
@@ -21422,7 +21436,10 @@ function defaultConfig() {
|
|
|
21422
21436
|
oauthClientId: null,
|
|
21423
21437
|
userId: null,
|
|
21424
21438
|
email: null,
|
|
21425
|
-
|
|
21439
|
+
// contributePackages defaults ON — the dependency backbone rides project
|
|
21440
|
+
// linking (see ConsentConfig). Still `sync`-gated: nothing ships until the
|
|
21441
|
+
// user opts into sync at all.
|
|
21442
|
+
consent: { sync: false, telemetry: false, contributePackages: true },
|
|
21426
21443
|
notifications: true,
|
|
21427
21444
|
onboardedAt: null,
|
|
21428
21445
|
machineId: null,
|
|
@@ -38269,8 +38286,8 @@ var init_report_render = __esm({
|
|
|
38269
38286
|
|
|
38270
38287
|
// src/cli.ts
|
|
38271
38288
|
init_src5();
|
|
38272
|
-
import { closeSync as closeSync2, existsSync as
|
|
38273
|
-
import { join as
|
|
38289
|
+
import { closeSync as closeSync2, existsSync as existsSync22, openSync as openSync2, readFileSync as readFileSync20, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
|
|
38290
|
+
import { join as join25 } from "node:path";
|
|
38274
38291
|
import { spawn as spawn3 } from "node:child_process";
|
|
38275
38292
|
|
|
38276
38293
|
// src/daemon.ts
|
|
@@ -39586,9 +39603,9 @@ var NodeFsHandler = class {
|
|
|
39586
39603
|
if (this.fsw.closed) {
|
|
39587
39604
|
return;
|
|
39588
39605
|
}
|
|
39589
|
-
const
|
|
39606
|
+
const dirname9 = sysPath.dirname(file2);
|
|
39590
39607
|
const basename5 = sysPath.basename(file2);
|
|
39591
|
-
const parent = this.fsw._getWatchedDir(
|
|
39608
|
+
const parent = this.fsw._getWatchedDir(dirname9);
|
|
39592
39609
|
let prevStats = stats;
|
|
39593
39610
|
if (parent.has(basename5))
|
|
39594
39611
|
return;
|
|
@@ -39615,7 +39632,7 @@ var NodeFsHandler = class {
|
|
|
39615
39632
|
prevStats = newStats2;
|
|
39616
39633
|
}
|
|
39617
39634
|
} catch (error48) {
|
|
39618
|
-
this.fsw._remove(
|
|
39635
|
+
this.fsw._remove(dirname9, basename5);
|
|
39619
39636
|
}
|
|
39620
39637
|
} else if (parent.has(basename5)) {
|
|
39621
39638
|
const at = newStats.atimeMs;
|
|
@@ -42679,7 +42696,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
42679
42696
|
}
|
|
42680
42697
|
|
|
42681
42698
|
// src/engine.ts
|
|
42682
|
-
var DAEMON_VERSION = true ? "2.0.0-dev.
|
|
42699
|
+
var DAEMON_VERSION = true ? "2.0.0-dev.49" : "2.0.0-alpha.0";
|
|
42683
42700
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
42684
42701
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
42685
42702
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -44761,6 +44778,48 @@ async function ensureProjectLink(root, profile, client) {
|
|
|
44761
44778
|
}
|
|
44762
44779
|
}
|
|
44763
44780
|
|
|
44781
|
+
// src/adopt.ts
|
|
44782
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
44783
|
+
import { dirname as dirname8, join as join24 } from "node:path";
|
|
44784
|
+
function findGitRoot(absPath) {
|
|
44785
|
+
let dir = absPath;
|
|
44786
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
44787
|
+
if (existsSync21(join24(dir, ".git"))) return dir;
|
|
44788
|
+
const parent = dirname8(dir);
|
|
44789
|
+
if (parent === dir) return null;
|
|
44790
|
+
dir = parent;
|
|
44791
|
+
}
|
|
44792
|
+
return null;
|
|
44793
|
+
}
|
|
44794
|
+
var RETRY_COOLDOWN_MS = 15 * 6e4;
|
|
44795
|
+
function createRootAdopter(deps) {
|
|
44796
|
+
const attempted = /* @__PURE__ */ new Map();
|
|
44797
|
+
let chain = Promise.resolve();
|
|
44798
|
+
const tryAdopt = async (path2) => {
|
|
44799
|
+
if (!deps.linkingAllowed()) return;
|
|
44800
|
+
const root = findGitRoot(path2);
|
|
44801
|
+
if (!root || deps.isKnownRoot(root)) return;
|
|
44802
|
+
const last = attempted.get(root);
|
|
44803
|
+
const now = Date.now();
|
|
44804
|
+
if (last !== void 0 && now - last < RETRY_COOLDOWN_MS) return;
|
|
44805
|
+
attempted.set(root, now);
|
|
44806
|
+
if (!resolveGitDir(root)) return;
|
|
44807
|
+
const locator = detectRepoLocator(root);
|
|
44808
|
+
if (!locator) return;
|
|
44809
|
+
const claimed = await deps.lookup(locator);
|
|
44810
|
+
if (!claimed) return;
|
|
44811
|
+
await deps.adopt(root);
|
|
44812
|
+
deps.log(`[errata] adopted ${root} \u2014 ${locator} is claimed by your org (project ${claimed.id})`);
|
|
44813
|
+
};
|
|
44814
|
+
return {
|
|
44815
|
+
noteMiss(path2) {
|
|
44816
|
+
if (!path2) return;
|
|
44817
|
+
chain = chain.then(() => tryAdopt(path2)).catch(() => void 0);
|
|
44818
|
+
},
|
|
44819
|
+
idle: () => chain
|
|
44820
|
+
};
|
|
44821
|
+
}
|
|
44822
|
+
|
|
44764
44823
|
// src/multi.ts
|
|
44765
44824
|
function normPath(p) {
|
|
44766
44825
|
return p.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
|
|
@@ -45023,7 +45082,10 @@ async function startMultiDaemon(opts = {}) {
|
|
|
45023
45082
|
return c.json({ error: "bad-json" }, 400);
|
|
45024
45083
|
}
|
|
45025
45084
|
const owner = ownerOf(records, pathInBody(body2));
|
|
45026
|
-
if (!owner)
|
|
45085
|
+
if (!owner) {
|
|
45086
|
+
rootAdopter.noteMiss(pathInBody(body2));
|
|
45087
|
+
return c.json({ error: "no-matching-project" }, 404);
|
|
45088
|
+
}
|
|
45027
45089
|
const sub = c.req.path;
|
|
45028
45090
|
const done = markPass(`${sub}:${owner.entry.name}`);
|
|
45029
45091
|
try {
|
|
@@ -45116,6 +45178,25 @@ async function startMultiDaemon(opts = {}) {
|
|
|
45116
45178
|
if (opts.reindexOnStart !== false && records.length > 0) {
|
|
45117
45179
|
void reindexAll({ skipEmbed: opts.skipEmbed ?? true });
|
|
45118
45180
|
}
|
|
45181
|
+
const rootAdopter = createRootAdopter({
|
|
45182
|
+
isKnownRoot: (root) => pickOwnerRoot(records.map((r) => r.root), root) !== null,
|
|
45183
|
+
linkingAllowed: () => {
|
|
45184
|
+
const c = loadConfig();
|
|
45185
|
+
return c.consent.sync && hasCloudCredential(c);
|
|
45186
|
+
},
|
|
45187
|
+
lookup: async (locator) => cloudNow().lookupProject(locator),
|
|
45188
|
+
adopt: async (root) => {
|
|
45189
|
+
let profile = loadProfile(root);
|
|
45190
|
+
if (!profile) {
|
|
45191
|
+
profile = autodetectProfile(root);
|
|
45192
|
+
saveProfile(root, profile);
|
|
45193
|
+
}
|
|
45194
|
+
registerWorkspace(profile, root);
|
|
45195
|
+
attachWorkspace(root);
|
|
45196
|
+
},
|
|
45197
|
+
// eslint-disable-next-line no-console
|
|
45198
|
+
log: (line) => console.log(line)
|
|
45199
|
+
});
|
|
45119
45200
|
const ambientLinkAll = async () => {
|
|
45120
45201
|
const c = loadConfig();
|
|
45121
45202
|
if (!c.consent.sync || !hasCloudCredential(c)) return;
|
|
@@ -46009,21 +46090,21 @@ async function cmdInit() {
|
|
|
46009
46090
|
if (!skipHooks) {
|
|
46010
46091
|
console.log("");
|
|
46011
46092
|
console.log("installing harness hooks...");
|
|
46012
|
-
const { existsSync:
|
|
46013
|
-
const { join:
|
|
46093
|
+
const { existsSync: existsSync23 } = await import("node:fs");
|
|
46094
|
+
const { join: join26 } = await import("node:path");
|
|
46014
46095
|
try {
|
|
46015
46096
|
await installClaudeHooks(port);
|
|
46016
46097
|
} catch (err2) {
|
|
46017
46098
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
46018
46099
|
}
|
|
46019
|
-
if (
|
|
46100
|
+
if (existsSync23(join26(ROOT, ".cursor"))) {
|
|
46020
46101
|
try {
|
|
46021
46102
|
await installCursorMcpConfig();
|
|
46022
46103
|
} catch (err2) {
|
|
46023
46104
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
46024
46105
|
}
|
|
46025
46106
|
}
|
|
46026
|
-
if (
|
|
46107
|
+
if (existsSync23(join26(ROOT, ".codex"))) {
|
|
46027
46108
|
try {
|
|
46028
46109
|
await installCodexHooks(port);
|
|
46029
46110
|
} catch (err2) {
|
|
@@ -46097,6 +46178,23 @@ async function cmdNotifyTest() {
|
|
|
46097
46178
|
}
|
|
46098
46179
|
}
|
|
46099
46180
|
async function cmdStart() {
|
|
46181
|
+
if (!loadProfile(ROOT)) {
|
|
46182
|
+
const cfg = loadConfig();
|
|
46183
|
+
const locator = detectRepoLocator(ROOT);
|
|
46184
|
+
if (locator && cfg.consent.sync && hasCloudCredential(cfg)) {
|
|
46185
|
+
try {
|
|
46186
|
+
const claimed = await authedCloudClient(cfg).lookupProject(locator);
|
|
46187
|
+
if (claimed) {
|
|
46188
|
+
const adopted = autodetectProfile(ROOT);
|
|
46189
|
+
saveProfile(ROOT, adopted);
|
|
46190
|
+
console.log(
|
|
46191
|
+
`adopted: ${locator} is claimed by your org (project ${claimed.id}) \u2014 workspace initialized`
|
|
46192
|
+
);
|
|
46193
|
+
}
|
|
46194
|
+
} catch {
|
|
46195
|
+
}
|
|
46196
|
+
}
|
|
46197
|
+
}
|
|
46100
46198
|
await ensureProfile();
|
|
46101
46199
|
const profile = loadProfile(ROOT);
|
|
46102
46200
|
if (profile) registerWorkspace(profile, ROOT);
|
|
@@ -46160,8 +46258,8 @@ async function cmdStatus() {
|
|
|
46160
46258
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
46161
46259
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
46162
46260
|
}
|
|
46163
|
-
console.log(` graph db: ${
|
|
46164
|
-
console.log(` event log: ${
|
|
46261
|
+
console.log(` graph db: ${existsSync22(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
46262
|
+
console.log(` event log: ${existsSync22(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
46165
46263
|
const lockPath = globalDaemonLock();
|
|
46166
46264
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
46167
46265
|
console.log(
|
|
@@ -46576,7 +46674,7 @@ async function cmdUse(args2) {
|
|
|
46576
46674
|
}
|
|
46577
46675
|
async function cmdReview() {
|
|
46578
46676
|
const paths = workspacePaths(ROOT);
|
|
46579
|
-
if (!
|
|
46677
|
+
if (!existsSync22(paths.reviewQueue)) {
|
|
46580
46678
|
console.log("(review queue empty)");
|
|
46581
46679
|
return;
|
|
46582
46680
|
}
|
|
@@ -47210,7 +47308,7 @@ async function gatherRepo(store, ws) {
|
|
|
47210
47308
|
};
|
|
47211
47309
|
}
|
|
47212
47310
|
async function gatherReportData(generatedAt) {
|
|
47213
|
-
const { existsSync:
|
|
47311
|
+
const { existsSync: existsSync23 } = await import("node:fs");
|
|
47214
47312
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
47215
47313
|
const cfg = loadConfig();
|
|
47216
47314
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -47218,7 +47316,7 @@ async function gatherReportData(generatedAt) {
|
|
|
47218
47316
|
for (const ws of listWorkspaces()) {
|
|
47219
47317
|
if (ws.missing) continue;
|
|
47220
47318
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
47221
|
-
if (!
|
|
47319
|
+
if (!existsSync23(dbPath)) continue;
|
|
47222
47320
|
let store = null;
|
|
47223
47321
|
try {
|
|
47224
47322
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -47262,8 +47360,8 @@ async function cmdReport(args2) {
|
|
|
47262
47360
|
const outDir = workspacePaths(ROOT).configDir;
|
|
47263
47361
|
mkdirSync6(outDir, { recursive: true });
|
|
47264
47362
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
47265
|
-
for (const f of files) writeFileSync16(
|
|
47266
|
-
const indexPath =
|
|
47363
|
+
for (const f of files) writeFileSync16(join25(outDir, f.name), f.html, "utf8");
|
|
47364
|
+
const indexPath = join25(outDir, "report.html");
|
|
47267
47365
|
console.log(`report \u2192 ${indexPath}`);
|
|
47268
47366
|
console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
|
|
47269
47367
|
console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
|
|
@@ -47383,13 +47481,13 @@ function hookRelayCommand(port, path2) {
|
|
|
47383
47481
|
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
|
|
47384
47482
|
}
|
|
47385
47483
|
async function installClaudeHooks(port) {
|
|
47386
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
47387
|
-
const { join:
|
|
47388
|
-
const dir =
|
|
47389
|
-
if (!
|
|
47390
|
-
const file2 =
|
|
47484
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
47485
|
+
const { join: join26 } = await import("node:path");
|
|
47486
|
+
const dir = join26(ROOT, ".claude");
|
|
47487
|
+
if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
|
|
47488
|
+
const file2 = join26(dir, "settings.json");
|
|
47391
47489
|
let settings = {};
|
|
47392
|
-
if (
|
|
47490
|
+
if (existsSync23(file2)) {
|
|
47393
47491
|
try {
|
|
47394
47492
|
settings = JSON.parse(readFileSync21(file2, "utf8"));
|
|
47395
47493
|
} catch {
|
|
@@ -47440,7 +47538,7 @@ async function installClaudeHooks(port) {
|
|
|
47440
47538
|
writeFileSync16(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
47441
47539
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
47442
47540
|
await installClaudeMcpConfig();
|
|
47443
|
-
const claudeMd =
|
|
47541
|
+
const claudeMd = join26(ROOT, "CLAUDE.md");
|
|
47444
47542
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
47445
47543
|
if (recall.kind === "collision") {
|
|
47446
47544
|
console.warn(
|
|
@@ -47452,13 +47550,13 @@ async function installClaudeHooks(port) {
|
|
|
47452
47550
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
47453
47551
|
}
|
|
47454
47552
|
async function installClaudeMcpConfig() {
|
|
47455
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
47456
|
-
const { join:
|
|
47457
|
-
const file2 =
|
|
47458
|
-
const dir =
|
|
47459
|
-
if (!
|
|
47553
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
47554
|
+
const { join: join26, dirname: dirname9 } = await import("node:path");
|
|
47555
|
+
const file2 = join26(ROOT, ".mcp.json");
|
|
47556
|
+
const dir = dirname9(file2);
|
|
47557
|
+
if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
|
|
47460
47558
|
let cfg = {};
|
|
47461
|
-
if (
|
|
47559
|
+
if (existsSync23(file2)) {
|
|
47462
47560
|
try {
|
|
47463
47561
|
cfg = JSON.parse(readFileSync21(file2, "utf8"));
|
|
47464
47562
|
} catch {
|
|
@@ -47474,13 +47572,13 @@ async function installClaudeMcpConfig() {
|
|
|
47474
47572
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
47475
47573
|
}
|
|
47476
47574
|
async function installCursorMcpConfig() {
|
|
47477
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
47478
|
-
const { join:
|
|
47479
|
-
const dir =
|
|
47480
|
-
if (!
|
|
47481
|
-
const file2 =
|
|
47575
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
47576
|
+
const { join: join26 } = await import("node:path");
|
|
47577
|
+
const dir = join26(ROOT, ".cursor");
|
|
47578
|
+
if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
|
|
47579
|
+
const file2 = join26(dir, "mcp.json");
|
|
47482
47580
|
let cfg = {};
|
|
47483
|
-
if (
|
|
47581
|
+
if (existsSync23(file2)) {
|
|
47484
47582
|
try {
|
|
47485
47583
|
cfg = JSON.parse(readFileSync21(file2, "utf8"));
|
|
47486
47584
|
} catch {
|
|
@@ -47498,15 +47596,15 @@ async function installCursorMcpConfig() {
|
|
|
47498
47596
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
47499
47597
|
}
|
|
47500
47598
|
async function installCodexHooks(port) {
|
|
47501
|
-
const { mkdirSync: mkdirSync6, existsSync:
|
|
47502
|
-
const { join:
|
|
47503
|
-
const dir =
|
|
47504
|
-
if (!
|
|
47505
|
-
const file2 =
|
|
47599
|
+
const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
47600
|
+
const { join: join26 } = await import("node:path");
|
|
47601
|
+
const dir = join26(ROOT, ".codex");
|
|
47602
|
+
if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
|
|
47603
|
+
const file2 = join26(dir, "config.toml");
|
|
47506
47604
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
47507
47605
|
const END = `# <<< errata hooks`;
|
|
47508
47606
|
let existing = "";
|
|
47509
|
-
if (
|
|
47607
|
+
if (existsSync23(file2)) {
|
|
47510
47608
|
existing = readFileSync21(file2, "utf8");
|
|
47511
47609
|
const beginIdx = existing.indexOf(BEGIN);
|
|
47512
47610
|
const endIdx = existing.indexOf(END);
|
|
@@ -47799,7 +47897,7 @@ async function cmdDash(args2) {
|
|
|
47799
47897
|
await yieldToLoop2();
|
|
47800
47898
|
try {
|
|
47801
47899
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
47802
|
-
const res = bleedRules(
|
|
47900
|
+
const res = bleedRules(join25(r.root, ".claude", "rules"), items);
|
|
47803
47901
|
if (res.written || res.pruned) {
|
|
47804
47902
|
console.log(
|
|
47805
47903
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|