@inerrata-corporation/errata 2.0.2-dev.245 → 2.0.2-dev.249
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/consolidate-worker.mjs +112 -16
- package/errata.mjs +402 -231
- package/package.json +1 -1
- package/pass-worker.mjs +112 -16
package/errata.mjs
CHANGED
|
@@ -16410,6 +16410,21 @@ var init_src2 = __esm({
|
|
|
16410
16410
|
});
|
|
16411
16411
|
|
|
16412
16412
|
// ../../packages/local-graph/src/store.ts
|
|
16413
|
+
function localEdgeViolation(fromLabel, type, toLabel) {
|
|
16414
|
+
if (type in LOCAL_RULE_OVERRIDES) {
|
|
16415
|
+
const rule = LOCAL_RULE_OVERRIDES[type];
|
|
16416
|
+
if (!rule) return null;
|
|
16417
|
+
if (fromLabel && rule.from && !rule.from.includes(fromLabel)) {
|
|
16418
|
+
return `${type} cannot originate from ${fromLabel} locally (allowed: ${rule.from.join(", ")})`;
|
|
16419
|
+
}
|
|
16420
|
+
if (toLabel && rule.to && !rule.to.includes(toLabel)) {
|
|
16421
|
+
return `${type} cannot target ${toLabel} locally (allowed: ${rule.to.join(", ")})`;
|
|
16422
|
+
}
|
|
16423
|
+
return null;
|
|
16424
|
+
}
|
|
16425
|
+
const verdict = isValidEdge(fromLabel, type, toLabel);
|
|
16426
|
+
return verdict.ok ? null : verdict.reason ?? "edge rule violation";
|
|
16427
|
+
}
|
|
16413
16428
|
function encodeEmbedding(emb) {
|
|
16414
16429
|
if (!emb || emb.length === 0) return null;
|
|
16415
16430
|
const f = Float32Array.from(emb);
|
|
@@ -16484,7 +16499,7 @@ var init_store = __esm({
|
|
|
16484
16499
|
REVEALED_BY: null,
|
|
16485
16500
|
PRODUCED: null
|
|
16486
16501
|
};
|
|
16487
|
-
SCHEMA_VERSION =
|
|
16502
|
+
SCHEMA_VERSION = 6;
|
|
16488
16503
|
SCHEMA_SQL = `
|
|
16489
16504
|
CREATE TABLE IF NOT EXISTS schema_version (
|
|
16490
16505
|
version INTEGER PRIMARY KEY
|
|
@@ -16499,6 +16514,21 @@ CREATE TABLE IF NOT EXISTS store_meta (
|
|
|
16499
16514
|
value TEXT NOT NULL
|
|
16500
16515
|
);
|
|
16501
16516
|
|
|
16517
|
+
-- Durable ledger of edges the ontology gate REFUSED, keyed by edge type.
|
|
16518
|
+
-- Durable rather than in-memory for one specific reason: the status command runs
|
|
16519
|
+
-- in a SEPARATE process and opens its own store handle, so a counter living on
|
|
16520
|
+
-- the instance reads 0 there forever. That is exactly how a producer rejecting
|
|
16521
|
+
-- 100% of its output stayed invisible for 17 days. Persisting it also survives
|
|
16522
|
+
-- the daemon restart that would otherwise erase the evidence.
|
|
16523
|
+
-- Keyed by type because a systematic producer bug shows up as ONE type
|
|
16524
|
+
-- dominating; sample keeps the latest reason so the count is actionable.
|
|
16525
|
+
CREATE TABLE IF NOT EXISTS edge_rejections (
|
|
16526
|
+
type TEXT PRIMARY KEY,
|
|
16527
|
+
count INTEGER NOT NULL DEFAULT 0,
|
|
16528
|
+
last_at INTEGER NOT NULL,
|
|
16529
|
+
sample TEXT
|
|
16530
|
+
);
|
|
16531
|
+
|
|
16502
16532
|
CREATE TABLE IF NOT EXISTS nodes (
|
|
16503
16533
|
id TEXT PRIMARY KEY,
|
|
16504
16534
|
label TEXT NOT NULL,
|
|
@@ -16818,6 +16848,16 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
16818
16848
|
if (!cols.has(name2)) this.db.exec(ddl);
|
|
16819
16849
|
}
|
|
16820
16850
|
}
|
|
16851
|
+
if (from < 6) {
|
|
16852
|
+
this.db.exec(`
|
|
16853
|
+
CREATE TABLE IF NOT EXISTS edge_rejections (
|
|
16854
|
+
type TEXT PRIMARY KEY,
|
|
16855
|
+
count INTEGER NOT NULL DEFAULT 0,
|
|
16856
|
+
last_at INTEGER NOT NULL,
|
|
16857
|
+
sample TEXT
|
|
16858
|
+
)
|
|
16859
|
+
`);
|
|
16860
|
+
}
|
|
16821
16861
|
this.db.prepare("UPDATE schema_version SET version = ?").run(SCHEMA_VERSION);
|
|
16822
16862
|
});
|
|
16823
16863
|
}
|
|
@@ -16899,6 +16939,7 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
16899
16939
|
const violation = this.edgeRuleViolation(edge2);
|
|
16900
16940
|
if (violation) {
|
|
16901
16941
|
this.rejectedEdgeCount++;
|
|
16942
|
+
this.recordEdgeRejection(edge2.type, violation, edge2.lastSeenAt || edge2.createdAt || 0);
|
|
16902
16943
|
console.warn(`[local-graph] rejected edge ${edge2.from}-[:${edge2.type}]->${edge2.to}: ${violation}`);
|
|
16903
16944
|
return;
|
|
16904
16945
|
}
|
|
@@ -16923,22 +16964,51 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
16923
16964
|
* overlay consulted first. Returns the reason string on a documented-
|
|
16924
16965
|
* forbidden combination, else null. Point lookups on the id PK — negligible
|
|
16925
16966
|
* next to the insert itself. */
|
|
16926
|
-
|
|
16927
|
-
|
|
16928
|
-
|
|
16929
|
-
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16967
|
+
/** Upsert one refusal into the durable ledger. Best-effort: a bookkeeping
|
|
16968
|
+
* failure must never turn a refused edge into a thrown write. */
|
|
16969
|
+
recordEdgeRejection(type, reason, at) {
|
|
16970
|
+
try {
|
|
16971
|
+
this.db.prepare(
|
|
16972
|
+
`INSERT INTO edge_rejections (type, count, last_at, sample) VALUES (?, 1, ?, ?)
|
|
16973
|
+
ON CONFLICT(type) DO UPDATE SET
|
|
16974
|
+
count = count + 1, last_at = excluded.last_at, sample = excluded.sample`
|
|
16975
|
+
).run(type, at, reason.slice(0, 200));
|
|
16976
|
+
} catch {
|
|
16977
|
+
}
|
|
16978
|
+
}
|
|
16979
|
+
/** Refusals recorded by the ontology gate, per edge type, newest activity first.
|
|
16980
|
+
* Durable across restarts and readable from any process (see the table note). */
|
|
16981
|
+
edgeRejections() {
|
|
16982
|
+
try {
|
|
16983
|
+
return this.db.prepare(
|
|
16984
|
+
"SELECT type, count, last_at AS lastAt, sample FROM edge_rejections ORDER BY count DESC, last_at DESC"
|
|
16985
|
+
).all();
|
|
16986
|
+
} catch {
|
|
16987
|
+
return [];
|
|
16988
|
+
}
|
|
16989
|
+
}
|
|
16990
|
+
/** Drop ledger entries whose last refusal predates `cutoff`. A still-misbehaving
|
|
16991
|
+
* producer keeps refreshing `last_at` and survives; a fixed one fades out. */
|
|
16992
|
+
pruneEdgeRejections(cutoff) {
|
|
16993
|
+
try {
|
|
16994
|
+
this.db.prepare("DELETE FROM edge_rejections WHERE last_at < ?").run(cutoff);
|
|
16995
|
+
} catch {
|
|
16996
|
+
}
|
|
16997
|
+
}
|
|
16998
|
+
/** Clear the ledger outright, whole or per type — operator escape hatch. */
|
|
16999
|
+
clearEdgeRejections(type) {
|
|
17000
|
+
try {
|
|
17001
|
+
if (type) this.db.prepare("DELETE FROM edge_rejections WHERE type = ?").run(type);
|
|
17002
|
+
else this.db.exec("DELETE FROM edge_rejections");
|
|
17003
|
+
} catch {
|
|
16939
17004
|
}
|
|
16940
|
-
|
|
16941
|
-
|
|
17005
|
+
}
|
|
17006
|
+
edgeRuleViolation(edge2) {
|
|
17007
|
+
return localEdgeViolation(
|
|
17008
|
+
this.getNode(edge2.from)?.label,
|
|
17009
|
+
edge2.type,
|
|
17010
|
+
this.getNode(edge2.to)?.label
|
|
17011
|
+
);
|
|
16942
17012
|
}
|
|
16943
17013
|
updateEdge(id, patch) {
|
|
16944
17014
|
this.stmts.updateEdge.run({
|
|
@@ -17075,6 +17145,32 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
17075
17145
|
const rows = this.db.prepare("SELECT from_id, to_id, type FROM edges WHERE valid_to IS NULL").all();
|
|
17076
17146
|
return rows.map((r) => ({ from: r.from_id, to: r.to_id, type: r.type }));
|
|
17077
17147
|
}
|
|
17148
|
+
/**
|
|
17149
|
+
* Live edges WITH their endpoint labels and ids, resolved in ONE join.
|
|
17150
|
+
*
|
|
17151
|
+
* The ontology sweep needs (id, type, fromLabel, toLabel) for every live edge.
|
|
17152
|
+
* Doing that as `scanLiveEdges()` + two `getNode()` calls is 2N node reads —
|
|
17153
|
+
* 550,000 on this store — and each one deserializes the node's embedding blob.
|
|
17154
|
+
* Measured: the sweep did not finish in 10 minutes. As a single join it is one
|
|
17155
|
+
* query over an index-covered scan. Labels only; nothing here touches embeddings.
|
|
17156
|
+
*/
|
|
17157
|
+
scanLiveEdgeRows() {
|
|
17158
|
+
const rows = this.db.prepare(
|
|
17159
|
+
`SELECT e.id, e.from_id, e.to_id, e.type, a.label AS from_label, b.label AS to_label
|
|
17160
|
+
FROM edges e
|
|
17161
|
+
LEFT JOIN nodes a ON a.id = e.from_id AND a.valid_to IS NULL
|
|
17162
|
+
LEFT JOIN nodes b ON b.id = e.to_id AND b.valid_to IS NULL
|
|
17163
|
+
WHERE e.valid_to IS NULL`
|
|
17164
|
+
).all();
|
|
17165
|
+
return rows.map((r) => ({
|
|
17166
|
+
id: r.id,
|
|
17167
|
+
from: r.from_id,
|
|
17168
|
+
to: r.to_id,
|
|
17169
|
+
type: r.type,
|
|
17170
|
+
fromLabel: r.from_label ?? void 0,
|
|
17171
|
+
toLabel: r.to_label ?? void 0
|
|
17172
|
+
}));
|
|
17173
|
+
}
|
|
17078
17174
|
/** Live nodes whose attrs.relPath is one of `relPaths`. Uses the nodes_relpath
|
|
17079
17175
|
* expression index so the incremental reindex fetches only the changed files'
|
|
17080
17176
|
* symbols instead of scanning every versioned node. */
|
|
@@ -20879,6 +20975,7 @@ __export(src_exports2, {
|
|
|
20879
20975
|
linkProblemToPackages: () => linkProblemToPackages,
|
|
20880
20976
|
linkProblemToSymbols: () => linkProblemToSymbols,
|
|
20881
20977
|
listNeedsRevisit: () => listNeedsRevisit,
|
|
20978
|
+
localEdgeViolation: () => localEdgeViolation,
|
|
20882
20979
|
markRevisit: () => markRevisit,
|
|
20883
20980
|
matchLanguagesInText: () => matchLanguagesInText,
|
|
20884
20981
|
matchPackagesInText: () => matchPackagesInText,
|
|
@@ -21643,7 +21740,6 @@ var init_oauth = __esm({
|
|
|
21643
21740
|
|
|
21644
21741
|
// ../../packages/cloud-client/src/client.ts
|
|
21645
21742
|
import { randomUUID } from "node:crypto";
|
|
21646
|
-
import { gzipSync } from "node:zlib";
|
|
21647
21743
|
function wirePerContext(value) {
|
|
21648
21744
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
21649
21745
|
const out2 = {};
|
|
@@ -21863,7 +21959,7 @@ function provenanceHeaders(provenance) {
|
|
|
21863
21959
|
...provenance.agentModel ? { "x-inerrata-agent-model": provenance.agentModel } : {}
|
|
21864
21960
|
};
|
|
21865
21961
|
}
|
|
21866
|
-
var asWireCount, INGEST_NODE_CHUNK,
|
|
21962
|
+
var asWireCount, INGEST_NODE_CHUNK, CloudClient, CloudError;
|
|
21867
21963
|
var init_client = __esm({
|
|
21868
21964
|
"../../packages/cloud-client/src/client.ts"() {
|
|
21869
21965
|
"use strict";
|
|
@@ -21871,7 +21967,6 @@ var init_client = __esm({
|
|
|
21871
21967
|
init_src();
|
|
21872
21968
|
asWireCount = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0 ? Math.floor(n) : null;
|
|
21873
21969
|
INGEST_NODE_CHUNK = 8;
|
|
21874
|
-
COMPRESS_MIN_BYTES = 4096;
|
|
21875
21970
|
CloudClient = class {
|
|
21876
21971
|
baseUrl;
|
|
21877
21972
|
apiKey;
|
|
@@ -21886,8 +21981,6 @@ var init_client = __esm({
|
|
|
21886
21981
|
daemonVersion;
|
|
21887
21982
|
daemonChannel;
|
|
21888
21983
|
provenance;
|
|
21889
|
-
/** Cleared for the process once a server proves it cannot inflate (see `json`). */
|
|
21890
|
-
compressRequests;
|
|
21891
21984
|
constructor(opts) {
|
|
21892
21985
|
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
21893
21986
|
if (opts.apiKey !== void 0) this.apiKey = opts.apiKey;
|
|
@@ -21901,7 +21994,6 @@ var init_client = __esm({
|
|
|
21901
21994
|
this.timeoutMs = opts.timeoutMs ?? 15e3;
|
|
21902
21995
|
this.daemonVersion = opts.daemonVersion;
|
|
21903
21996
|
this.daemonChannel = opts.daemonChannel;
|
|
21904
|
-
this.compressRequests = opts.compressRequests ?? true;
|
|
21905
21997
|
this.provenance = opts.provenance ?? {
|
|
21906
21998
|
clientProduct: "inerrata_cloud_client",
|
|
21907
21999
|
clientKind: "sdk",
|
|
@@ -22430,43 +22522,15 @@ var init_client = __esm({
|
|
|
22430
22522
|
const token = opts?.bearerToken ?? await this.authToken();
|
|
22431
22523
|
if (token) headers["authorization"] = `Bearer ${token}`;
|
|
22432
22524
|
}
|
|
22433
|
-
let payload;
|
|
22434
|
-
if (body2 !== void 0) {
|
|
22435
|
-
const raw2 = JSON.stringify(body2);
|
|
22436
|
-
if (this.compressRequests && Buffer.byteLength(raw2) >= COMPRESS_MIN_BYTES) {
|
|
22437
|
-
payload = gzipSync(Buffer.from(raw2));
|
|
22438
|
-
headers["content-encoding"] = "gzip";
|
|
22439
|
-
} else {
|
|
22440
|
-
payload = raw2;
|
|
22441
|
-
}
|
|
22442
|
-
}
|
|
22443
22525
|
const ac = new AbortController();
|
|
22444
22526
|
const tid = setTimeout(() => ac.abort(), this.timeoutMs);
|
|
22445
22527
|
try {
|
|
22446
22528
|
const res = await this.fetchFn(url2, {
|
|
22447
22529
|
method,
|
|
22448
22530
|
headers,
|
|
22449
|
-
body:
|
|
22531
|
+
body: body2 === void 0 ? void 0 : JSON.stringify(body2),
|
|
22450
22532
|
signal: ac.signal
|
|
22451
22533
|
});
|
|
22452
|
-
if (res.status === 400 && headers["content-encoding"] === "gzip") {
|
|
22453
|
-
delete headers["content-encoding"];
|
|
22454
|
-
const retry = await this.fetchFn(url2, {
|
|
22455
|
-
method,
|
|
22456
|
-
headers,
|
|
22457
|
-
body: JSON.stringify(body2),
|
|
22458
|
-
signal: ac.signal
|
|
22459
|
-
});
|
|
22460
|
-
if (!retry.ok) {
|
|
22461
|
-
const text = await retry.text();
|
|
22462
|
-
throw new CloudError(
|
|
22463
|
-
`${method} ${path2} failed: HTTP ${retry.status} ${text.slice(0, 200)}`,
|
|
22464
|
-
retry.status
|
|
22465
|
-
);
|
|
22466
|
-
}
|
|
22467
|
-
this.compressRequests = false;
|
|
22468
|
-
return await retry.json();
|
|
22469
|
-
}
|
|
22470
22534
|
if (!res.ok) {
|
|
22471
22535
|
const text = await res.text();
|
|
22472
22536
|
throw new CloudError(
|
|
@@ -47311,12 +47375,12 @@ var init_report_render = __esm({
|
|
|
47311
47375
|
|
|
47312
47376
|
// src/cli.ts
|
|
47313
47377
|
init_src5();
|
|
47314
|
-
import { closeSync as closeSync2, existsSync as
|
|
47315
|
-
import { join as
|
|
47378
|
+
import { closeSync as closeSync2, existsSync as existsSync26, openSync as openSync2, readFileSync as readFileSync25, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
|
|
47379
|
+
import { join as join29 } from "node:path";
|
|
47316
47380
|
import { spawn as spawn3 } from "node:child_process";
|
|
47317
47381
|
|
|
47318
47382
|
// src/daemon.ts
|
|
47319
|
-
import { existsSync as
|
|
47383
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync18 } from "node:fs";
|
|
47320
47384
|
|
|
47321
47385
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
47322
47386
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -47896,8 +47960,8 @@ init_config();
|
|
|
47896
47960
|
|
|
47897
47961
|
// src/engine.ts
|
|
47898
47962
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
47899
|
-
import { existsSync as
|
|
47900
|
-
import { join as
|
|
47963
|
+
import { existsSync as existsSync20, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync9, renameSync as renameSync3, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "node:fs";
|
|
47964
|
+
import { join as join25, relative as relative6, sep as sep4 } from "node:path";
|
|
47901
47965
|
|
|
47902
47966
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
47903
47967
|
import { stat as statcb } from "fs";
|
|
@@ -50341,6 +50405,10 @@ function tagEdgeCorroborated(targetAnchorIds, sessionTouchedNodeIds, independent
|
|
|
50341
50405
|
for (const a of targetAnchorIds) if (sessionTouchedNodeIds.has(a)) return true;
|
|
50342
50406
|
return false;
|
|
50343
50407
|
}
|
|
50408
|
+
function citeEdgeType(targetLabel2) {
|
|
50409
|
+
const t = typePriorEdge("Problem", targetLabel2);
|
|
50410
|
+
return t === "SUPERSEDES" ? "RELATES_TO" : t;
|
|
50411
|
+
}
|
|
50344
50412
|
function typePriorEdge(sourceLabel, targetLabel2, sentence = "") {
|
|
50345
50413
|
const direct = LABEL_PAIR[`${sourceLabel}>${targetLabel2}`];
|
|
50346
50414
|
if (direct) return direct;
|
|
@@ -50887,6 +50955,90 @@ function backfillConstraintKind(store, opts) {
|
|
|
50887
50955
|
return report;
|
|
50888
50956
|
}
|
|
50889
50957
|
|
|
50958
|
+
// src/edge-repair.ts
|
|
50959
|
+
init_src();
|
|
50960
|
+
init_src4();
|
|
50961
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "node:fs";
|
|
50962
|
+
import { join as join17 } from "node:path";
|
|
50963
|
+
function citeEdgeId(from, type, to) {
|
|
50964
|
+
return `edge_${digest({ from, type, to })}`.slice(0, 24);
|
|
50965
|
+
}
|
|
50966
|
+
var EDGE_REPAIR_VERSION = 1;
|
|
50967
|
+
var REJECTION_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
50968
|
+
var EMPTY2 = {
|
|
50969
|
+
skipped: true,
|
|
50970
|
+
scanned: 0,
|
|
50971
|
+
invalid: 0,
|
|
50972
|
+
retyped: 0,
|
|
50973
|
+
closed: 0,
|
|
50974
|
+
byType: {}
|
|
50975
|
+
};
|
|
50976
|
+
function markerPath2(configDir) {
|
|
50977
|
+
return join17(configDir, "edge-repair.json");
|
|
50978
|
+
}
|
|
50979
|
+
function alreadyDone2(configDir) {
|
|
50980
|
+
const p = markerPath2(configDir);
|
|
50981
|
+
if (!existsSync14(p)) return false;
|
|
50982
|
+
try {
|
|
50983
|
+
return JSON.parse(readFileSync12(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
|
|
50984
|
+
} catch {
|
|
50985
|
+
return false;
|
|
50986
|
+
}
|
|
50987
|
+
}
|
|
50988
|
+
function repairInvalidEdges(store, opts) {
|
|
50989
|
+
if (!opts.force && !opts.dryRun && alreadyDone2(opts.configDir)) return EMPTY2;
|
|
50990
|
+
const report = {
|
|
50991
|
+
skipped: false,
|
|
50992
|
+
scanned: 0,
|
|
50993
|
+
invalid: 0,
|
|
50994
|
+
retyped: 0,
|
|
50995
|
+
closed: 0,
|
|
50996
|
+
byType: {}
|
|
50997
|
+
};
|
|
50998
|
+
const work = [];
|
|
50999
|
+
for (const e of store.scanLiveEdgeRows()) {
|
|
51000
|
+
report.scanned++;
|
|
51001
|
+
if (!localEdgeViolation(e.fromLabel, e.type, e.toLabel)) continue;
|
|
51002
|
+
report.invalid++;
|
|
51003
|
+
const candidate = e.toLabel ? citeEdgeType(e.toLabel) : null;
|
|
51004
|
+
const retype = candidate && candidate !== e.type && !localEdgeViolation(e.fromLabel, candidate, e.toLabel) ? candidate : null;
|
|
51005
|
+
work.push({ edge: { id: e.id, from: e.from, to: e.to, type: e.type }, retype });
|
|
51006
|
+
report.byType[e.type] = (report.byType[e.type] ?? 0) + 1;
|
|
51007
|
+
if (retype) report.retyped++;
|
|
51008
|
+
else report.closed++;
|
|
51009
|
+
}
|
|
51010
|
+
if (opts.dryRun) return report;
|
|
51011
|
+
store.transaction(() => {
|
|
51012
|
+
for (const w of work) {
|
|
51013
|
+
const prior = store.getEdge(w.edge.id);
|
|
51014
|
+
store.closeEdge(w.edge.id, opts.now);
|
|
51015
|
+
if (!w.retype || !prior) continue;
|
|
51016
|
+
store.mergeEdge({
|
|
51017
|
+
...prior,
|
|
51018
|
+
id: citeEdgeId(w.edge.from, w.retype, w.edge.to),
|
|
51019
|
+
type: w.retype,
|
|
51020
|
+
validFrom: opts.now,
|
|
51021
|
+
validTo: null,
|
|
51022
|
+
lastSeenAt: opts.now,
|
|
51023
|
+
// Mark the provenance of the rewrite so a later audit can tell a repaired
|
|
51024
|
+
// edge from one captured natively — without which this sweep would be
|
|
51025
|
+
// indistinguishable from the agent having witnessed it post-fix.
|
|
51026
|
+
attrs: { ...prior.attrs ?? {}, retypedFrom: w.edge.type, retypedBy: `edge-repair:v${EDGE_REPAIR_VERSION}` }
|
|
51027
|
+
});
|
|
51028
|
+
}
|
|
51029
|
+
});
|
|
51030
|
+
store.pruneEdgeRejections(opts.now - REJECTION_RETENTION_MS);
|
|
51031
|
+
try {
|
|
51032
|
+
writeFileSync12(
|
|
51033
|
+
markerPath2(opts.configDir),
|
|
51034
|
+
JSON.stringify({ version: EDGE_REPAIR_VERSION, at: opts.now, ...report }, null, 2),
|
|
51035
|
+
"utf8"
|
|
51036
|
+
);
|
|
51037
|
+
} catch {
|
|
51038
|
+
}
|
|
51039
|
+
return report;
|
|
51040
|
+
}
|
|
51041
|
+
|
|
50890
51042
|
// src/engine.ts
|
|
50891
51043
|
init_symbol_summaries();
|
|
50892
51044
|
init_reconcile();
|
|
@@ -51085,11 +51237,11 @@ init_outbox();
|
|
|
51085
51237
|
init_src8();
|
|
51086
51238
|
init_src();
|
|
51087
51239
|
init_src2();
|
|
51088
|
-
import { readFileSync as
|
|
51089
|
-
import { join as
|
|
51240
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
51241
|
+
import { join as join18 } from "node:path";
|
|
51090
51242
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
51091
51243
|
try {
|
|
51092
|
-
return
|
|
51244
|
+
return readFileSync13(join18(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
|
|
51093
51245
|
} catch {
|
|
51094
51246
|
return [];
|
|
51095
51247
|
}
|
|
@@ -51450,22 +51602,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
51450
51602
|
}
|
|
51451
51603
|
|
|
51452
51604
|
// src/git-sensor.ts
|
|
51453
|
-
import { existsSync as
|
|
51454
|
-
import { join as
|
|
51605
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14, watch as fsWatch } from "node:fs";
|
|
51606
|
+
import { join as join19 } from "node:path";
|
|
51455
51607
|
function readFirstLine(path2) {
|
|
51456
51608
|
try {
|
|
51457
|
-
return
|
|
51609
|
+
return readFileSync14(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
51458
51610
|
} catch {
|
|
51459
51611
|
return null;
|
|
51460
51612
|
}
|
|
51461
51613
|
}
|
|
51462
51614
|
function readGitRefState(gitDir) {
|
|
51463
|
-
const head2 = readFirstLine(
|
|
51615
|
+
const head2 = readFirstLine(join19(gitDir, "HEAD"));
|
|
51464
51616
|
const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
|
|
51465
51617
|
const branch = m ? m[1] : null;
|
|
51466
51618
|
let sha2 = null;
|
|
51467
51619
|
if (branch) {
|
|
51468
|
-
sha2 = readFirstLine(
|
|
51620
|
+
sha2 = readFirstLine(join19(gitDir, "refs", "heads", branch));
|
|
51469
51621
|
if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
|
|
51470
51622
|
} else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
|
|
51471
51623
|
sha2 = head2;
|
|
@@ -51473,13 +51625,13 @@ function readGitRefState(gitDir) {
|
|
|
51473
51625
|
return {
|
|
51474
51626
|
branch,
|
|
51475
51627
|
sha: sha2,
|
|
51476
|
-
mergeHeadExists:
|
|
51477
|
-
origHeadExists:
|
|
51628
|
+
mergeHeadExists: existsSync15(join19(gitDir, "MERGE_HEAD")),
|
|
51629
|
+
origHeadExists: existsSync15(join19(gitDir, "ORIG_HEAD"))
|
|
51478
51630
|
};
|
|
51479
51631
|
}
|
|
51480
51632
|
function shaFromPackedRefs(gitDir, ref) {
|
|
51481
51633
|
try {
|
|
51482
|
-
for (const line of
|
|
51634
|
+
for (const line of readFileSync14(join19(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
51483
51635
|
const [sha2, name2] = line.split(/\s+/);
|
|
51484
51636
|
if (name2 === ref && sha2) return sha2;
|
|
51485
51637
|
}
|
|
@@ -51513,7 +51665,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51513
51665
|
const settle = () => {
|
|
51514
51666
|
if (timer) clearTimeout(timer);
|
|
51515
51667
|
timer = setTimeout(() => {
|
|
51516
|
-
if (
|
|
51668
|
+
if (existsSync15(join19(gitDir, "index.lock"))) {
|
|
51517
51669
|
settle();
|
|
51518
51670
|
return;
|
|
51519
51671
|
}
|
|
@@ -51524,7 +51676,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51524
51676
|
}, debounceMs);
|
|
51525
51677
|
};
|
|
51526
51678
|
for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
|
|
51527
|
-
const p =
|
|
51679
|
+
const p = join19(gitDir, sub);
|
|
51528
51680
|
try {
|
|
51529
51681
|
watchers.push(fsWatch(p, settle));
|
|
51530
51682
|
} catch {
|
|
@@ -51749,21 +51901,21 @@ var TelemetryRecorder = class {
|
|
|
51749
51901
|
|
|
51750
51902
|
// src/skills.ts
|
|
51751
51903
|
import {
|
|
51752
|
-
existsSync as
|
|
51904
|
+
existsSync as existsSync16,
|
|
51753
51905
|
mkdirSync as mkdirSync6,
|
|
51754
|
-
readFileSync as
|
|
51906
|
+
readFileSync as readFileSync15,
|
|
51755
51907
|
readdirSync as readdirSync7,
|
|
51756
51908
|
unlinkSync as unlinkSync2,
|
|
51757
|
-
writeFileSync as
|
|
51909
|
+
writeFileSync as writeFileSync13
|
|
51758
51910
|
} from "node:fs";
|
|
51759
|
-
import { basename as basename4, join as
|
|
51911
|
+
import { basename as basename4, join as join20 } from "node:path";
|
|
51760
51912
|
function skillFileName(id) {
|
|
51761
51913
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
51762
51914
|
}
|
|
51763
51915
|
function readSkillManifest(manifestPath) {
|
|
51764
|
-
if (!
|
|
51916
|
+
if (!existsSync16(manifestPath)) return [];
|
|
51765
51917
|
try {
|
|
51766
|
-
const parsed = JSON.parse(
|
|
51918
|
+
const parsed = JSON.parse(readFileSync15(manifestPath, "utf8"));
|
|
51767
51919
|
return (parsed.skills ?? []).map((s) => ({
|
|
51768
51920
|
title: s.title ?? "",
|
|
51769
51921
|
layer: s.layer ?? "technique",
|
|
@@ -51787,7 +51939,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51787
51939
|
for (const s of res.skills) {
|
|
51788
51940
|
const fileName = skillFileName(s.id);
|
|
51789
51941
|
keep.add(fileName);
|
|
51790
|
-
|
|
51942
|
+
writeFileSync13(join20(paths.skillsDir, fileName), s.markdown, "utf8");
|
|
51791
51943
|
rows.push({
|
|
51792
51944
|
id: s.id,
|
|
51793
51945
|
title: s.title,
|
|
@@ -51800,7 +51952,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51800
51952
|
const fileName = skillFileName(p.id);
|
|
51801
51953
|
if (keep.has(fileName)) continue;
|
|
51802
51954
|
keep.add(fileName);
|
|
51803
|
-
|
|
51955
|
+
writeFileSync13(join20(paths.skillsDir, fileName), p.markdown, "utf8");
|
|
51804
51956
|
rows.push({
|
|
51805
51957
|
id: p.id,
|
|
51806
51958
|
title: p.title,
|
|
@@ -51814,13 +51966,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51814
51966
|
if (!f.endsWith(".md")) continue;
|
|
51815
51967
|
if (keep.has(basename4(f))) continue;
|
|
51816
51968
|
try {
|
|
51817
|
-
unlinkSync2(
|
|
51969
|
+
unlinkSync2(join20(paths.skillsDir, f));
|
|
51818
51970
|
pruned++;
|
|
51819
51971
|
} catch {
|
|
51820
51972
|
}
|
|
51821
51973
|
}
|
|
51822
51974
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
51823
|
-
|
|
51975
|
+
writeFileSync13(
|
|
51824
51976
|
paths.skillsManifest,
|
|
51825
51977
|
JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
|
|
51826
51978
|
"utf8"
|
|
@@ -51832,22 +51984,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51832
51984
|
init_src2();
|
|
51833
51985
|
import {
|
|
51834
51986
|
cpSync,
|
|
51835
|
-
existsSync as
|
|
51987
|
+
existsSync as existsSync17,
|
|
51836
51988
|
lstatSync,
|
|
51837
51989
|
mkdirSync as mkdirSync7,
|
|
51838
|
-
readFileSync as
|
|
51990
|
+
readFileSync as readFileSync16,
|
|
51839
51991
|
readdirSync as readdirSync8,
|
|
51840
51992
|
rmSync as rmSync2,
|
|
51841
51993
|
symlinkSync,
|
|
51842
|
-
writeFileSync as
|
|
51994
|
+
writeFileSync as writeFileSync14
|
|
51843
51995
|
} from "node:fs";
|
|
51844
|
-
import { join as
|
|
51996
|
+
import { join as join21 } from "node:path";
|
|
51845
51997
|
var SKILL_NS = "errata-";
|
|
51846
51998
|
var HARNESS_SKILL_DIRS = [
|
|
51847
|
-
{ configDir: ".claude", skillsDir:
|
|
51999
|
+
{ configDir: ".claude", skillsDir: join21(".claude", "skills") },
|
|
51848
52000
|
// Cursor adopted the standard; its exact project dir is still moving — kept
|
|
51849
52001
|
// best-effort and gated on `.cursor/` presence so we never create it blind.
|
|
51850
|
-
{ configDir: ".cursor", skillsDir:
|
|
52002
|
+
{ configDir: ".cursor", skillsDir: join21(".cursor", "skills") }
|
|
51851
52003
|
];
|
|
51852
52004
|
function skillSlug(title, id) {
|
|
51853
52005
|
const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
|
|
@@ -51892,12 +52044,12 @@ function skillCiteHandle(s) {
|
|
|
51892
52044
|
return priorHandle({ id: s.id, description: s.title });
|
|
51893
52045
|
}
|
|
51894
52046
|
function reconcileNamespaced(dir, keep) {
|
|
51895
|
-
if (!
|
|
52047
|
+
if (!existsSync17(dir)) return 0;
|
|
51896
52048
|
let pruned = 0;
|
|
51897
52049
|
for (const name2 of readdirSync8(dir)) {
|
|
51898
52050
|
if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
|
|
51899
52051
|
try {
|
|
51900
|
-
rmSync2(
|
|
52052
|
+
rmSync2(join21(dir, name2), { recursive: true, force: true });
|
|
51901
52053
|
pruned++;
|
|
51902
52054
|
} catch {
|
|
51903
52055
|
}
|
|
@@ -51906,7 +52058,7 @@ function reconcileNamespaced(dir, keep) {
|
|
|
51906
52058
|
}
|
|
51907
52059
|
function linkOrCopy(linkPath, target) {
|
|
51908
52060
|
try {
|
|
51909
|
-
if (
|
|
52061
|
+
if (existsSync17(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
|
|
51910
52062
|
} catch {
|
|
51911
52063
|
}
|
|
51912
52064
|
try {
|
|
@@ -51927,7 +52079,7 @@ function safeLstat(p) {
|
|
|
51927
52079
|
}
|
|
51928
52080
|
}
|
|
51929
52081
|
function emitAndProjectSkills(root, skills) {
|
|
51930
|
-
const agentsSkillsDir =
|
|
52082
|
+
const agentsSkillsDir = join21(root, ".agents", "skills");
|
|
51931
52083
|
mkdirSync7(agentsSkillsDir, { recursive: true });
|
|
51932
52084
|
const slugs = [];
|
|
51933
52085
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -51935,7 +52087,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51935
52087
|
for (const s of skills) {
|
|
51936
52088
|
let body2;
|
|
51937
52089
|
try {
|
|
51938
|
-
body2 =
|
|
52090
|
+
body2 = readFileSync16(s.bodyPath, "utf8");
|
|
51939
52091
|
} catch {
|
|
51940
52092
|
continue;
|
|
51941
52093
|
}
|
|
@@ -51944,9 +52096,9 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51944
52096
|
keep.add(slug2);
|
|
51945
52097
|
slugs.push(slug2);
|
|
51946
52098
|
const description = deriveDescription(s.title, s.layer, body2);
|
|
51947
|
-
mkdirSync7(
|
|
51948
|
-
|
|
51949
|
-
|
|
52099
|
+
mkdirSync7(join21(agentsSkillsDir, slug2), { recursive: true });
|
|
52100
|
+
writeFileSync14(
|
|
52101
|
+
join21(agentsSkillsDir, slug2, "SKILL.md"),
|
|
51950
52102
|
renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
|
|
51951
52103
|
"utf8"
|
|
51952
52104
|
);
|
|
@@ -51955,11 +52107,11 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51955
52107
|
reconcileNamespaced(agentsSkillsDir, keep);
|
|
51956
52108
|
let projected = 0;
|
|
51957
52109
|
for (const h of HARNESS_SKILL_DIRS) {
|
|
51958
|
-
if (!
|
|
51959
|
-
const dir =
|
|
52110
|
+
if (!existsSync17(join21(root, h.configDir))) continue;
|
|
52111
|
+
const dir = join21(root, h.skillsDir);
|
|
51960
52112
|
mkdirSync7(dir, { recursive: true });
|
|
51961
52113
|
for (const slug2 of slugs) {
|
|
51962
|
-
linkOrCopy(
|
|
52114
|
+
linkOrCopy(join21(dir, slug2), join21(agentsSkillsDir, slug2));
|
|
51963
52115
|
projected++;
|
|
51964
52116
|
}
|
|
51965
52117
|
reconcileNamespaced(dir, keep);
|
|
@@ -51968,15 +52120,15 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51968
52120
|
return { slugs, emitted, projected };
|
|
51969
52121
|
}
|
|
51970
52122
|
function emitInputsFromManifest(erretaDir, manifestPath) {
|
|
51971
|
-
if (!
|
|
52123
|
+
if (!existsSync17(manifestPath)) return [];
|
|
51972
52124
|
try {
|
|
51973
|
-
const parsed = JSON.parse(
|
|
52125
|
+
const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
|
|
51974
52126
|
return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
|
|
51975
52127
|
id: s.id,
|
|
51976
52128
|
title: s.title ?? s.id,
|
|
51977
52129
|
layer: s.layer ?? "technique",
|
|
51978
52130
|
confidence: s.confidence ?? 0,
|
|
51979
|
-
bodyPath:
|
|
52131
|
+
bodyPath: join21(erretaDir, s.file)
|
|
51980
52132
|
}));
|
|
51981
52133
|
} catch {
|
|
51982
52134
|
return [];
|
|
@@ -51990,17 +52142,17 @@ var GITIGNORE_LINES = [
|
|
|
51990
52142
|
".cursor/skills/errata-*/"
|
|
51991
52143
|
];
|
|
51992
52144
|
function ensureSkillGitignore(root) {
|
|
51993
|
-
const path2 =
|
|
52145
|
+
const path2 = join21(root, ".gitignore");
|
|
51994
52146
|
let current = "";
|
|
51995
52147
|
try {
|
|
51996
|
-
current =
|
|
52148
|
+
current = existsSync17(path2) ? readFileSync16(path2, "utf8") : "";
|
|
51997
52149
|
} catch {
|
|
51998
52150
|
return;
|
|
51999
52151
|
}
|
|
52000
52152
|
if (current.includes(GITIGNORE_MARK)) return;
|
|
52001
52153
|
const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
|
|
52002
52154
|
try {
|
|
52003
|
-
|
|
52155
|
+
writeFileSync14(path2, `${current}${prefix}
|
|
52004
52156
|
${GITIGNORE_LINES.join("\n")}
|
|
52005
52157
|
`, "utf8");
|
|
52006
52158
|
} catch {
|
|
@@ -52061,20 +52213,20 @@ init_paths();
|
|
|
52061
52213
|
// src/profile.ts
|
|
52062
52214
|
init_src2();
|
|
52063
52215
|
init_paths();
|
|
52064
|
-
import { existsSync as
|
|
52216
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "node:fs";
|
|
52065
52217
|
import { createHash as createHash12 } from "node:crypto";
|
|
52066
|
-
import { join as
|
|
52218
|
+
import { join as join23 } from "node:path";
|
|
52067
52219
|
|
|
52068
52220
|
// src/git-remote.ts
|
|
52069
52221
|
init_src();
|
|
52070
|
-
import { existsSync as
|
|
52071
|
-
import { isAbsolute as isAbsolute3, join as
|
|
52222
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync4 } from "node:fs";
|
|
52223
|
+
import { isAbsolute as isAbsolute3, join as join22, resolve as resolve5 } from "node:path";
|
|
52072
52224
|
function resolveGitDir(root) {
|
|
52073
|
-
const dotGit =
|
|
52225
|
+
const dotGit = join22(root, ".git");
|
|
52074
52226
|
try {
|
|
52075
52227
|
const st = statSync4(dotGit);
|
|
52076
52228
|
if (st.isDirectory()) return dotGit;
|
|
52077
|
-
const m = /^gitdir:\s*(.+?)\s*$/m.exec(
|
|
52229
|
+
const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync17(dotGit, "utf8"));
|
|
52078
52230
|
if (!m) return null;
|
|
52079
52231
|
const dir = m[1];
|
|
52080
52232
|
return isAbsolute3(dir) ? dir : resolve5(root, dir);
|
|
@@ -52083,22 +52235,22 @@ function resolveGitDir(root) {
|
|
|
52083
52235
|
}
|
|
52084
52236
|
}
|
|
52085
52237
|
function gitConfigPath(gitDir) {
|
|
52086
|
-
const commondirFile =
|
|
52087
|
-
if (
|
|
52088
|
-
const common =
|
|
52238
|
+
const commondirFile = join22(gitDir, "commondir");
|
|
52239
|
+
if (existsSync18(commondirFile)) {
|
|
52240
|
+
const common = readFileSync17(commondirFile, "utf8").trim();
|
|
52089
52241
|
const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
|
|
52090
|
-
return
|
|
52242
|
+
return join22(commonDir, "config");
|
|
52091
52243
|
}
|
|
52092
|
-
return
|
|
52244
|
+
return join22(gitDir, "config");
|
|
52093
52245
|
}
|
|
52094
52246
|
function readRemotes(root) {
|
|
52095
52247
|
const gitDir = resolveGitDir(root);
|
|
52096
52248
|
if (!gitDir) return [];
|
|
52097
52249
|
const cfgPath = gitConfigPath(gitDir);
|
|
52098
|
-
if (!
|
|
52250
|
+
if (!existsSync18(cfgPath)) return [];
|
|
52099
52251
|
let txt;
|
|
52100
52252
|
try {
|
|
52101
|
-
txt =
|
|
52253
|
+
txt = readFileSync17(cfgPath, "utf8");
|
|
52102
52254
|
} catch {
|
|
52103
52255
|
return [];
|
|
52104
52256
|
}
|
|
@@ -52134,13 +52286,13 @@ function refreshRepoLocator(root, profile) {
|
|
|
52134
52286
|
}
|
|
52135
52287
|
function loadProfile(root) {
|
|
52136
52288
|
const p = workspacePaths(root);
|
|
52137
|
-
if (!
|
|
52138
|
-
return JSON.parse(
|
|
52289
|
+
if (!existsSync19(p.workspaceJson)) return null;
|
|
52290
|
+
return JSON.parse(readFileSync18(p.workspaceJson, "utf8"));
|
|
52139
52291
|
}
|
|
52140
52292
|
function saveProfile(root, profile) {
|
|
52141
52293
|
const p = workspacePaths(root);
|
|
52142
52294
|
ensureDir(p.configDir);
|
|
52143
|
-
|
|
52295
|
+
writeFileSync15(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
52144
52296
|
}
|
|
52145
52297
|
function autodetectProfile(root) {
|
|
52146
52298
|
const id = workspaceId(root);
|
|
@@ -52148,10 +52300,10 @@ function autodetectProfile(root) {
|
|
|
52148
52300
|
const p = emptyProfile(id, name2);
|
|
52149
52301
|
const locator = detectRepoLocator(root);
|
|
52150
52302
|
if (locator) p.repoLocator = locator;
|
|
52151
|
-
const pkgPath =
|
|
52152
|
-
if (
|
|
52303
|
+
const pkgPath = join23(root, "package.json");
|
|
52304
|
+
if (existsSync19(pkgPath)) {
|
|
52153
52305
|
try {
|
|
52154
|
-
const pkg = JSON.parse(
|
|
52306
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
52155
52307
|
p.languages.push("typescript", "javascript");
|
|
52156
52308
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
52157
52309
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -52172,10 +52324,10 @@ function autodetectProfile(root) {
|
|
|
52172
52324
|
} catch {
|
|
52173
52325
|
}
|
|
52174
52326
|
}
|
|
52175
|
-
const pyproject =
|
|
52176
|
-
if (
|
|
52327
|
+
const pyproject = join23(root, "pyproject.toml");
|
|
52328
|
+
if (existsSync19(pyproject)) {
|
|
52177
52329
|
try {
|
|
52178
|
-
const txt =
|
|
52330
|
+
const txt = readFileSync18(pyproject, "utf8");
|
|
52179
52331
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
52180
52332
|
p.languages.push("python");
|
|
52181
52333
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -52186,16 +52338,16 @@ function autodetectProfile(root) {
|
|
|
52186
52338
|
} catch {
|
|
52187
52339
|
}
|
|
52188
52340
|
}
|
|
52189
|
-
const reqs =
|
|
52190
|
-
if (
|
|
52341
|
+
const reqs = join23(root, "requirements.txt");
|
|
52342
|
+
if (existsSync19(reqs)) {
|
|
52191
52343
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
52192
52344
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
52193
52345
|
}
|
|
52194
|
-
if (
|
|
52346
|
+
if (existsSync19(join23(root, "go.mod"))) {
|
|
52195
52347
|
p.languages.push("go");
|
|
52196
52348
|
p.stack.push("go");
|
|
52197
52349
|
}
|
|
52198
|
-
if (
|
|
52350
|
+
if (existsSync19(join23(root, "Cargo.toml"))) {
|
|
52199
52351
|
p.languages.push("rust");
|
|
52200
52352
|
p.stack.push("rust");
|
|
52201
52353
|
}
|
|
@@ -52205,17 +52357,17 @@ function autodetectProfile(root) {
|
|
|
52205
52357
|
}
|
|
52206
52358
|
|
|
52207
52359
|
// src/witness-queue.ts
|
|
52208
|
-
import { readFileSync as
|
|
52209
|
-
import { dirname as dirname9, join as
|
|
52360
|
+
import { readFileSync as readFileSync19, renameSync as renameSync2, writeFileSync as writeFileSync16 } from "node:fs";
|
|
52361
|
+
import { dirname as dirname9, join as join24 } from "node:path";
|
|
52210
52362
|
var WITNESS_QUEUE_CAP = 500;
|
|
52211
52363
|
var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
52212
52364
|
var WITNESS_MAX_ATTEMPTS = 5;
|
|
52213
52365
|
function witnessQueuePath(workspaceConfigDir) {
|
|
52214
|
-
return
|
|
52366
|
+
return join24(workspaceConfigDir, "witness-queue.json");
|
|
52215
52367
|
}
|
|
52216
52368
|
function loadWitnessQueue(path2) {
|
|
52217
52369
|
try {
|
|
52218
|
-
const raw2 = JSON.parse(
|
|
52370
|
+
const raw2 = JSON.parse(readFileSync19(path2, "utf8"));
|
|
52219
52371
|
if (!Array.isArray(raw2)) return [];
|
|
52220
52372
|
return raw2.filter(
|
|
52221
52373
|
(w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
|
|
@@ -52226,8 +52378,8 @@ function loadWitnessQueue(path2) {
|
|
|
52226
52378
|
}
|
|
52227
52379
|
function saveWitnessQueue(path2, queue) {
|
|
52228
52380
|
try {
|
|
52229
|
-
const tmp =
|
|
52230
|
-
|
|
52381
|
+
const tmp = join24(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
|
|
52382
|
+
writeFileSync16(tmp, JSON.stringify(queue), "utf8");
|
|
52231
52383
|
renameSync2(tmp, path2);
|
|
52232
52384
|
} catch {
|
|
52233
52385
|
}
|
|
@@ -52507,7 +52659,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
52507
52659
|
}
|
|
52508
52660
|
|
|
52509
52661
|
// src/engine.ts
|
|
52510
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
52662
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.249" : "2.0.0-alpha.0";
|
|
52511
52663
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
52512
52664
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
52513
52665
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -52517,7 +52669,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
52517
52669
|
function appendIdentityAudit(path2, record2, line) {
|
|
52518
52670
|
if (!record2.accepted && record2.score <= 0) return;
|
|
52519
52671
|
try {
|
|
52520
|
-
if (
|
|
52672
|
+
if (existsSync20(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
52521
52673
|
renameSync3(path2, `${path2}.1`);
|
|
52522
52674
|
}
|
|
52523
52675
|
appendFileSync2(path2, line);
|
|
@@ -52527,7 +52679,7 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
52527
52679
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
52528
52680
|
function loadTurnCursors(path2) {
|
|
52529
52681
|
try {
|
|
52530
|
-
const raw2 = JSON.parse(
|
|
52682
|
+
const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
|
|
52531
52683
|
return new Map(
|
|
52532
52684
|
Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
|
|
52533
52685
|
);
|
|
@@ -52537,7 +52689,7 @@ function loadTurnCursors(path2) {
|
|
|
52537
52689
|
}
|
|
52538
52690
|
function loadTurnOffsets(path2) {
|
|
52539
52691
|
try {
|
|
52540
|
-
const raw2 = JSON.parse(
|
|
52692
|
+
const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
|
|
52541
52693
|
const out2 = /* @__PURE__ */ new Map();
|
|
52542
52694
|
for (const [k, v] of Object.entries(raw2)) {
|
|
52543
52695
|
const off = typeof v === "object" && v !== null ? v.offset : void 0;
|
|
@@ -52553,7 +52705,7 @@ function saveTurnCursors(path2, cursors, offsets) {
|
|
|
52553
52705
|
const merged = {};
|
|
52554
52706
|
for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
|
|
52555
52707
|
for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
|
|
52556
|
-
|
|
52708
|
+
writeFileSync17(path2, JSON.stringify(merged), "utf8");
|
|
52557
52709
|
} catch {
|
|
52558
52710
|
}
|
|
52559
52711
|
}
|
|
@@ -52575,7 +52727,7 @@ function gitSourceWatchTargets(root) {
|
|
|
52575
52727
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
52576
52728
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
52577
52729
|
);
|
|
52578
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
52730
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join25(root, d) + sep4));
|
|
52579
52731
|
} catch {
|
|
52580
52732
|
}
|
|
52581
52733
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -52587,19 +52739,19 @@ function gitSourceWatchTargets(root) {
|
|
|
52587
52739
|
if (!f.startsWith(prefix)) continue;
|
|
52588
52740
|
const rest2 = f.slice(prefix.length);
|
|
52589
52741
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
52590
|
-
else targets.add(
|
|
52742
|
+
else targets.add(join25(root, f));
|
|
52591
52743
|
}
|
|
52592
52744
|
for (const c of children) {
|
|
52593
|
-
if (IGNORED_PATH.test(
|
|
52745
|
+
if (IGNORED_PATH.test(join25(root, c) + sep4)) continue;
|
|
52594
52746
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
52595
|
-
else targets.add(
|
|
52747
|
+
else targets.add(join25(root, c));
|
|
52596
52748
|
}
|
|
52597
52749
|
};
|
|
52598
52750
|
addUnder("");
|
|
52599
52751
|
if (targets.size > 0) return [...targets];
|
|
52600
52752
|
} catch {
|
|
52601
52753
|
}
|
|
52602
|
-
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(
|
|
52754
|
+
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join25(root, String(e.name)) + sep4)).map((e) => join25(root, String(e.name)));
|
|
52603
52755
|
}
|
|
52604
52756
|
function createWorkspaceEngine(opts) {
|
|
52605
52757
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -52757,7 +52909,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52757
52909
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
52758
52910
|
let episodeId2;
|
|
52759
52911
|
if (srcPaths.length > 0) {
|
|
52760
|
-
const abs = srcPaths.map((p) =>
|
|
52912
|
+
const abs = srcPaths.map((p) => join25(opts.workspaceRoot, p));
|
|
52761
52913
|
try {
|
|
52762
52914
|
const r = await runReindexPass(
|
|
52763
52915
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -52793,8 +52945,8 @@ function createWorkspaceEngine(opts) {
|
|
|
52793
52945
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
52794
52946
|
);
|
|
52795
52947
|
};
|
|
52796
|
-
const gitDir =
|
|
52797
|
-
if (
|
|
52948
|
+
const gitDir = join25(opts.workspaceRoot, ".git");
|
|
52949
|
+
if (existsSync20(gitDir)) {
|
|
52798
52950
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
52799
52951
|
void handleGitEvent(ev).catch((err2) => {
|
|
52800
52952
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -52864,10 +53016,10 @@ function createWorkspaceEngine(opts) {
|
|
|
52864
53016
|
});
|
|
52865
53017
|
doneRender?.();
|
|
52866
53018
|
writeContextFile(opts.workspaceRoot, body2);
|
|
52867
|
-
const target =
|
|
53019
|
+
const target = join25(opts.workspaceRoot, "AGENTS.md");
|
|
52868
53020
|
writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
|
|
52869
53021
|
if (elicit) {
|
|
52870
|
-
writePrimingHandles(
|
|
53022
|
+
writePrimingHandles(join25(paths.configDir, "priming-handles.json"), [
|
|
52871
53023
|
...snapshot.recentProblems.map((r) => r.node),
|
|
52872
53024
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
52873
53025
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -52958,6 +53110,17 @@ function createWorkspaceEngine(opts) {
|
|
|
52958
53110
|
} catch (err2) {
|
|
52959
53111
|
console.warn("[errata] anchor backfill failed:", err2);
|
|
52960
53112
|
}
|
|
53113
|
+
try {
|
|
53114
|
+
const r = repairInvalidEdges(store, { configDir: paths.configDir, now: Date.now() });
|
|
53115
|
+
if (!r.skipped && r.invalid > 0) {
|
|
53116
|
+
console.log(
|
|
53117
|
+
`[errata] edge repair: ${r.retyped} edge(s) retyped, ${r.closed} closed (${Object.entries(r.byType).map(([t, n]) => `${t}x${n}`).join(", ")})`
|
|
53118
|
+
);
|
|
53119
|
+
refreshContextNow();
|
|
53120
|
+
}
|
|
53121
|
+
} catch (err2) {
|
|
53122
|
+
console.warn("[errata] edge repair failed:", err2);
|
|
53123
|
+
}
|
|
52961
53124
|
try {
|
|
52962
53125
|
const c = backfillConstraintKind(store, {
|
|
52963
53126
|
root: opts.workspaceRoot,
|
|
@@ -53072,7 +53235,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53072
53235
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
53073
53236
|
});
|
|
53074
53237
|
};
|
|
53075
|
-
const turnCursorPath =
|
|
53238
|
+
const turnCursorPath = join25(paths.configDir, "turn-cursors.json");
|
|
53076
53239
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
53077
53240
|
const turnOffset = loadTurnOffsets(turnCursorPath);
|
|
53078
53241
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
@@ -53096,7 +53259,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53096
53259
|
const t = Date.now();
|
|
53097
53260
|
let processedTurns = 0;
|
|
53098
53261
|
const elicit = isEdgeElicitationEnabled();
|
|
53099
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
53262
|
+
const handleMap = elicit ? readPrimingHandles(join25(paths.configDir, "priming-handles.json")) : {};
|
|
53100
53263
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
53101
53264
|
const toRel = (abs) => {
|
|
53102
53265
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -53405,9 +53568,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53405
53568
|
if (targetId === pid) continue;
|
|
53406
53569
|
const target = store.getNode(targetId);
|
|
53407
53570
|
if (!target) continue;
|
|
53408
|
-
|
|
53409
|
-
const type = target.label === "Pattern" ? "INSTANCE_OF" : target.label === "Problem" ? "MATCHES" : fallback === "SUPERSEDES" ? "RELATES_TO" : fallback;
|
|
53410
|
-
mintCiteEdge(pid, targetId, type, inst.evidence === "witnessed" ? 0.4 : 0.3, { instanceCite: true, evidence: inst.evidence });
|
|
53571
|
+
mintCiteEdge(pid, targetId, citeEdgeType(target.label), inst.evidence === "witnessed" ? 0.4 : 0.3, { instanceCite: true, evidence: inst.evidence });
|
|
53411
53572
|
}
|
|
53412
53573
|
}
|
|
53413
53574
|
for (const tf of plan.transfers) {
|
|
@@ -53707,7 +53868,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53707
53868
|
try {
|
|
53708
53869
|
const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
|
|
53709
53870
|
emitAndProjectSkills(opts.workspaceRoot, inputs);
|
|
53710
|
-
writePrimingHandles(
|
|
53871
|
+
writePrimingHandles(join25(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
|
|
53711
53872
|
} catch (err2) {
|
|
53712
53873
|
console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
|
|
53713
53874
|
}
|
|
@@ -53894,7 +54055,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53894
54055
|
console.log(
|
|
53895
54056
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
53896
54057
|
);
|
|
53897
|
-
const pending =
|
|
54058
|
+
const pending = existsSync20(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
53898
54059
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
53899
54060
|
}
|
|
53900
54061
|
try {
|
|
@@ -53981,7 +54142,7 @@ async function startDaemon(opts) {
|
|
|
53981
54142
|
reviewUrl: () => webUiUrl + "/review"
|
|
53982
54143
|
});
|
|
53983
54144
|
const writeLockFile = (url2) => {
|
|
53984
|
-
|
|
54145
|
+
writeFileSync18(
|
|
53985
54146
|
engine.paths.daemonLock,
|
|
53986
54147
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
53987
54148
|
"utf8"
|
|
@@ -54024,7 +54185,7 @@ async function startDaemon(opts) {
|
|
|
54024
54185
|
);
|
|
54025
54186
|
await engine.stop();
|
|
54026
54187
|
try {
|
|
54027
|
-
if (
|
|
54188
|
+
if (existsSync21(engine.paths.daemonLock)) {
|
|
54028
54189
|
}
|
|
54029
54190
|
} catch {
|
|
54030
54191
|
}
|
|
@@ -54041,16 +54202,16 @@ async function listenServer(fetchFn, port) {
|
|
|
54041
54202
|
|
|
54042
54203
|
// src/registry.ts
|
|
54043
54204
|
init_paths();
|
|
54044
|
-
import { existsSync as
|
|
54045
|
-
import { join as
|
|
54205
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21, writeFileSync as writeFileSync19 } from "node:fs";
|
|
54206
|
+
import { join as join26 } from "node:path";
|
|
54046
54207
|
function registryPath() {
|
|
54047
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
54208
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join26(globalDir(), "workspaces.json");
|
|
54048
54209
|
}
|
|
54049
54210
|
function read() {
|
|
54050
54211
|
const p = registryPath();
|
|
54051
|
-
if (!
|
|
54212
|
+
if (!existsSync22(p)) return { version: 1, workspaces: {} };
|
|
54052
54213
|
try {
|
|
54053
|
-
const parsed = JSON.parse(
|
|
54214
|
+
const parsed = JSON.parse(readFileSync21(p, "utf8"));
|
|
54054
54215
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
54055
54216
|
} catch {
|
|
54056
54217
|
return { version: 1, workspaces: {} };
|
|
@@ -54058,7 +54219,7 @@ function read() {
|
|
|
54058
54219
|
}
|
|
54059
54220
|
function write(reg) {
|
|
54060
54221
|
ensureDir(globalDir());
|
|
54061
|
-
|
|
54222
|
+
writeFileSync19(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
54062
54223
|
}
|
|
54063
54224
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
54064
54225
|
const reg = read();
|
|
@@ -54075,7 +54236,7 @@ function pruneMissingWorkspaces() {
|
|
|
54075
54236
|
const reg = read();
|
|
54076
54237
|
const removed = [];
|
|
54077
54238
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
54078
|
-
if (!
|
|
54239
|
+
if (!existsSync22(entry.path)) {
|
|
54079
54240
|
removed.push(entry);
|
|
54080
54241
|
delete reg.workspaces[id];
|
|
54081
54242
|
}
|
|
@@ -54084,13 +54245,13 @@ function pruneMissingWorkspaces() {
|
|
|
54084
54245
|
return removed;
|
|
54085
54246
|
}
|
|
54086
54247
|
function workspaceStatus(entry) {
|
|
54087
|
-
const missing = !
|
|
54248
|
+
const missing = !existsSync22(entry.path);
|
|
54088
54249
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
54089
54250
|
let running = false;
|
|
54090
54251
|
let webUiUrl = null;
|
|
54091
|
-
if (
|
|
54252
|
+
if (existsSync22(lockPath)) {
|
|
54092
54253
|
try {
|
|
54093
|
-
const lock = JSON.parse(
|
|
54254
|
+
const lock = JSON.parse(readFileSync21(lockPath, "utf8"));
|
|
54094
54255
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
54095
54256
|
running = true;
|
|
54096
54257
|
webUiUrl = lock.webUiUrl;
|
|
@@ -54118,7 +54279,7 @@ function pidAlive(pid) {
|
|
|
54118
54279
|
// src/multi.ts
|
|
54119
54280
|
init_dist();
|
|
54120
54281
|
init_src4();
|
|
54121
|
-
import { readFileSync as
|
|
54282
|
+
import { readFileSync as readFileSync24, unlinkSync as unlinkSync3, writeFileSync as writeFileSync20 } from "node:fs";
|
|
54122
54283
|
|
|
54123
54284
|
// src/principle-sync.ts
|
|
54124
54285
|
init_src4();
|
|
@@ -54146,8 +54307,8 @@ init_reconcile();
|
|
|
54146
54307
|
|
|
54147
54308
|
// src/lockfile-auto.ts
|
|
54148
54309
|
init_src();
|
|
54149
|
-
import { existsSync as
|
|
54150
|
-
import { join as
|
|
54310
|
+
import { existsSync as existsSync23, readFileSync as readFileSync22 } from "node:fs";
|
|
54311
|
+
import { join as join27 } from "node:path";
|
|
54151
54312
|
|
|
54152
54313
|
// src/package-index.ts
|
|
54153
54314
|
init_src();
|
|
@@ -54296,11 +54457,11 @@ function runLockfilePass(opts) {
|
|
|
54296
54457
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
54297
54458
|
];
|
|
54298
54459
|
for (const c of candidates) {
|
|
54299
|
-
const p =
|
|
54300
|
-
if (!
|
|
54460
|
+
const p = join27(opts.root, c.file);
|
|
54461
|
+
if (!existsSync23(p)) continue;
|
|
54301
54462
|
let sbom;
|
|
54302
54463
|
try {
|
|
54303
|
-
sbom = c.parse(
|
|
54464
|
+
sbom = c.parse(readFileSync22(p, "utf8"));
|
|
54304
54465
|
} catch {
|
|
54305
54466
|
continue;
|
|
54306
54467
|
}
|
|
@@ -54748,7 +54909,7 @@ var ConsolidateWorker = class {
|
|
|
54748
54909
|
init_paths();
|
|
54749
54910
|
|
|
54750
54911
|
// src/lock.ts
|
|
54751
|
-
import { existsSync as
|
|
54912
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23 } from "node:fs";
|
|
54752
54913
|
function isProcessAlive(pid) {
|
|
54753
54914
|
if (!pid || pid <= 0) return false;
|
|
54754
54915
|
try {
|
|
@@ -54759,9 +54920,9 @@ function isProcessAlive(pid) {
|
|
|
54759
54920
|
}
|
|
54760
54921
|
}
|
|
54761
54922
|
function readDaemonLock(lockPath) {
|
|
54762
|
-
if (!
|
|
54923
|
+
if (!existsSync24(lockPath)) return null;
|
|
54763
54924
|
try {
|
|
54764
|
-
const lock = JSON.parse(
|
|
54925
|
+
const lock = JSON.parse(readFileSync23(lockPath, "utf8"));
|
|
54765
54926
|
return typeof lock.pid === "number" ? lock : null;
|
|
54766
54927
|
} catch {
|
|
54767
54928
|
return null;
|
|
@@ -55040,12 +55201,12 @@ async function reanchorProject(opts) {
|
|
|
55040
55201
|
}
|
|
55041
55202
|
|
|
55042
55203
|
// src/adopt.ts
|
|
55043
|
-
import { existsSync as
|
|
55044
|
-
import { dirname as dirname10, join as
|
|
55204
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
55205
|
+
import { dirname as dirname10, join as join28 } from "node:path";
|
|
55045
55206
|
function findGitRoot(absPath) {
|
|
55046
55207
|
let dir = absPath;
|
|
55047
55208
|
for (let depth = 0; depth < 64; depth++) {
|
|
55048
|
-
if (
|
|
55209
|
+
if (existsSync25(join28(dir, ".git"))) return dir;
|
|
55049
55210
|
const parent = dirname10(dir);
|
|
55050
55211
|
if (parent === dir) return null;
|
|
55051
55212
|
dir = parent;
|
|
@@ -55294,7 +55455,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55294
55455
|
void ambientLinkAll();
|
|
55295
55456
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
55296
55457
|
try {
|
|
55297
|
-
|
|
55458
|
+
writeFileSync20(
|
|
55298
55459
|
rec.engine.paths.daemonLock,
|
|
55299
55460
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
55300
55461
|
"utf8"
|
|
@@ -55483,7 +55644,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55483
55644
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
55484
55645
|
try {
|
|
55485
55646
|
ensureDir(globalDir());
|
|
55486
|
-
|
|
55647
|
+
writeFileSync20(
|
|
55487
55648
|
lockPath,
|
|
55488
55649
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
55489
55650
|
"utf8"
|
|
@@ -55492,7 +55653,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55492
55653
|
}
|
|
55493
55654
|
for (const r of records) {
|
|
55494
55655
|
try {
|
|
55495
|
-
|
|
55656
|
+
writeFileSync20(
|
|
55496
55657
|
r.engine.paths.daemonLock,
|
|
55497
55658
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
55498
55659
|
"utf8"
|
|
@@ -55990,7 +56151,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55990
56151
|
},
|
|
55991
56152
|
async stop() {
|
|
55992
56153
|
try {
|
|
55993
|
-
const cur =
|
|
56154
|
+
const cur = readFileSync24(lockPath, "utf8");
|
|
55994
56155
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
55995
56156
|
} catch {
|
|
55996
56157
|
}
|
|
@@ -57007,21 +57168,21 @@ async function cmdInit() {
|
|
|
57007
57168
|
if (!skipHooks) {
|
|
57008
57169
|
console.log("");
|
|
57009
57170
|
console.log("installing harness hooks...");
|
|
57010
|
-
const { existsSync:
|
|
57011
|
-
const { join:
|
|
57171
|
+
const { existsSync: existsSync27 } = await import("node:fs");
|
|
57172
|
+
const { join: join30 } = await import("node:path");
|
|
57012
57173
|
try {
|
|
57013
57174
|
await installClaudeHooks(port);
|
|
57014
57175
|
} catch (err2) {
|
|
57015
57176
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
57016
57177
|
}
|
|
57017
|
-
if (
|
|
57178
|
+
if (existsSync27(join30(ROOT, ".cursor"))) {
|
|
57018
57179
|
try {
|
|
57019
57180
|
await installCursorMcpConfig();
|
|
57020
57181
|
} catch (err2) {
|
|
57021
57182
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
57022
57183
|
}
|
|
57023
57184
|
}
|
|
57024
|
-
if (
|
|
57185
|
+
if (existsSync27(join30(ROOT, ".codex"))) {
|
|
57025
57186
|
try {
|
|
57026
57187
|
await installCodexHooks(port);
|
|
57027
57188
|
} catch (err2) {
|
|
@@ -57178,9 +57339,9 @@ async function cmdStatus() {
|
|
|
57178
57339
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
57179
57340
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
57180
57341
|
}
|
|
57181
|
-
console.log(` graph db: ${
|
|
57182
|
-
console.log(` event log: ${
|
|
57183
|
-
if (
|
|
57342
|
+
console.log(` graph db: ${existsSync26(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
57343
|
+
console.log(` event log: ${existsSync26(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
57344
|
+
if (existsSync26(paths.castalia)) {
|
|
57184
57345
|
try {
|
|
57185
57346
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
57186
57347
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -57196,6 +57357,16 @@ async function cmdStatus() {
|
|
|
57196
57357
|
}
|
|
57197
57358
|
}
|
|
57198
57359
|
console.log(` contribute: ${pending} pending of ${total} instance node(s)`);
|
|
57360
|
+
const rejections = store.edgeRejections();
|
|
57361
|
+
if (rejections.length > 0) {
|
|
57362
|
+
const refused = rejections.reduce((n, r) => n + r.count, 0);
|
|
57363
|
+
console.log(` edges: ${refused} refused by the ontology gate \u2014 a producer is emitting invalid edges`);
|
|
57364
|
+
for (const r of rejections.slice(0, 3)) {
|
|
57365
|
+
const mins = Math.max(0, Math.round((Date.now() - r.lastAt) / 6e4));
|
|
57366
|
+
const age = mins < 60 ? `${mins}m ago` : mins < 1440 ? `${Math.round(mins / 60)}h ago` : `${Math.round(mins / 1440)}d ago`;
|
|
57367
|
+
console.log(` ${r.count}x ${r.type} (last ${age})${r.sample ? ` \u2014 ${r.sample}` : ""}`);
|
|
57368
|
+
}
|
|
57369
|
+
}
|
|
57199
57370
|
} finally {
|
|
57200
57371
|
store.close();
|
|
57201
57372
|
}
|
|
@@ -57844,11 +58015,11 @@ function cmdInstallationProfile(args2) {
|
|
|
57844
58015
|
}
|
|
57845
58016
|
async function cmdReview() {
|
|
57846
58017
|
const paths = workspacePaths(ROOT);
|
|
57847
|
-
if (!
|
|
58018
|
+
if (!existsSync26(paths.reviewQueue)) {
|
|
57848
58019
|
console.log("(review queue empty)");
|
|
57849
58020
|
return;
|
|
57850
58021
|
}
|
|
57851
|
-
const queue = JSON.parse(
|
|
58022
|
+
const queue = JSON.parse(readFileSync25(paths.reviewQueue, "utf8"));
|
|
57852
58023
|
if (queue.length === 0) {
|
|
57853
58024
|
console.log("(review queue empty)");
|
|
57854
58025
|
return;
|
|
@@ -58519,7 +58690,7 @@ async function gatherRepo(store, ws) {
|
|
|
58519
58690
|
};
|
|
58520
58691
|
}
|
|
58521
58692
|
async function gatherReportData(generatedAt) {
|
|
58522
|
-
const { existsSync:
|
|
58693
|
+
const { existsSync: existsSync27 } = await import("node:fs");
|
|
58523
58694
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
58524
58695
|
const cfg = loadConfig();
|
|
58525
58696
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -58527,7 +58698,7 @@ async function gatherReportData(generatedAt) {
|
|
|
58527
58698
|
for (const ws of listWorkspaces()) {
|
|
58528
58699
|
if (ws.missing) continue;
|
|
58529
58700
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
58530
|
-
if (!
|
|
58701
|
+
if (!existsSync27(dbPath)) continue;
|
|
58531
58702
|
let store = null;
|
|
58532
58703
|
try {
|
|
58533
58704
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -58558,7 +58729,7 @@ async function gatherReportData(generatedAt) {
|
|
|
58558
58729
|
};
|
|
58559
58730
|
}
|
|
58560
58731
|
async function cmdReport(args2) {
|
|
58561
|
-
const { mkdirSync: mkdirSync8, writeFileSync:
|
|
58732
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58562
58733
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
58563
58734
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
58564
58735
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -58571,8 +58742,8 @@ async function cmdReport(args2) {
|
|
|
58571
58742
|
const outDir = workspacePaths(ROOT).configDir;
|
|
58572
58743
|
mkdirSync8(outDir, { recursive: true });
|
|
58573
58744
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
58574
|
-
for (const f of files)
|
|
58575
|
-
const indexPath =
|
|
58745
|
+
for (const f of files) writeFileSync21(join29(outDir, f.name), f.html, "utf8");
|
|
58746
|
+
const indexPath = join29(outDir, "report.html");
|
|
58576
58747
|
console.log(`report \u2192 ${indexPath}`);
|
|
58577
58748
|
console.log(
|
|
58578
58749
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -58690,15 +58861,15 @@ function hookRelayCommand(port, path2) {
|
|
|
58690
58861
|
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 '{}'`;
|
|
58691
58862
|
}
|
|
58692
58863
|
async function installClaudeHooks(port) {
|
|
58693
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58694
|
-
const { join:
|
|
58695
|
-
const dir =
|
|
58696
|
-
if (!
|
|
58697
|
-
const file2 =
|
|
58864
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58865
|
+
const { join: join30 } = await import("node:path");
|
|
58866
|
+
const dir = join30(ROOT, ".claude");
|
|
58867
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
58868
|
+
const file2 = join30(dir, "settings.json");
|
|
58698
58869
|
let settings = {};
|
|
58699
|
-
if (
|
|
58870
|
+
if (existsSync27(file2)) {
|
|
58700
58871
|
try {
|
|
58701
|
-
settings = JSON.parse(
|
|
58872
|
+
settings = JSON.parse(readFileSync26(file2, "utf8"));
|
|
58702
58873
|
} catch {
|
|
58703
58874
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58704
58875
|
process.exit(2);
|
|
@@ -58744,10 +58915,10 @@ async function installClaudeHooks(port) {
|
|
|
58744
58915
|
dropErrata(list);
|
|
58745
58916
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
58746
58917
|
}
|
|
58747
|
-
|
|
58918
|
+
writeFileSync21(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
58748
58919
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
58749
58920
|
await installClaudeMcpConfig();
|
|
58750
|
-
const claudeMd =
|
|
58921
|
+
const claudeMd = join30(ROOT, "CLAUDE.md");
|
|
58751
58922
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
58752
58923
|
if (recall.kind === "collision") {
|
|
58753
58924
|
console.warn(
|
|
@@ -58759,15 +58930,15 @@ async function installClaudeHooks(port) {
|
|
|
58759
58930
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58760
58931
|
}
|
|
58761
58932
|
async function installClaudeMcpConfig() {
|
|
58762
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58763
|
-
const { join:
|
|
58764
|
-
const file2 =
|
|
58933
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58934
|
+
const { join: join30, dirname: dirname11 } = await import("node:path");
|
|
58935
|
+
const file2 = join30(ROOT, ".mcp.json");
|
|
58765
58936
|
const dir = dirname11(file2);
|
|
58766
|
-
if (!
|
|
58937
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
58767
58938
|
let cfg = {};
|
|
58768
|
-
if (
|
|
58939
|
+
if (existsSync27(file2)) {
|
|
58769
58940
|
try {
|
|
58770
|
-
cfg = JSON.parse(
|
|
58941
|
+
cfg = JSON.parse(readFileSync26(file2, "utf8"));
|
|
58771
58942
|
} catch {
|
|
58772
58943
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58773
58944
|
process.exit(2);
|
|
@@ -58775,21 +58946,21 @@ async function installClaudeMcpConfig() {
|
|
|
58775
58946
|
}
|
|
58776
58947
|
cfg.mcpServers ??= {};
|
|
58777
58948
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58778
|
-
|
|
58949
|
+
writeFileSync21(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58779
58950
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
58780
58951
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
58781
58952
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
58782
58953
|
}
|
|
58783
58954
|
async function installCursorMcpConfig() {
|
|
58784
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58785
|
-
const { join:
|
|
58786
|
-
const dir =
|
|
58787
|
-
if (!
|
|
58788
|
-
const file2 =
|
|
58955
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58956
|
+
const { join: join30 } = await import("node:path");
|
|
58957
|
+
const dir = join30(ROOT, ".cursor");
|
|
58958
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
58959
|
+
const file2 = join30(dir, "mcp.json");
|
|
58789
58960
|
let cfg = {};
|
|
58790
|
-
if (
|
|
58961
|
+
if (existsSync27(file2)) {
|
|
58791
58962
|
try {
|
|
58792
|
-
cfg = JSON.parse(
|
|
58963
|
+
cfg = JSON.parse(readFileSync26(file2, "utf8"));
|
|
58793
58964
|
} catch {
|
|
58794
58965
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58795
58966
|
process.exit(2);
|
|
@@ -58797,7 +58968,7 @@ async function installCursorMcpConfig() {
|
|
|
58797
58968
|
}
|
|
58798
58969
|
cfg.mcpServers ??= {};
|
|
58799
58970
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58800
|
-
|
|
58971
|
+
writeFileSync21(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58801
58972
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
58802
58973
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
58803
58974
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -58805,16 +58976,16 @@ async function installCursorMcpConfig() {
|
|
|
58805
58976
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
58806
58977
|
}
|
|
58807
58978
|
async function installCodexHooks(port) {
|
|
58808
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58809
|
-
const { join:
|
|
58810
|
-
const dir =
|
|
58811
|
-
if (!
|
|
58812
|
-
const file2 =
|
|
58979
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58980
|
+
const { join: join30 } = await import("node:path");
|
|
58981
|
+
const dir = join30(ROOT, ".codex");
|
|
58982
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
58983
|
+
const file2 = join30(dir, "config.toml");
|
|
58813
58984
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
58814
58985
|
const END = `# <<< errata hooks`;
|
|
58815
58986
|
let existing = "";
|
|
58816
|
-
if (
|
|
58817
|
-
existing =
|
|
58987
|
+
if (existsSync27(file2)) {
|
|
58988
|
+
existing = readFileSync26(file2, "utf8");
|
|
58818
58989
|
const beginIdx = existing.indexOf(BEGIN);
|
|
58819
58990
|
const endIdx = existing.indexOf(END);
|
|
58820
58991
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -58843,7 +59014,7 @@ ${END}
|
|
|
58843
59014
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
58844
59015
|
|
|
58845
59016
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
58846
|
-
|
|
59017
|
+
writeFileSync21(file2, final, "utf8");
|
|
58847
59018
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
58848
59019
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58849
59020
|
console.log("");
|
|
@@ -59157,7 +59328,7 @@ async function cmdDash(args2) {
|
|
|
59157
59328
|
await yieldToLoop2();
|
|
59158
59329
|
try {
|
|
59159
59330
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
59160
|
-
const res = bleedRules(
|
|
59331
|
+
const res = bleedRules(join29(r.root, ".claude", "rules"), items);
|
|
59161
59332
|
if (res.written || res.pruned) {
|
|
59162
59333
|
console.log(
|
|
59163
59334
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|