@inerrata-corporation/errata 2.0.2-dev.245 → 2.0.2-dev.247
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 +400 -196
- 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
|
-
return `${edge2.type} cannot target ${toLabel} locally (allowed: ${rule.to.join(", ")})`;
|
|
16937
|
-
}
|
|
16938
|
-
return null;
|
|
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 {
|
|
16939
16977
|
}
|
|
16940
|
-
|
|
16941
|
-
|
|
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 {
|
|
17004
|
+
}
|
|
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,
|
|
@@ -47311,12 +47408,12 @@ var init_report_render = __esm({
|
|
|
47311
47408
|
|
|
47312
47409
|
// src/cli.ts
|
|
47313
47410
|
init_src5();
|
|
47314
|
-
import { closeSync as closeSync2, existsSync as
|
|
47315
|
-
import { join as
|
|
47411
|
+
import { closeSync as closeSync2, existsSync as existsSync26, openSync as openSync2, readFileSync as readFileSync25, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
|
|
47412
|
+
import { join as join29 } from "node:path";
|
|
47316
47413
|
import { spawn as spawn3 } from "node:child_process";
|
|
47317
47414
|
|
|
47318
47415
|
// src/daemon.ts
|
|
47319
|
-
import { existsSync as
|
|
47416
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync18 } from "node:fs";
|
|
47320
47417
|
|
|
47321
47418
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
47322
47419
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -47896,8 +47993,8 @@ init_config();
|
|
|
47896
47993
|
|
|
47897
47994
|
// src/engine.ts
|
|
47898
47995
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
47899
|
-
import { existsSync as
|
|
47900
|
-
import { join as
|
|
47996
|
+
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";
|
|
47997
|
+
import { join as join25, relative as relative6, sep as sep4 } from "node:path";
|
|
47901
47998
|
|
|
47902
47999
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
47903
48000
|
import { stat as statcb } from "fs";
|
|
@@ -50341,6 +50438,10 @@ function tagEdgeCorroborated(targetAnchorIds, sessionTouchedNodeIds, independent
|
|
|
50341
50438
|
for (const a of targetAnchorIds) if (sessionTouchedNodeIds.has(a)) return true;
|
|
50342
50439
|
return false;
|
|
50343
50440
|
}
|
|
50441
|
+
function citeEdgeType(targetLabel2) {
|
|
50442
|
+
const t = typePriorEdge("Problem", targetLabel2);
|
|
50443
|
+
return t === "SUPERSEDES" ? "RELATES_TO" : t;
|
|
50444
|
+
}
|
|
50344
50445
|
function typePriorEdge(sourceLabel, targetLabel2, sentence = "") {
|
|
50345
50446
|
const direct = LABEL_PAIR[`${sourceLabel}>${targetLabel2}`];
|
|
50346
50447
|
if (direct) return direct;
|
|
@@ -50887,6 +50988,90 @@ function backfillConstraintKind(store, opts) {
|
|
|
50887
50988
|
return report;
|
|
50888
50989
|
}
|
|
50889
50990
|
|
|
50991
|
+
// src/edge-repair.ts
|
|
50992
|
+
init_src();
|
|
50993
|
+
init_src4();
|
|
50994
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "node:fs";
|
|
50995
|
+
import { join as join17 } from "node:path";
|
|
50996
|
+
function citeEdgeId(from, type, to) {
|
|
50997
|
+
return `edge_${digest({ from, type, to })}`.slice(0, 24);
|
|
50998
|
+
}
|
|
50999
|
+
var EDGE_REPAIR_VERSION = 1;
|
|
51000
|
+
var REJECTION_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
51001
|
+
var EMPTY2 = {
|
|
51002
|
+
skipped: true,
|
|
51003
|
+
scanned: 0,
|
|
51004
|
+
invalid: 0,
|
|
51005
|
+
retyped: 0,
|
|
51006
|
+
closed: 0,
|
|
51007
|
+
byType: {}
|
|
51008
|
+
};
|
|
51009
|
+
function markerPath2(configDir) {
|
|
51010
|
+
return join17(configDir, "edge-repair.json");
|
|
51011
|
+
}
|
|
51012
|
+
function alreadyDone2(configDir) {
|
|
51013
|
+
const p = markerPath2(configDir);
|
|
51014
|
+
if (!existsSync14(p)) return false;
|
|
51015
|
+
try {
|
|
51016
|
+
return JSON.parse(readFileSync12(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
|
|
51017
|
+
} catch {
|
|
51018
|
+
return false;
|
|
51019
|
+
}
|
|
51020
|
+
}
|
|
51021
|
+
function repairInvalidEdges(store, opts) {
|
|
51022
|
+
if (!opts.force && !opts.dryRun && alreadyDone2(opts.configDir)) return EMPTY2;
|
|
51023
|
+
const report = {
|
|
51024
|
+
skipped: false,
|
|
51025
|
+
scanned: 0,
|
|
51026
|
+
invalid: 0,
|
|
51027
|
+
retyped: 0,
|
|
51028
|
+
closed: 0,
|
|
51029
|
+
byType: {}
|
|
51030
|
+
};
|
|
51031
|
+
const work = [];
|
|
51032
|
+
for (const e of store.scanLiveEdgeRows()) {
|
|
51033
|
+
report.scanned++;
|
|
51034
|
+
if (!localEdgeViolation(e.fromLabel, e.type, e.toLabel)) continue;
|
|
51035
|
+
report.invalid++;
|
|
51036
|
+
const candidate = e.toLabel ? citeEdgeType(e.toLabel) : null;
|
|
51037
|
+
const retype = candidate && candidate !== e.type && !localEdgeViolation(e.fromLabel, candidate, e.toLabel) ? candidate : null;
|
|
51038
|
+
work.push({ edge: { id: e.id, from: e.from, to: e.to, type: e.type }, retype });
|
|
51039
|
+
report.byType[e.type] = (report.byType[e.type] ?? 0) + 1;
|
|
51040
|
+
if (retype) report.retyped++;
|
|
51041
|
+
else report.closed++;
|
|
51042
|
+
}
|
|
51043
|
+
if (opts.dryRun) return report;
|
|
51044
|
+
store.transaction(() => {
|
|
51045
|
+
for (const w of work) {
|
|
51046
|
+
const prior = store.getEdge(w.edge.id);
|
|
51047
|
+
store.closeEdge(w.edge.id, opts.now);
|
|
51048
|
+
if (!w.retype || !prior) continue;
|
|
51049
|
+
store.mergeEdge({
|
|
51050
|
+
...prior,
|
|
51051
|
+
id: citeEdgeId(w.edge.from, w.retype, w.edge.to),
|
|
51052
|
+
type: w.retype,
|
|
51053
|
+
validFrom: opts.now,
|
|
51054
|
+
validTo: null,
|
|
51055
|
+
lastSeenAt: opts.now,
|
|
51056
|
+
// Mark the provenance of the rewrite so a later audit can tell a repaired
|
|
51057
|
+
// edge from one captured natively — without which this sweep would be
|
|
51058
|
+
// indistinguishable from the agent having witnessed it post-fix.
|
|
51059
|
+
attrs: { ...prior.attrs ?? {}, retypedFrom: w.edge.type, retypedBy: `edge-repair:v${EDGE_REPAIR_VERSION}` }
|
|
51060
|
+
});
|
|
51061
|
+
}
|
|
51062
|
+
});
|
|
51063
|
+
store.pruneEdgeRejections(opts.now - REJECTION_RETENTION_MS);
|
|
51064
|
+
try {
|
|
51065
|
+
writeFileSync12(
|
|
51066
|
+
markerPath2(opts.configDir),
|
|
51067
|
+
JSON.stringify({ version: EDGE_REPAIR_VERSION, at: opts.now, ...report }, null, 2),
|
|
51068
|
+
"utf8"
|
|
51069
|
+
);
|
|
51070
|
+
} catch {
|
|
51071
|
+
}
|
|
51072
|
+
return report;
|
|
51073
|
+
}
|
|
51074
|
+
|
|
50890
51075
|
// src/engine.ts
|
|
50891
51076
|
init_symbol_summaries();
|
|
50892
51077
|
init_reconcile();
|
|
@@ -51085,11 +51270,11 @@ init_outbox();
|
|
|
51085
51270
|
init_src8();
|
|
51086
51271
|
init_src();
|
|
51087
51272
|
init_src2();
|
|
51088
|
-
import { readFileSync as
|
|
51089
|
-
import { join as
|
|
51273
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
51274
|
+
import { join as join18 } from "node:path";
|
|
51090
51275
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
51091
51276
|
try {
|
|
51092
|
-
return
|
|
51277
|
+
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
51278
|
} catch {
|
|
51094
51279
|
return [];
|
|
51095
51280
|
}
|
|
@@ -51450,22 +51635,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
51450
51635
|
}
|
|
51451
51636
|
|
|
51452
51637
|
// src/git-sensor.ts
|
|
51453
|
-
import { existsSync as
|
|
51454
|
-
import { join as
|
|
51638
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14, watch as fsWatch } from "node:fs";
|
|
51639
|
+
import { join as join19 } from "node:path";
|
|
51455
51640
|
function readFirstLine(path2) {
|
|
51456
51641
|
try {
|
|
51457
|
-
return
|
|
51642
|
+
return readFileSync14(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
51458
51643
|
} catch {
|
|
51459
51644
|
return null;
|
|
51460
51645
|
}
|
|
51461
51646
|
}
|
|
51462
51647
|
function readGitRefState(gitDir) {
|
|
51463
|
-
const head2 = readFirstLine(
|
|
51648
|
+
const head2 = readFirstLine(join19(gitDir, "HEAD"));
|
|
51464
51649
|
const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
|
|
51465
51650
|
const branch = m ? m[1] : null;
|
|
51466
51651
|
let sha2 = null;
|
|
51467
51652
|
if (branch) {
|
|
51468
|
-
sha2 = readFirstLine(
|
|
51653
|
+
sha2 = readFirstLine(join19(gitDir, "refs", "heads", branch));
|
|
51469
51654
|
if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
|
|
51470
51655
|
} else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
|
|
51471
51656
|
sha2 = head2;
|
|
@@ -51473,13 +51658,13 @@ function readGitRefState(gitDir) {
|
|
|
51473
51658
|
return {
|
|
51474
51659
|
branch,
|
|
51475
51660
|
sha: sha2,
|
|
51476
|
-
mergeHeadExists:
|
|
51477
|
-
origHeadExists:
|
|
51661
|
+
mergeHeadExists: existsSync15(join19(gitDir, "MERGE_HEAD")),
|
|
51662
|
+
origHeadExists: existsSync15(join19(gitDir, "ORIG_HEAD"))
|
|
51478
51663
|
};
|
|
51479
51664
|
}
|
|
51480
51665
|
function shaFromPackedRefs(gitDir, ref) {
|
|
51481
51666
|
try {
|
|
51482
|
-
for (const line of
|
|
51667
|
+
for (const line of readFileSync14(join19(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
51483
51668
|
const [sha2, name2] = line.split(/\s+/);
|
|
51484
51669
|
if (name2 === ref && sha2) return sha2;
|
|
51485
51670
|
}
|
|
@@ -51513,7 +51698,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51513
51698
|
const settle = () => {
|
|
51514
51699
|
if (timer) clearTimeout(timer);
|
|
51515
51700
|
timer = setTimeout(() => {
|
|
51516
|
-
if (
|
|
51701
|
+
if (existsSync15(join19(gitDir, "index.lock"))) {
|
|
51517
51702
|
settle();
|
|
51518
51703
|
return;
|
|
51519
51704
|
}
|
|
@@ -51524,7 +51709,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51524
51709
|
}, debounceMs);
|
|
51525
51710
|
};
|
|
51526
51711
|
for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
|
|
51527
|
-
const p =
|
|
51712
|
+
const p = join19(gitDir, sub);
|
|
51528
51713
|
try {
|
|
51529
51714
|
watchers.push(fsWatch(p, settle));
|
|
51530
51715
|
} catch {
|
|
@@ -51749,21 +51934,21 @@ var TelemetryRecorder = class {
|
|
|
51749
51934
|
|
|
51750
51935
|
// src/skills.ts
|
|
51751
51936
|
import {
|
|
51752
|
-
existsSync as
|
|
51937
|
+
existsSync as existsSync16,
|
|
51753
51938
|
mkdirSync as mkdirSync6,
|
|
51754
|
-
readFileSync as
|
|
51939
|
+
readFileSync as readFileSync15,
|
|
51755
51940
|
readdirSync as readdirSync7,
|
|
51756
51941
|
unlinkSync as unlinkSync2,
|
|
51757
|
-
writeFileSync as
|
|
51942
|
+
writeFileSync as writeFileSync13
|
|
51758
51943
|
} from "node:fs";
|
|
51759
|
-
import { basename as basename4, join as
|
|
51944
|
+
import { basename as basename4, join as join20 } from "node:path";
|
|
51760
51945
|
function skillFileName(id) {
|
|
51761
51946
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
51762
51947
|
}
|
|
51763
51948
|
function readSkillManifest(manifestPath) {
|
|
51764
|
-
if (!
|
|
51949
|
+
if (!existsSync16(manifestPath)) return [];
|
|
51765
51950
|
try {
|
|
51766
|
-
const parsed = JSON.parse(
|
|
51951
|
+
const parsed = JSON.parse(readFileSync15(manifestPath, "utf8"));
|
|
51767
51952
|
return (parsed.skills ?? []).map((s) => ({
|
|
51768
51953
|
title: s.title ?? "",
|
|
51769
51954
|
layer: s.layer ?? "technique",
|
|
@@ -51787,7 +51972,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51787
51972
|
for (const s of res.skills) {
|
|
51788
51973
|
const fileName = skillFileName(s.id);
|
|
51789
51974
|
keep.add(fileName);
|
|
51790
|
-
|
|
51975
|
+
writeFileSync13(join20(paths.skillsDir, fileName), s.markdown, "utf8");
|
|
51791
51976
|
rows.push({
|
|
51792
51977
|
id: s.id,
|
|
51793
51978
|
title: s.title,
|
|
@@ -51800,7 +51985,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51800
51985
|
const fileName = skillFileName(p.id);
|
|
51801
51986
|
if (keep.has(fileName)) continue;
|
|
51802
51987
|
keep.add(fileName);
|
|
51803
|
-
|
|
51988
|
+
writeFileSync13(join20(paths.skillsDir, fileName), p.markdown, "utf8");
|
|
51804
51989
|
rows.push({
|
|
51805
51990
|
id: p.id,
|
|
51806
51991
|
title: p.title,
|
|
@@ -51814,13 +51999,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51814
51999
|
if (!f.endsWith(".md")) continue;
|
|
51815
52000
|
if (keep.has(basename4(f))) continue;
|
|
51816
52001
|
try {
|
|
51817
|
-
unlinkSync2(
|
|
52002
|
+
unlinkSync2(join20(paths.skillsDir, f));
|
|
51818
52003
|
pruned++;
|
|
51819
52004
|
} catch {
|
|
51820
52005
|
}
|
|
51821
52006
|
}
|
|
51822
52007
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
51823
|
-
|
|
52008
|
+
writeFileSync13(
|
|
51824
52009
|
paths.skillsManifest,
|
|
51825
52010
|
JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
|
|
51826
52011
|
"utf8"
|
|
@@ -51832,22 +52017,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51832
52017
|
init_src2();
|
|
51833
52018
|
import {
|
|
51834
52019
|
cpSync,
|
|
51835
|
-
existsSync as
|
|
52020
|
+
existsSync as existsSync17,
|
|
51836
52021
|
lstatSync,
|
|
51837
52022
|
mkdirSync as mkdirSync7,
|
|
51838
|
-
readFileSync as
|
|
52023
|
+
readFileSync as readFileSync16,
|
|
51839
52024
|
readdirSync as readdirSync8,
|
|
51840
52025
|
rmSync as rmSync2,
|
|
51841
52026
|
symlinkSync,
|
|
51842
|
-
writeFileSync as
|
|
52027
|
+
writeFileSync as writeFileSync14
|
|
51843
52028
|
} from "node:fs";
|
|
51844
|
-
import { join as
|
|
52029
|
+
import { join as join21 } from "node:path";
|
|
51845
52030
|
var SKILL_NS = "errata-";
|
|
51846
52031
|
var HARNESS_SKILL_DIRS = [
|
|
51847
|
-
{ configDir: ".claude", skillsDir:
|
|
52032
|
+
{ configDir: ".claude", skillsDir: join21(".claude", "skills") },
|
|
51848
52033
|
// Cursor adopted the standard; its exact project dir is still moving — kept
|
|
51849
52034
|
// best-effort and gated on `.cursor/` presence so we never create it blind.
|
|
51850
|
-
{ configDir: ".cursor", skillsDir:
|
|
52035
|
+
{ configDir: ".cursor", skillsDir: join21(".cursor", "skills") }
|
|
51851
52036
|
];
|
|
51852
52037
|
function skillSlug(title, id) {
|
|
51853
52038
|
const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
|
|
@@ -51892,12 +52077,12 @@ function skillCiteHandle(s) {
|
|
|
51892
52077
|
return priorHandle({ id: s.id, description: s.title });
|
|
51893
52078
|
}
|
|
51894
52079
|
function reconcileNamespaced(dir, keep) {
|
|
51895
|
-
if (!
|
|
52080
|
+
if (!existsSync17(dir)) return 0;
|
|
51896
52081
|
let pruned = 0;
|
|
51897
52082
|
for (const name2 of readdirSync8(dir)) {
|
|
51898
52083
|
if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
|
|
51899
52084
|
try {
|
|
51900
|
-
rmSync2(
|
|
52085
|
+
rmSync2(join21(dir, name2), { recursive: true, force: true });
|
|
51901
52086
|
pruned++;
|
|
51902
52087
|
} catch {
|
|
51903
52088
|
}
|
|
@@ -51906,7 +52091,7 @@ function reconcileNamespaced(dir, keep) {
|
|
|
51906
52091
|
}
|
|
51907
52092
|
function linkOrCopy(linkPath, target) {
|
|
51908
52093
|
try {
|
|
51909
|
-
if (
|
|
52094
|
+
if (existsSync17(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
|
|
51910
52095
|
} catch {
|
|
51911
52096
|
}
|
|
51912
52097
|
try {
|
|
@@ -51927,7 +52112,7 @@ function safeLstat(p) {
|
|
|
51927
52112
|
}
|
|
51928
52113
|
}
|
|
51929
52114
|
function emitAndProjectSkills(root, skills) {
|
|
51930
|
-
const agentsSkillsDir =
|
|
52115
|
+
const agentsSkillsDir = join21(root, ".agents", "skills");
|
|
51931
52116
|
mkdirSync7(agentsSkillsDir, { recursive: true });
|
|
51932
52117
|
const slugs = [];
|
|
51933
52118
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -51935,7 +52120,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51935
52120
|
for (const s of skills) {
|
|
51936
52121
|
let body2;
|
|
51937
52122
|
try {
|
|
51938
|
-
body2 =
|
|
52123
|
+
body2 = readFileSync16(s.bodyPath, "utf8");
|
|
51939
52124
|
} catch {
|
|
51940
52125
|
continue;
|
|
51941
52126
|
}
|
|
@@ -51944,9 +52129,9 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51944
52129
|
keep.add(slug2);
|
|
51945
52130
|
slugs.push(slug2);
|
|
51946
52131
|
const description = deriveDescription(s.title, s.layer, body2);
|
|
51947
|
-
mkdirSync7(
|
|
51948
|
-
|
|
51949
|
-
|
|
52132
|
+
mkdirSync7(join21(agentsSkillsDir, slug2), { recursive: true });
|
|
52133
|
+
writeFileSync14(
|
|
52134
|
+
join21(agentsSkillsDir, slug2, "SKILL.md"),
|
|
51950
52135
|
renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
|
|
51951
52136
|
"utf8"
|
|
51952
52137
|
);
|
|
@@ -51955,11 +52140,11 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51955
52140
|
reconcileNamespaced(agentsSkillsDir, keep);
|
|
51956
52141
|
let projected = 0;
|
|
51957
52142
|
for (const h of HARNESS_SKILL_DIRS) {
|
|
51958
|
-
if (!
|
|
51959
|
-
const dir =
|
|
52143
|
+
if (!existsSync17(join21(root, h.configDir))) continue;
|
|
52144
|
+
const dir = join21(root, h.skillsDir);
|
|
51960
52145
|
mkdirSync7(dir, { recursive: true });
|
|
51961
52146
|
for (const slug2 of slugs) {
|
|
51962
|
-
linkOrCopy(
|
|
52147
|
+
linkOrCopy(join21(dir, slug2), join21(agentsSkillsDir, slug2));
|
|
51963
52148
|
projected++;
|
|
51964
52149
|
}
|
|
51965
52150
|
reconcileNamespaced(dir, keep);
|
|
@@ -51968,15 +52153,15 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51968
52153
|
return { slugs, emitted, projected };
|
|
51969
52154
|
}
|
|
51970
52155
|
function emitInputsFromManifest(erretaDir, manifestPath) {
|
|
51971
|
-
if (!
|
|
52156
|
+
if (!existsSync17(manifestPath)) return [];
|
|
51972
52157
|
try {
|
|
51973
|
-
const parsed = JSON.parse(
|
|
52158
|
+
const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
|
|
51974
52159
|
return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
|
|
51975
52160
|
id: s.id,
|
|
51976
52161
|
title: s.title ?? s.id,
|
|
51977
52162
|
layer: s.layer ?? "technique",
|
|
51978
52163
|
confidence: s.confidence ?? 0,
|
|
51979
|
-
bodyPath:
|
|
52164
|
+
bodyPath: join21(erretaDir, s.file)
|
|
51980
52165
|
}));
|
|
51981
52166
|
} catch {
|
|
51982
52167
|
return [];
|
|
@@ -51990,17 +52175,17 @@ var GITIGNORE_LINES = [
|
|
|
51990
52175
|
".cursor/skills/errata-*/"
|
|
51991
52176
|
];
|
|
51992
52177
|
function ensureSkillGitignore(root) {
|
|
51993
|
-
const path2 =
|
|
52178
|
+
const path2 = join21(root, ".gitignore");
|
|
51994
52179
|
let current = "";
|
|
51995
52180
|
try {
|
|
51996
|
-
current =
|
|
52181
|
+
current = existsSync17(path2) ? readFileSync16(path2, "utf8") : "";
|
|
51997
52182
|
} catch {
|
|
51998
52183
|
return;
|
|
51999
52184
|
}
|
|
52000
52185
|
if (current.includes(GITIGNORE_MARK)) return;
|
|
52001
52186
|
const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
|
|
52002
52187
|
try {
|
|
52003
|
-
|
|
52188
|
+
writeFileSync14(path2, `${current}${prefix}
|
|
52004
52189
|
${GITIGNORE_LINES.join("\n")}
|
|
52005
52190
|
`, "utf8");
|
|
52006
52191
|
} catch {
|
|
@@ -52061,20 +52246,20 @@ init_paths();
|
|
|
52061
52246
|
// src/profile.ts
|
|
52062
52247
|
init_src2();
|
|
52063
52248
|
init_paths();
|
|
52064
|
-
import { existsSync as
|
|
52249
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "node:fs";
|
|
52065
52250
|
import { createHash as createHash12 } from "node:crypto";
|
|
52066
|
-
import { join as
|
|
52251
|
+
import { join as join23 } from "node:path";
|
|
52067
52252
|
|
|
52068
52253
|
// src/git-remote.ts
|
|
52069
52254
|
init_src();
|
|
52070
|
-
import { existsSync as
|
|
52071
|
-
import { isAbsolute as isAbsolute3, join as
|
|
52255
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync4 } from "node:fs";
|
|
52256
|
+
import { isAbsolute as isAbsolute3, join as join22, resolve as resolve5 } from "node:path";
|
|
52072
52257
|
function resolveGitDir(root) {
|
|
52073
|
-
const dotGit =
|
|
52258
|
+
const dotGit = join22(root, ".git");
|
|
52074
52259
|
try {
|
|
52075
52260
|
const st = statSync4(dotGit);
|
|
52076
52261
|
if (st.isDirectory()) return dotGit;
|
|
52077
|
-
const m = /^gitdir:\s*(.+?)\s*$/m.exec(
|
|
52262
|
+
const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync17(dotGit, "utf8"));
|
|
52078
52263
|
if (!m) return null;
|
|
52079
52264
|
const dir = m[1];
|
|
52080
52265
|
return isAbsolute3(dir) ? dir : resolve5(root, dir);
|
|
@@ -52083,22 +52268,22 @@ function resolveGitDir(root) {
|
|
|
52083
52268
|
}
|
|
52084
52269
|
}
|
|
52085
52270
|
function gitConfigPath(gitDir) {
|
|
52086
|
-
const commondirFile =
|
|
52087
|
-
if (
|
|
52088
|
-
const common =
|
|
52271
|
+
const commondirFile = join22(gitDir, "commondir");
|
|
52272
|
+
if (existsSync18(commondirFile)) {
|
|
52273
|
+
const common = readFileSync17(commondirFile, "utf8").trim();
|
|
52089
52274
|
const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
|
|
52090
|
-
return
|
|
52275
|
+
return join22(commonDir, "config");
|
|
52091
52276
|
}
|
|
52092
|
-
return
|
|
52277
|
+
return join22(gitDir, "config");
|
|
52093
52278
|
}
|
|
52094
52279
|
function readRemotes(root) {
|
|
52095
52280
|
const gitDir = resolveGitDir(root);
|
|
52096
52281
|
if (!gitDir) return [];
|
|
52097
52282
|
const cfgPath = gitConfigPath(gitDir);
|
|
52098
|
-
if (!
|
|
52283
|
+
if (!existsSync18(cfgPath)) return [];
|
|
52099
52284
|
let txt;
|
|
52100
52285
|
try {
|
|
52101
|
-
txt =
|
|
52286
|
+
txt = readFileSync17(cfgPath, "utf8");
|
|
52102
52287
|
} catch {
|
|
52103
52288
|
return [];
|
|
52104
52289
|
}
|
|
@@ -52134,13 +52319,13 @@ function refreshRepoLocator(root, profile) {
|
|
|
52134
52319
|
}
|
|
52135
52320
|
function loadProfile(root) {
|
|
52136
52321
|
const p = workspacePaths(root);
|
|
52137
|
-
if (!
|
|
52138
|
-
return JSON.parse(
|
|
52322
|
+
if (!existsSync19(p.workspaceJson)) return null;
|
|
52323
|
+
return JSON.parse(readFileSync18(p.workspaceJson, "utf8"));
|
|
52139
52324
|
}
|
|
52140
52325
|
function saveProfile(root, profile) {
|
|
52141
52326
|
const p = workspacePaths(root);
|
|
52142
52327
|
ensureDir(p.configDir);
|
|
52143
|
-
|
|
52328
|
+
writeFileSync15(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
52144
52329
|
}
|
|
52145
52330
|
function autodetectProfile(root) {
|
|
52146
52331
|
const id = workspaceId(root);
|
|
@@ -52148,10 +52333,10 @@ function autodetectProfile(root) {
|
|
|
52148
52333
|
const p = emptyProfile(id, name2);
|
|
52149
52334
|
const locator = detectRepoLocator(root);
|
|
52150
52335
|
if (locator) p.repoLocator = locator;
|
|
52151
|
-
const pkgPath =
|
|
52152
|
-
if (
|
|
52336
|
+
const pkgPath = join23(root, "package.json");
|
|
52337
|
+
if (existsSync19(pkgPath)) {
|
|
52153
52338
|
try {
|
|
52154
|
-
const pkg = JSON.parse(
|
|
52339
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
52155
52340
|
p.languages.push("typescript", "javascript");
|
|
52156
52341
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
52157
52342
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -52172,10 +52357,10 @@ function autodetectProfile(root) {
|
|
|
52172
52357
|
} catch {
|
|
52173
52358
|
}
|
|
52174
52359
|
}
|
|
52175
|
-
const pyproject =
|
|
52176
|
-
if (
|
|
52360
|
+
const pyproject = join23(root, "pyproject.toml");
|
|
52361
|
+
if (existsSync19(pyproject)) {
|
|
52177
52362
|
try {
|
|
52178
|
-
const txt =
|
|
52363
|
+
const txt = readFileSync18(pyproject, "utf8");
|
|
52179
52364
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
52180
52365
|
p.languages.push("python");
|
|
52181
52366
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -52186,16 +52371,16 @@ function autodetectProfile(root) {
|
|
|
52186
52371
|
} catch {
|
|
52187
52372
|
}
|
|
52188
52373
|
}
|
|
52189
|
-
const reqs =
|
|
52190
|
-
if (
|
|
52374
|
+
const reqs = join23(root, "requirements.txt");
|
|
52375
|
+
if (existsSync19(reqs)) {
|
|
52191
52376
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
52192
52377
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
52193
52378
|
}
|
|
52194
|
-
if (
|
|
52379
|
+
if (existsSync19(join23(root, "go.mod"))) {
|
|
52195
52380
|
p.languages.push("go");
|
|
52196
52381
|
p.stack.push("go");
|
|
52197
52382
|
}
|
|
52198
|
-
if (
|
|
52383
|
+
if (existsSync19(join23(root, "Cargo.toml"))) {
|
|
52199
52384
|
p.languages.push("rust");
|
|
52200
52385
|
p.stack.push("rust");
|
|
52201
52386
|
}
|
|
@@ -52205,17 +52390,17 @@ function autodetectProfile(root) {
|
|
|
52205
52390
|
}
|
|
52206
52391
|
|
|
52207
52392
|
// src/witness-queue.ts
|
|
52208
|
-
import { readFileSync as
|
|
52209
|
-
import { dirname as dirname9, join as
|
|
52393
|
+
import { readFileSync as readFileSync19, renameSync as renameSync2, writeFileSync as writeFileSync16 } from "node:fs";
|
|
52394
|
+
import { dirname as dirname9, join as join24 } from "node:path";
|
|
52210
52395
|
var WITNESS_QUEUE_CAP = 500;
|
|
52211
52396
|
var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
52212
52397
|
var WITNESS_MAX_ATTEMPTS = 5;
|
|
52213
52398
|
function witnessQueuePath(workspaceConfigDir) {
|
|
52214
|
-
return
|
|
52399
|
+
return join24(workspaceConfigDir, "witness-queue.json");
|
|
52215
52400
|
}
|
|
52216
52401
|
function loadWitnessQueue(path2) {
|
|
52217
52402
|
try {
|
|
52218
|
-
const raw2 = JSON.parse(
|
|
52403
|
+
const raw2 = JSON.parse(readFileSync19(path2, "utf8"));
|
|
52219
52404
|
if (!Array.isArray(raw2)) return [];
|
|
52220
52405
|
return raw2.filter(
|
|
52221
52406
|
(w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
|
|
@@ -52226,8 +52411,8 @@ function loadWitnessQueue(path2) {
|
|
|
52226
52411
|
}
|
|
52227
52412
|
function saveWitnessQueue(path2, queue) {
|
|
52228
52413
|
try {
|
|
52229
|
-
const tmp =
|
|
52230
|
-
|
|
52414
|
+
const tmp = join24(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
|
|
52415
|
+
writeFileSync16(tmp, JSON.stringify(queue), "utf8");
|
|
52231
52416
|
renameSync2(tmp, path2);
|
|
52232
52417
|
} catch {
|
|
52233
52418
|
}
|
|
@@ -52507,7 +52692,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
52507
52692
|
}
|
|
52508
52693
|
|
|
52509
52694
|
// src/engine.ts
|
|
52510
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
52695
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.247" : "2.0.0-alpha.0";
|
|
52511
52696
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
52512
52697
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
52513
52698
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -52517,7 +52702,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
52517
52702
|
function appendIdentityAudit(path2, record2, line) {
|
|
52518
52703
|
if (!record2.accepted && record2.score <= 0) return;
|
|
52519
52704
|
try {
|
|
52520
|
-
if (
|
|
52705
|
+
if (existsSync20(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
52521
52706
|
renameSync3(path2, `${path2}.1`);
|
|
52522
52707
|
}
|
|
52523
52708
|
appendFileSync2(path2, line);
|
|
@@ -52527,7 +52712,7 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
52527
52712
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
52528
52713
|
function loadTurnCursors(path2) {
|
|
52529
52714
|
try {
|
|
52530
|
-
const raw2 = JSON.parse(
|
|
52715
|
+
const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
|
|
52531
52716
|
return new Map(
|
|
52532
52717
|
Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
|
|
52533
52718
|
);
|
|
@@ -52537,7 +52722,7 @@ function loadTurnCursors(path2) {
|
|
|
52537
52722
|
}
|
|
52538
52723
|
function loadTurnOffsets(path2) {
|
|
52539
52724
|
try {
|
|
52540
|
-
const raw2 = JSON.parse(
|
|
52725
|
+
const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
|
|
52541
52726
|
const out2 = /* @__PURE__ */ new Map();
|
|
52542
52727
|
for (const [k, v] of Object.entries(raw2)) {
|
|
52543
52728
|
const off = typeof v === "object" && v !== null ? v.offset : void 0;
|
|
@@ -52553,7 +52738,7 @@ function saveTurnCursors(path2, cursors, offsets) {
|
|
|
52553
52738
|
const merged = {};
|
|
52554
52739
|
for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
|
|
52555
52740
|
for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
|
|
52556
|
-
|
|
52741
|
+
writeFileSync17(path2, JSON.stringify(merged), "utf8");
|
|
52557
52742
|
} catch {
|
|
52558
52743
|
}
|
|
52559
52744
|
}
|
|
@@ -52575,7 +52760,7 @@ function gitSourceWatchTargets(root) {
|
|
|
52575
52760
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
52576
52761
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
52577
52762
|
);
|
|
52578
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
52763
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join25(root, d) + sep4));
|
|
52579
52764
|
} catch {
|
|
52580
52765
|
}
|
|
52581
52766
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -52587,19 +52772,19 @@ function gitSourceWatchTargets(root) {
|
|
|
52587
52772
|
if (!f.startsWith(prefix)) continue;
|
|
52588
52773
|
const rest2 = f.slice(prefix.length);
|
|
52589
52774
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
52590
|
-
else targets.add(
|
|
52775
|
+
else targets.add(join25(root, f));
|
|
52591
52776
|
}
|
|
52592
52777
|
for (const c of children) {
|
|
52593
|
-
if (IGNORED_PATH.test(
|
|
52778
|
+
if (IGNORED_PATH.test(join25(root, c) + sep4)) continue;
|
|
52594
52779
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
52595
|
-
else targets.add(
|
|
52780
|
+
else targets.add(join25(root, c));
|
|
52596
52781
|
}
|
|
52597
52782
|
};
|
|
52598
52783
|
addUnder("");
|
|
52599
52784
|
if (targets.size > 0) return [...targets];
|
|
52600
52785
|
} catch {
|
|
52601
52786
|
}
|
|
52602
|
-
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(
|
|
52787
|
+
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
52788
|
}
|
|
52604
52789
|
function createWorkspaceEngine(opts) {
|
|
52605
52790
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -52757,7 +52942,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52757
52942
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
52758
52943
|
let episodeId2;
|
|
52759
52944
|
if (srcPaths.length > 0) {
|
|
52760
|
-
const abs = srcPaths.map((p) =>
|
|
52945
|
+
const abs = srcPaths.map((p) => join25(opts.workspaceRoot, p));
|
|
52761
52946
|
try {
|
|
52762
52947
|
const r = await runReindexPass(
|
|
52763
52948
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -52793,8 +52978,8 @@ function createWorkspaceEngine(opts) {
|
|
|
52793
52978
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
52794
52979
|
);
|
|
52795
52980
|
};
|
|
52796
|
-
const gitDir =
|
|
52797
|
-
if (
|
|
52981
|
+
const gitDir = join25(opts.workspaceRoot, ".git");
|
|
52982
|
+
if (existsSync20(gitDir)) {
|
|
52798
52983
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
52799
52984
|
void handleGitEvent(ev).catch((err2) => {
|
|
52800
52985
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -52864,10 +53049,10 @@ function createWorkspaceEngine(opts) {
|
|
|
52864
53049
|
});
|
|
52865
53050
|
doneRender?.();
|
|
52866
53051
|
writeContextFile(opts.workspaceRoot, body2);
|
|
52867
|
-
const target =
|
|
53052
|
+
const target = join25(opts.workspaceRoot, "AGENTS.md");
|
|
52868
53053
|
writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
|
|
52869
53054
|
if (elicit) {
|
|
52870
|
-
writePrimingHandles(
|
|
53055
|
+
writePrimingHandles(join25(paths.configDir, "priming-handles.json"), [
|
|
52871
53056
|
...snapshot.recentProblems.map((r) => r.node),
|
|
52872
53057
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
52873
53058
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -52958,6 +53143,17 @@ function createWorkspaceEngine(opts) {
|
|
|
52958
53143
|
} catch (err2) {
|
|
52959
53144
|
console.warn("[errata] anchor backfill failed:", err2);
|
|
52960
53145
|
}
|
|
53146
|
+
try {
|
|
53147
|
+
const r = repairInvalidEdges(store, { configDir: paths.configDir, now: Date.now() });
|
|
53148
|
+
if (!r.skipped && r.invalid > 0) {
|
|
53149
|
+
console.log(
|
|
53150
|
+
`[errata] edge repair: ${r.retyped} edge(s) retyped, ${r.closed} closed (${Object.entries(r.byType).map(([t, n]) => `${t}x${n}`).join(", ")})`
|
|
53151
|
+
);
|
|
53152
|
+
refreshContextNow();
|
|
53153
|
+
}
|
|
53154
|
+
} catch (err2) {
|
|
53155
|
+
console.warn("[errata] edge repair failed:", err2);
|
|
53156
|
+
}
|
|
52961
53157
|
try {
|
|
52962
53158
|
const c = backfillConstraintKind(store, {
|
|
52963
53159
|
root: opts.workspaceRoot,
|
|
@@ -53072,7 +53268,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53072
53268
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
53073
53269
|
});
|
|
53074
53270
|
};
|
|
53075
|
-
const turnCursorPath =
|
|
53271
|
+
const turnCursorPath = join25(paths.configDir, "turn-cursors.json");
|
|
53076
53272
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
53077
53273
|
const turnOffset = loadTurnOffsets(turnCursorPath);
|
|
53078
53274
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
@@ -53096,7 +53292,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53096
53292
|
const t = Date.now();
|
|
53097
53293
|
let processedTurns = 0;
|
|
53098
53294
|
const elicit = isEdgeElicitationEnabled();
|
|
53099
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
53295
|
+
const handleMap = elicit ? readPrimingHandles(join25(paths.configDir, "priming-handles.json")) : {};
|
|
53100
53296
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
53101
53297
|
const toRel = (abs) => {
|
|
53102
53298
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -53405,9 +53601,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53405
53601
|
if (targetId === pid) continue;
|
|
53406
53602
|
const target = store.getNode(targetId);
|
|
53407
53603
|
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 });
|
|
53604
|
+
mintCiteEdge(pid, targetId, citeEdgeType(target.label), inst.evidence === "witnessed" ? 0.4 : 0.3, { instanceCite: true, evidence: inst.evidence });
|
|
53411
53605
|
}
|
|
53412
53606
|
}
|
|
53413
53607
|
for (const tf of plan.transfers) {
|
|
@@ -53707,7 +53901,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53707
53901
|
try {
|
|
53708
53902
|
const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
|
|
53709
53903
|
emitAndProjectSkills(opts.workspaceRoot, inputs);
|
|
53710
|
-
writePrimingHandles(
|
|
53904
|
+
writePrimingHandles(join25(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
|
|
53711
53905
|
} catch (err2) {
|
|
53712
53906
|
console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
|
|
53713
53907
|
}
|
|
@@ -53894,7 +54088,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53894
54088
|
console.log(
|
|
53895
54089
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
53896
54090
|
);
|
|
53897
|
-
const pending =
|
|
54091
|
+
const pending = existsSync20(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
53898
54092
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
53899
54093
|
}
|
|
53900
54094
|
try {
|
|
@@ -53981,7 +54175,7 @@ async function startDaemon(opts) {
|
|
|
53981
54175
|
reviewUrl: () => webUiUrl + "/review"
|
|
53982
54176
|
});
|
|
53983
54177
|
const writeLockFile = (url2) => {
|
|
53984
|
-
|
|
54178
|
+
writeFileSync18(
|
|
53985
54179
|
engine.paths.daemonLock,
|
|
53986
54180
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
53987
54181
|
"utf8"
|
|
@@ -54024,7 +54218,7 @@ async function startDaemon(opts) {
|
|
|
54024
54218
|
);
|
|
54025
54219
|
await engine.stop();
|
|
54026
54220
|
try {
|
|
54027
|
-
if (
|
|
54221
|
+
if (existsSync21(engine.paths.daemonLock)) {
|
|
54028
54222
|
}
|
|
54029
54223
|
} catch {
|
|
54030
54224
|
}
|
|
@@ -54041,16 +54235,16 @@ async function listenServer(fetchFn, port) {
|
|
|
54041
54235
|
|
|
54042
54236
|
// src/registry.ts
|
|
54043
54237
|
init_paths();
|
|
54044
|
-
import { existsSync as
|
|
54045
|
-
import { join as
|
|
54238
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21, writeFileSync as writeFileSync19 } from "node:fs";
|
|
54239
|
+
import { join as join26 } from "node:path";
|
|
54046
54240
|
function registryPath() {
|
|
54047
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
54241
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join26(globalDir(), "workspaces.json");
|
|
54048
54242
|
}
|
|
54049
54243
|
function read() {
|
|
54050
54244
|
const p = registryPath();
|
|
54051
|
-
if (!
|
|
54245
|
+
if (!existsSync22(p)) return { version: 1, workspaces: {} };
|
|
54052
54246
|
try {
|
|
54053
|
-
const parsed = JSON.parse(
|
|
54247
|
+
const parsed = JSON.parse(readFileSync21(p, "utf8"));
|
|
54054
54248
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
54055
54249
|
} catch {
|
|
54056
54250
|
return { version: 1, workspaces: {} };
|
|
@@ -54058,7 +54252,7 @@ function read() {
|
|
|
54058
54252
|
}
|
|
54059
54253
|
function write(reg) {
|
|
54060
54254
|
ensureDir(globalDir());
|
|
54061
|
-
|
|
54255
|
+
writeFileSync19(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
54062
54256
|
}
|
|
54063
54257
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
54064
54258
|
const reg = read();
|
|
@@ -54075,7 +54269,7 @@ function pruneMissingWorkspaces() {
|
|
|
54075
54269
|
const reg = read();
|
|
54076
54270
|
const removed = [];
|
|
54077
54271
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
54078
|
-
if (!
|
|
54272
|
+
if (!existsSync22(entry.path)) {
|
|
54079
54273
|
removed.push(entry);
|
|
54080
54274
|
delete reg.workspaces[id];
|
|
54081
54275
|
}
|
|
@@ -54084,13 +54278,13 @@ function pruneMissingWorkspaces() {
|
|
|
54084
54278
|
return removed;
|
|
54085
54279
|
}
|
|
54086
54280
|
function workspaceStatus(entry) {
|
|
54087
|
-
const missing = !
|
|
54281
|
+
const missing = !existsSync22(entry.path);
|
|
54088
54282
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
54089
54283
|
let running = false;
|
|
54090
54284
|
let webUiUrl = null;
|
|
54091
|
-
if (
|
|
54285
|
+
if (existsSync22(lockPath)) {
|
|
54092
54286
|
try {
|
|
54093
|
-
const lock = JSON.parse(
|
|
54287
|
+
const lock = JSON.parse(readFileSync21(lockPath, "utf8"));
|
|
54094
54288
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
54095
54289
|
running = true;
|
|
54096
54290
|
webUiUrl = lock.webUiUrl;
|
|
@@ -54118,7 +54312,7 @@ function pidAlive(pid) {
|
|
|
54118
54312
|
// src/multi.ts
|
|
54119
54313
|
init_dist();
|
|
54120
54314
|
init_src4();
|
|
54121
|
-
import { readFileSync as
|
|
54315
|
+
import { readFileSync as readFileSync24, unlinkSync as unlinkSync3, writeFileSync as writeFileSync20 } from "node:fs";
|
|
54122
54316
|
|
|
54123
54317
|
// src/principle-sync.ts
|
|
54124
54318
|
init_src4();
|
|
@@ -54146,8 +54340,8 @@ init_reconcile();
|
|
|
54146
54340
|
|
|
54147
54341
|
// src/lockfile-auto.ts
|
|
54148
54342
|
init_src();
|
|
54149
|
-
import { existsSync as
|
|
54150
|
-
import { join as
|
|
54343
|
+
import { existsSync as existsSync23, readFileSync as readFileSync22 } from "node:fs";
|
|
54344
|
+
import { join as join27 } from "node:path";
|
|
54151
54345
|
|
|
54152
54346
|
// src/package-index.ts
|
|
54153
54347
|
init_src();
|
|
@@ -54296,11 +54490,11 @@ function runLockfilePass(opts) {
|
|
|
54296
54490
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
54297
54491
|
];
|
|
54298
54492
|
for (const c of candidates) {
|
|
54299
|
-
const p =
|
|
54300
|
-
if (!
|
|
54493
|
+
const p = join27(opts.root, c.file);
|
|
54494
|
+
if (!existsSync23(p)) continue;
|
|
54301
54495
|
let sbom;
|
|
54302
54496
|
try {
|
|
54303
|
-
sbom = c.parse(
|
|
54497
|
+
sbom = c.parse(readFileSync22(p, "utf8"));
|
|
54304
54498
|
} catch {
|
|
54305
54499
|
continue;
|
|
54306
54500
|
}
|
|
@@ -54748,7 +54942,7 @@ var ConsolidateWorker = class {
|
|
|
54748
54942
|
init_paths();
|
|
54749
54943
|
|
|
54750
54944
|
// src/lock.ts
|
|
54751
|
-
import { existsSync as
|
|
54945
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23 } from "node:fs";
|
|
54752
54946
|
function isProcessAlive(pid) {
|
|
54753
54947
|
if (!pid || pid <= 0) return false;
|
|
54754
54948
|
try {
|
|
@@ -54759,9 +54953,9 @@ function isProcessAlive(pid) {
|
|
|
54759
54953
|
}
|
|
54760
54954
|
}
|
|
54761
54955
|
function readDaemonLock(lockPath) {
|
|
54762
|
-
if (!
|
|
54956
|
+
if (!existsSync24(lockPath)) return null;
|
|
54763
54957
|
try {
|
|
54764
|
-
const lock = JSON.parse(
|
|
54958
|
+
const lock = JSON.parse(readFileSync23(lockPath, "utf8"));
|
|
54765
54959
|
return typeof lock.pid === "number" ? lock : null;
|
|
54766
54960
|
} catch {
|
|
54767
54961
|
return null;
|
|
@@ -55040,12 +55234,12 @@ async function reanchorProject(opts) {
|
|
|
55040
55234
|
}
|
|
55041
55235
|
|
|
55042
55236
|
// src/adopt.ts
|
|
55043
|
-
import { existsSync as
|
|
55044
|
-
import { dirname as dirname10, join as
|
|
55237
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
55238
|
+
import { dirname as dirname10, join as join28 } from "node:path";
|
|
55045
55239
|
function findGitRoot(absPath) {
|
|
55046
55240
|
let dir = absPath;
|
|
55047
55241
|
for (let depth = 0; depth < 64; depth++) {
|
|
55048
|
-
if (
|
|
55242
|
+
if (existsSync25(join28(dir, ".git"))) return dir;
|
|
55049
55243
|
const parent = dirname10(dir);
|
|
55050
55244
|
if (parent === dir) return null;
|
|
55051
55245
|
dir = parent;
|
|
@@ -55294,7 +55488,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55294
55488
|
void ambientLinkAll();
|
|
55295
55489
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
55296
55490
|
try {
|
|
55297
|
-
|
|
55491
|
+
writeFileSync20(
|
|
55298
55492
|
rec.engine.paths.daemonLock,
|
|
55299
55493
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
55300
55494
|
"utf8"
|
|
@@ -55483,7 +55677,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55483
55677
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
55484
55678
|
try {
|
|
55485
55679
|
ensureDir(globalDir());
|
|
55486
|
-
|
|
55680
|
+
writeFileSync20(
|
|
55487
55681
|
lockPath,
|
|
55488
55682
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
55489
55683
|
"utf8"
|
|
@@ -55492,7 +55686,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55492
55686
|
}
|
|
55493
55687
|
for (const r of records) {
|
|
55494
55688
|
try {
|
|
55495
|
-
|
|
55689
|
+
writeFileSync20(
|
|
55496
55690
|
r.engine.paths.daemonLock,
|
|
55497
55691
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
55498
55692
|
"utf8"
|
|
@@ -55990,7 +56184,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55990
56184
|
},
|
|
55991
56185
|
async stop() {
|
|
55992
56186
|
try {
|
|
55993
|
-
const cur =
|
|
56187
|
+
const cur = readFileSync24(lockPath, "utf8");
|
|
55994
56188
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
55995
56189
|
} catch {
|
|
55996
56190
|
}
|
|
@@ -57007,21 +57201,21 @@ async function cmdInit() {
|
|
|
57007
57201
|
if (!skipHooks) {
|
|
57008
57202
|
console.log("");
|
|
57009
57203
|
console.log("installing harness hooks...");
|
|
57010
|
-
const { existsSync:
|
|
57011
|
-
const { join:
|
|
57204
|
+
const { existsSync: existsSync27 } = await import("node:fs");
|
|
57205
|
+
const { join: join30 } = await import("node:path");
|
|
57012
57206
|
try {
|
|
57013
57207
|
await installClaudeHooks(port);
|
|
57014
57208
|
} catch (err2) {
|
|
57015
57209
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
57016
57210
|
}
|
|
57017
|
-
if (
|
|
57211
|
+
if (existsSync27(join30(ROOT, ".cursor"))) {
|
|
57018
57212
|
try {
|
|
57019
57213
|
await installCursorMcpConfig();
|
|
57020
57214
|
} catch (err2) {
|
|
57021
57215
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
57022
57216
|
}
|
|
57023
57217
|
}
|
|
57024
|
-
if (
|
|
57218
|
+
if (existsSync27(join30(ROOT, ".codex"))) {
|
|
57025
57219
|
try {
|
|
57026
57220
|
await installCodexHooks(port);
|
|
57027
57221
|
} catch (err2) {
|
|
@@ -57178,9 +57372,9 @@ async function cmdStatus() {
|
|
|
57178
57372
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
57179
57373
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
57180
57374
|
}
|
|
57181
|
-
console.log(` graph db: ${
|
|
57182
|
-
console.log(` event log: ${
|
|
57183
|
-
if (
|
|
57375
|
+
console.log(` graph db: ${existsSync26(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
57376
|
+
console.log(` event log: ${existsSync26(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
57377
|
+
if (existsSync26(paths.castalia)) {
|
|
57184
57378
|
try {
|
|
57185
57379
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
57186
57380
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -57196,6 +57390,16 @@ async function cmdStatus() {
|
|
|
57196
57390
|
}
|
|
57197
57391
|
}
|
|
57198
57392
|
console.log(` contribute: ${pending} pending of ${total} instance node(s)`);
|
|
57393
|
+
const rejections = store.edgeRejections();
|
|
57394
|
+
if (rejections.length > 0) {
|
|
57395
|
+
const refused = rejections.reduce((n, r) => n + r.count, 0);
|
|
57396
|
+
console.log(` edges: ${refused} refused by the ontology gate \u2014 a producer is emitting invalid edges`);
|
|
57397
|
+
for (const r of rejections.slice(0, 3)) {
|
|
57398
|
+
const mins = Math.max(0, Math.round((Date.now() - r.lastAt) / 6e4));
|
|
57399
|
+
const age = mins < 60 ? `${mins}m ago` : mins < 1440 ? `${Math.round(mins / 60)}h ago` : `${Math.round(mins / 1440)}d ago`;
|
|
57400
|
+
console.log(` ${r.count}x ${r.type} (last ${age})${r.sample ? ` \u2014 ${r.sample}` : ""}`);
|
|
57401
|
+
}
|
|
57402
|
+
}
|
|
57199
57403
|
} finally {
|
|
57200
57404
|
store.close();
|
|
57201
57405
|
}
|
|
@@ -57844,11 +58048,11 @@ function cmdInstallationProfile(args2) {
|
|
|
57844
58048
|
}
|
|
57845
58049
|
async function cmdReview() {
|
|
57846
58050
|
const paths = workspacePaths(ROOT);
|
|
57847
|
-
if (!
|
|
58051
|
+
if (!existsSync26(paths.reviewQueue)) {
|
|
57848
58052
|
console.log("(review queue empty)");
|
|
57849
58053
|
return;
|
|
57850
58054
|
}
|
|
57851
|
-
const queue = JSON.parse(
|
|
58055
|
+
const queue = JSON.parse(readFileSync25(paths.reviewQueue, "utf8"));
|
|
57852
58056
|
if (queue.length === 0) {
|
|
57853
58057
|
console.log("(review queue empty)");
|
|
57854
58058
|
return;
|
|
@@ -58519,7 +58723,7 @@ async function gatherRepo(store, ws) {
|
|
|
58519
58723
|
};
|
|
58520
58724
|
}
|
|
58521
58725
|
async function gatherReportData(generatedAt) {
|
|
58522
|
-
const { existsSync:
|
|
58726
|
+
const { existsSync: existsSync27 } = await import("node:fs");
|
|
58523
58727
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
58524
58728
|
const cfg = loadConfig();
|
|
58525
58729
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -58527,7 +58731,7 @@ async function gatherReportData(generatedAt) {
|
|
|
58527
58731
|
for (const ws of listWorkspaces()) {
|
|
58528
58732
|
if (ws.missing) continue;
|
|
58529
58733
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
58530
|
-
if (!
|
|
58734
|
+
if (!existsSync27(dbPath)) continue;
|
|
58531
58735
|
let store = null;
|
|
58532
58736
|
try {
|
|
58533
58737
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -58558,7 +58762,7 @@ async function gatherReportData(generatedAt) {
|
|
|
58558
58762
|
};
|
|
58559
58763
|
}
|
|
58560
58764
|
async function cmdReport(args2) {
|
|
58561
|
-
const { mkdirSync: mkdirSync8, writeFileSync:
|
|
58765
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58562
58766
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
58563
58767
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
58564
58768
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -58571,8 +58775,8 @@ async function cmdReport(args2) {
|
|
|
58571
58775
|
const outDir = workspacePaths(ROOT).configDir;
|
|
58572
58776
|
mkdirSync8(outDir, { recursive: true });
|
|
58573
58777
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
58574
|
-
for (const f of files)
|
|
58575
|
-
const indexPath =
|
|
58778
|
+
for (const f of files) writeFileSync21(join29(outDir, f.name), f.html, "utf8");
|
|
58779
|
+
const indexPath = join29(outDir, "report.html");
|
|
58576
58780
|
console.log(`report \u2192 ${indexPath}`);
|
|
58577
58781
|
console.log(
|
|
58578
58782
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -58690,15 +58894,15 @@ function hookRelayCommand(port, path2) {
|
|
|
58690
58894
|
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
58895
|
}
|
|
58692
58896
|
async function installClaudeHooks(port) {
|
|
58693
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58694
|
-
const { join:
|
|
58695
|
-
const dir =
|
|
58696
|
-
if (!
|
|
58697
|
-
const file2 =
|
|
58897
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58898
|
+
const { join: join30 } = await import("node:path");
|
|
58899
|
+
const dir = join30(ROOT, ".claude");
|
|
58900
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
58901
|
+
const file2 = join30(dir, "settings.json");
|
|
58698
58902
|
let settings = {};
|
|
58699
|
-
if (
|
|
58903
|
+
if (existsSync27(file2)) {
|
|
58700
58904
|
try {
|
|
58701
|
-
settings = JSON.parse(
|
|
58905
|
+
settings = JSON.parse(readFileSync26(file2, "utf8"));
|
|
58702
58906
|
} catch {
|
|
58703
58907
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58704
58908
|
process.exit(2);
|
|
@@ -58744,10 +58948,10 @@ async function installClaudeHooks(port) {
|
|
|
58744
58948
|
dropErrata(list);
|
|
58745
58949
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
58746
58950
|
}
|
|
58747
|
-
|
|
58951
|
+
writeFileSync21(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
58748
58952
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
58749
58953
|
await installClaudeMcpConfig();
|
|
58750
|
-
const claudeMd =
|
|
58954
|
+
const claudeMd = join30(ROOT, "CLAUDE.md");
|
|
58751
58955
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
58752
58956
|
if (recall.kind === "collision") {
|
|
58753
58957
|
console.warn(
|
|
@@ -58759,15 +58963,15 @@ async function installClaudeHooks(port) {
|
|
|
58759
58963
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58760
58964
|
}
|
|
58761
58965
|
async function installClaudeMcpConfig() {
|
|
58762
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58763
|
-
const { join:
|
|
58764
|
-
const file2 =
|
|
58966
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58967
|
+
const { join: join30, dirname: dirname11 } = await import("node:path");
|
|
58968
|
+
const file2 = join30(ROOT, ".mcp.json");
|
|
58765
58969
|
const dir = dirname11(file2);
|
|
58766
|
-
if (!
|
|
58970
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
58767
58971
|
let cfg = {};
|
|
58768
|
-
if (
|
|
58972
|
+
if (existsSync27(file2)) {
|
|
58769
58973
|
try {
|
|
58770
|
-
cfg = JSON.parse(
|
|
58974
|
+
cfg = JSON.parse(readFileSync26(file2, "utf8"));
|
|
58771
58975
|
} catch {
|
|
58772
58976
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58773
58977
|
process.exit(2);
|
|
@@ -58775,21 +58979,21 @@ async function installClaudeMcpConfig() {
|
|
|
58775
58979
|
}
|
|
58776
58980
|
cfg.mcpServers ??= {};
|
|
58777
58981
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58778
|
-
|
|
58982
|
+
writeFileSync21(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58779
58983
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
58780
58984
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
58781
58985
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
58782
58986
|
}
|
|
58783
58987
|
async function installCursorMcpConfig() {
|
|
58784
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58785
|
-
const { join:
|
|
58786
|
-
const dir =
|
|
58787
|
-
if (!
|
|
58788
|
-
const file2 =
|
|
58988
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
58989
|
+
const { join: join30 } = await import("node:path");
|
|
58990
|
+
const dir = join30(ROOT, ".cursor");
|
|
58991
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
58992
|
+
const file2 = join30(dir, "mcp.json");
|
|
58789
58993
|
let cfg = {};
|
|
58790
|
-
if (
|
|
58994
|
+
if (existsSync27(file2)) {
|
|
58791
58995
|
try {
|
|
58792
|
-
cfg = JSON.parse(
|
|
58996
|
+
cfg = JSON.parse(readFileSync26(file2, "utf8"));
|
|
58793
58997
|
} catch {
|
|
58794
58998
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58795
58999
|
process.exit(2);
|
|
@@ -58797,7 +59001,7 @@ async function installCursorMcpConfig() {
|
|
|
58797
59001
|
}
|
|
58798
59002
|
cfg.mcpServers ??= {};
|
|
58799
59003
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58800
|
-
|
|
59004
|
+
writeFileSync21(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58801
59005
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
58802
59006
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
58803
59007
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -58805,16 +59009,16 @@ async function installCursorMcpConfig() {
|
|
|
58805
59009
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
58806
59010
|
}
|
|
58807
59011
|
async function installCodexHooks(port) {
|
|
58808
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58809
|
-
const { join:
|
|
58810
|
-
const dir =
|
|
58811
|
-
if (!
|
|
58812
|
-
const file2 =
|
|
59012
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync27, readFileSync: readFileSync26, writeFileSync: writeFileSync21 } = await import("node:fs");
|
|
59013
|
+
const { join: join30 } = await import("node:path");
|
|
59014
|
+
const dir = join30(ROOT, ".codex");
|
|
59015
|
+
if (!existsSync27(dir)) mkdirSync8(dir, { recursive: true });
|
|
59016
|
+
const file2 = join30(dir, "config.toml");
|
|
58813
59017
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
58814
59018
|
const END = `# <<< errata hooks`;
|
|
58815
59019
|
let existing = "";
|
|
58816
|
-
if (
|
|
58817
|
-
existing =
|
|
59020
|
+
if (existsSync27(file2)) {
|
|
59021
|
+
existing = readFileSync26(file2, "utf8");
|
|
58818
59022
|
const beginIdx = existing.indexOf(BEGIN);
|
|
58819
59023
|
const endIdx = existing.indexOf(END);
|
|
58820
59024
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -58843,7 +59047,7 @@ ${END}
|
|
|
58843
59047
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
58844
59048
|
|
|
58845
59049
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
58846
|
-
|
|
59050
|
+
writeFileSync21(file2, final, "utf8");
|
|
58847
59051
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
58848
59052
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58849
59053
|
console.log("");
|
|
@@ -59157,7 +59361,7 @@ async function cmdDash(args2) {
|
|
|
59157
59361
|
await yieldToLoop2();
|
|
59158
59362
|
try {
|
|
59159
59363
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
59160
|
-
const res = bleedRules(
|
|
59364
|
+
const res = bleedRules(join29(r.root, ".claude", "rules"), items);
|
|
59161
59365
|
if (res.written || res.pruned) {
|
|
59162
59366
|
console.log(
|
|
59163
59367
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|