@inerrata-corporation/errata 2.0.6-dev.2511 → 2.0.6-dev.2550
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/README.txt +22 -0
- package/consolidate-worker.mjs +74 -8
- package/errata.mjs +399 -137
- package/package.json +1 -1
- package/pass-worker.mjs +27 -2
package/README.txt
CHANGED
|
@@ -25,6 +25,28 @@ USE
|
|
|
25
25
|
|
|
26
26
|
Dashboard: http://127.0.0.1:7891
|
|
27
27
|
|
|
28
|
+
CODEX
|
|
29
|
+
|
|
30
|
+
errata install-hooks codex # explicit install or upgrade for this workspace
|
|
31
|
+
|
|
32
|
+
Init detects .codex in the project or CODEX_HOME (default ~/.codex). Successful
|
|
33
|
+
errata link flows also refresh detected Codex hooks; --skip-hooks opts out of
|
|
34
|
+
either automatic install. The installer preserves other config and writes its
|
|
35
|
+
Node relay into .codex/hooks/errata-relay.mjs. No curl or Bash dependency.
|
|
36
|
+
|
|
37
|
+
Restart/resume Codex after installing, and review/trust the hooks with /hooks.
|
|
38
|
+
If your Codex build gates hooks, enable [features] codex_hooks = true. Update
|
|
39
|
+
older Codex builds if UserPromptSubmit or tool hooks are unsupported.
|
|
40
|
+
|
|
41
|
+
SessionStart injects .errata/context.md, including startup/resume/compaction.
|
|
42
|
+
UserPromptSubmit and PostToolUse inject it again only when it changes. Tool
|
|
43
|
+
recall and capture remain enabled. Refresh happens at a tool boundary, not
|
|
44
|
+
during model generation. The daemon must be running; unavailable hooks fail
|
|
45
|
+
open. AGENTS.md's file-read instruction remains a useful fallback.
|
|
46
|
+
|
|
47
|
+
The cloud MCP/plugin installer alone does not install this local daemon.
|
|
48
|
+
Install errata and run init in each workspace to enable daemon context.
|
|
49
|
+
|
|
28
50
|
UPDATE
|
|
29
51
|
|
|
30
52
|
errata update # pull the newest build on your channel (npm i -g)
|
package/consolidate-worker.mjs
CHANGED
|
@@ -15322,6 +15322,9 @@ var init_symbol_intent = __esm({
|
|
|
15322
15322
|
});
|
|
15323
15323
|
|
|
15324
15324
|
// ../../packages/shared/src/wire.ts
|
|
15325
|
+
function isAnchorLabelKind(kind) {
|
|
15326
|
+
return typeof kind === "string" && ANCHOR_LABEL_KINDS.includes(kind);
|
|
15327
|
+
}
|
|
15325
15328
|
function anchorVersionAttrs(attrs) {
|
|
15326
15329
|
if (!attrs) return {};
|
|
15327
15330
|
const commit = attrs["observedAtCommit"];
|
|
@@ -15331,7 +15334,24 @@ function anchorVersionAttrs(attrs) {
|
|
|
15331
15334
|
...typeof hash2 === "string" && ANCHOR_BODY_HASH_RE.test(hash2) ? { symbolContentHash: hash2 } : {}
|
|
15332
15335
|
};
|
|
15333
15336
|
}
|
|
15334
|
-
|
|
15337
|
+
function anchorLabelAttrs(attrs) {
|
|
15338
|
+
if (!attrs) return {};
|
|
15339
|
+
const relPath = attrs["labelRelPath"];
|
|
15340
|
+
const qname = attrs["labelQname"];
|
|
15341
|
+
const kind = attrs["labelKind"];
|
|
15342
|
+
const line = attrs["labelLine"];
|
|
15343
|
+
if (typeof relPath !== "string" || !ANCHOR_LABEL_PATH_RE.test(relPath)) return {};
|
|
15344
|
+
if (!isAnchorLabelKind(kind)) return {};
|
|
15345
|
+
const qnameOk = typeof qname === "string" && ANCHOR_LABEL_QNAME_RE.test(qname);
|
|
15346
|
+
if (kind !== "File" && !qnameOk) return {};
|
|
15347
|
+
return {
|
|
15348
|
+
labelRelPath: relPath,
|
|
15349
|
+
labelKind: kind,
|
|
15350
|
+
...kind !== "File" && qnameOk ? { labelQname: qname } : {},
|
|
15351
|
+
...typeof line === "number" && Number.isInteger(line) && line >= 1 && line <= 1e7 ? { labelLine: line } : {}
|
|
15352
|
+
};
|
|
15353
|
+
}
|
|
15354
|
+
var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, FILE_ANCHOR_QNAME, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
|
|
15335
15355
|
var init_wire = __esm({
|
|
15336
15356
|
"../../packages/shared/src/wire.ts"() {
|
|
15337
15357
|
"use strict";
|
|
@@ -15434,6 +15454,22 @@ var init_wire = __esm({
|
|
|
15434
15454
|
});
|
|
15435
15455
|
ANCHOR_COMMIT_SHA_RE = /^[0-9a-f]{7,40}$/;
|
|
15436
15456
|
ANCHOR_BODY_HASH_RE = /^[0-9a-f]{8,64}$/;
|
|
15457
|
+
ANCHOR_SYMBOL_KINDS = [
|
|
15458
|
+
"Function",
|
|
15459
|
+
"Class",
|
|
15460
|
+
"Method",
|
|
15461
|
+
"Module",
|
|
15462
|
+
"Interface",
|
|
15463
|
+
"Const",
|
|
15464
|
+
"Enum",
|
|
15465
|
+
"TypeAlias",
|
|
15466
|
+
"Namespace",
|
|
15467
|
+
"Property"
|
|
15468
|
+
];
|
|
15469
|
+
ANCHOR_LABEL_KINDS = [...ANCHOR_SYMBOL_KINDS, "File"];
|
|
15470
|
+
FILE_ANCHOR_QNAME = "";
|
|
15471
|
+
ANCHOR_LABEL_PATH_RE = /^(?![/])(?![A-Za-z]:)(?!(?:.*\/)?\.\.(?:\/|$))[^\x00-\x1f\x7f\\`]{1,512}$/;
|
|
15472
|
+
ANCHOR_LABEL_QNAME_RE = /^[^\x00-\x1f\x7f`]{1,256}$/;
|
|
15437
15473
|
CastaliaIngestEdgeSchema = external_exports.object({
|
|
15438
15474
|
fromCanonicalId: external_exports.string().min(6).max(160),
|
|
15439
15475
|
toCanonicalId: external_exports.string().min(6).max(160),
|
|
@@ -15453,7 +15489,17 @@ var init_wire = __esm({
|
|
|
15453
15489
|
* classify the anchor current / pre-change; absent ⇒ the pre-versioning
|
|
15454
15490
|
* contract, unverified. Only meaningful on `ANCHORED_AT`. */
|
|
15455
15491
|
observedAtCommit: external_exports.string().regex(ANCHOR_COMMIT_SHA_RE).optional(),
|
|
15456
|
-
symbolContentHash: external_exports.string().regex(ANCHOR_BODY_HASH_RE).optional()
|
|
15492
|
+
symbolContentHash: external_exports.string().regex(ANCHOR_BODY_HASH_RE).optional(),
|
|
15493
|
+
/** PJ-anchor-labels: the READABLE identity of the anchor's target —
|
|
15494
|
+
* repo-relative path, qualified name (absent for a File), kind and line.
|
|
15495
|
+
* Sent only for a project whose owner opted in; the door strips them again
|
|
15496
|
+
* for any project that has not (the daemon's flag is not trusted alone).
|
|
15497
|
+
* Prefixed `label*` so no local edge attr (`anchorLine` lives there
|
|
15498
|
+
* natively) can ride out under a shared key. */
|
|
15499
|
+
labelRelPath: external_exports.string().regex(ANCHOR_LABEL_PATH_RE).optional(),
|
|
15500
|
+
labelQname: external_exports.string().regex(ANCHOR_LABEL_QNAME_RE).optional(),
|
|
15501
|
+
labelKind: external_exports.enum(ANCHOR_LABEL_KINDS).optional(),
|
|
15502
|
+
labelLine: external_exports.number().int().min(1).max(1e7).optional()
|
|
15457
15503
|
}).optional()
|
|
15458
15504
|
});
|
|
15459
15505
|
SymbolSummarySidecarSchema = external_exports.record(
|
|
@@ -19153,19 +19199,39 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
19153
19199
|
for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
|
|
19154
19200
|
const target = store.getNode(e.to);
|
|
19155
19201
|
if (!target) continue;
|
|
19202
|
+
if (!isAnchorLabelKind(target.label)) continue;
|
|
19203
|
+
const isFile = target.label === "File";
|
|
19204
|
+
if (isFile && !project.anchorLabels) continue;
|
|
19156
19205
|
const relPath = target.attrs["relPath"];
|
|
19157
|
-
const qname = target.attrs["qname"];
|
|
19206
|
+
const qname = isFile ? FILE_ANCHOR_QNAME : target.attrs["qname"];
|
|
19158
19207
|
if (typeof relPath !== "string" || typeof qname !== "string") continue;
|
|
19159
|
-
if (ignored(relPath) || ignored(qname)) continue;
|
|
19160
|
-
|
|
19208
|
+
if (ignored(relPath) || qname !== "" && ignored(qname)) continue;
|
|
19209
|
+
const line = e.attrs?.["anchorLine"];
|
|
19210
|
+
const wireAttrs = {
|
|
19211
|
+
...anchorVersionAttrs(e.attrs),
|
|
19212
|
+
// PJ-anchor-labels: only for an opted-in project, and only through the
|
|
19213
|
+
// shared projection (invalid path/kind ⇒ no label, never half of one).
|
|
19214
|
+
...project.anchorLabels ? anchorLabelAttrs({
|
|
19215
|
+
labelRelPath: normalizeSymbolPath(relPath),
|
|
19216
|
+
labelKind: target.label,
|
|
19217
|
+
...isFile ? {} : { labelQname: qname },
|
|
19218
|
+
...typeof line === "number" ? { labelLine: line } : {}
|
|
19219
|
+
}) : {}
|
|
19220
|
+
};
|
|
19221
|
+
planned.push({
|
|
19222
|
+
e,
|
|
19223
|
+
target,
|
|
19224
|
+
symId: projectSymbolId(project.salt, project.projectId, relPath, qname, target.label),
|
|
19225
|
+
wireAttrs
|
|
19226
|
+
});
|
|
19161
19227
|
}
|
|
19162
19228
|
if (planned.length === 0) continue;
|
|
19163
19229
|
const dg = digest(
|
|
19164
|
-
planned.map(({
|
|
19230
|
+
planned.map(({ symId, wireAttrs }) => `ANCHORED_AT>${symId}>${JSON.stringify(wireAttrs)}`).sort()
|
|
19165
19231
|
);
|
|
19166
19232
|
if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
|
|
19167
19233
|
projectAnchorDigests[sourceId] = dg;
|
|
19168
|
-
for (const { e, target, symId } of planned) {
|
|
19234
|
+
for (const { e, target, symId, wireAttrs } of planned) {
|
|
19169
19235
|
if (!contextSeen.has(symId)) {
|
|
19170
19236
|
contextSeen.add(symId);
|
|
19171
19237
|
contextNodes.push({
|
|
@@ -19192,7 +19258,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
19192
19258
|
stability: "unstable"
|
|
19193
19259
|
});
|
|
19194
19260
|
}
|
|
19195
|
-
anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs:
|
|
19261
|
+
anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs: wireAttrs });
|
|
19196
19262
|
}
|
|
19197
19263
|
}
|
|
19198
19264
|
}
|
package/errata.mjs
CHANGED
|
@@ -15729,6 +15729,9 @@ function provenanceBand(source) {
|
|
|
15729
15729
|
function isSeedProvenance(source) {
|
|
15730
15730
|
return provenanceBand(source) === "seed";
|
|
15731
15731
|
}
|
|
15732
|
+
function isAnchorLabelKind(kind) {
|
|
15733
|
+
return typeof kind === "string" && ANCHOR_LABEL_KINDS.includes(kind);
|
|
15734
|
+
}
|
|
15732
15735
|
function anchorVersionAttrs(attrs) {
|
|
15733
15736
|
if (!attrs) return {};
|
|
15734
15737
|
const commit = attrs["observedAtCommit"];
|
|
@@ -15738,6 +15741,28 @@ function anchorVersionAttrs(attrs) {
|
|
|
15738
15741
|
...typeof hash2 === "string" && ANCHOR_BODY_HASH_RE.test(hash2) ? { symbolContentHash: hash2 } : {}
|
|
15739
15742
|
};
|
|
15740
15743
|
}
|
|
15744
|
+
function anchorLabelAttrs(attrs) {
|
|
15745
|
+
if (!attrs) return {};
|
|
15746
|
+
const relPath = attrs["labelRelPath"];
|
|
15747
|
+
const qname = attrs["labelQname"];
|
|
15748
|
+
const kind = attrs["labelKind"];
|
|
15749
|
+
const line = attrs["labelLine"];
|
|
15750
|
+
if (typeof relPath !== "string" || !ANCHOR_LABEL_PATH_RE.test(relPath)) return {};
|
|
15751
|
+
if (!isAnchorLabelKind(kind)) return {};
|
|
15752
|
+
const qnameOk = typeof qname === "string" && ANCHOR_LABEL_QNAME_RE.test(qname);
|
|
15753
|
+
if (kind !== "File" && !qnameOk) return {};
|
|
15754
|
+
return {
|
|
15755
|
+
labelRelPath: relPath,
|
|
15756
|
+
labelKind: kind,
|
|
15757
|
+
...kind !== "File" && qnameOk ? { labelQname: qname } : {},
|
|
15758
|
+
...typeof line === "number" && Number.isInteger(line) && line >= 1 && line <= 1e7 ? { labelLine: line } : {}
|
|
15759
|
+
};
|
|
15760
|
+
}
|
|
15761
|
+
function stripAnchorLabels(attrs) {
|
|
15762
|
+
const out2 = { ...attrs };
|
|
15763
|
+
for (const k of ANCHOR_LABEL_KEYS) delete out2[k];
|
|
15764
|
+
return out2;
|
|
15765
|
+
}
|
|
15741
15766
|
function validateCastaliaPayload(p) {
|
|
15742
15767
|
const errors = [];
|
|
15743
15768
|
const labelByCid = /* @__PURE__ */ new Map();
|
|
@@ -15767,7 +15792,7 @@ function summarizeIngestResult(r) {
|
|
|
15767
15792
|
...r.patternReconciliation ? { patternReconciliation: r.patternReconciliation } : {}
|
|
15768
15793
|
};
|
|
15769
15794
|
}
|
|
15770
|
-
var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, QUARANTINE_EXTRACTION_SOURCE_PREFIX, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
|
|
15795
|
+
var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, QUARANTINE_EXTRACTION_SOURCE_PREFIX, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, FILE_ANCHOR_QNAME, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, ANCHOR_LABEL_KEYS, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
|
|
15771
15796
|
var init_wire = __esm({
|
|
15772
15797
|
"../../packages/shared/src/wire.ts"() {
|
|
15773
15798
|
"use strict";
|
|
@@ -15873,6 +15898,23 @@ var init_wire = __esm({
|
|
|
15873
15898
|
});
|
|
15874
15899
|
ANCHOR_COMMIT_SHA_RE = /^[0-9a-f]{7,40}$/;
|
|
15875
15900
|
ANCHOR_BODY_HASH_RE = /^[0-9a-f]{8,64}$/;
|
|
15901
|
+
ANCHOR_SYMBOL_KINDS = [
|
|
15902
|
+
"Function",
|
|
15903
|
+
"Class",
|
|
15904
|
+
"Method",
|
|
15905
|
+
"Module",
|
|
15906
|
+
"Interface",
|
|
15907
|
+
"Const",
|
|
15908
|
+
"Enum",
|
|
15909
|
+
"TypeAlias",
|
|
15910
|
+
"Namespace",
|
|
15911
|
+
"Property"
|
|
15912
|
+
];
|
|
15913
|
+
ANCHOR_LABEL_KINDS = [...ANCHOR_SYMBOL_KINDS, "File"];
|
|
15914
|
+
FILE_ANCHOR_QNAME = "";
|
|
15915
|
+
ANCHOR_LABEL_PATH_RE = /^(?![/])(?![A-Za-z]:)(?!(?:.*\/)?\.\.(?:\/|$))[^\x00-\x1f\x7f\\`]{1,512}$/;
|
|
15916
|
+
ANCHOR_LABEL_QNAME_RE = /^[^\x00-\x1f\x7f`]{1,256}$/;
|
|
15917
|
+
ANCHOR_LABEL_KEYS = ["labelRelPath", "labelQname", "labelKind", "labelLine"];
|
|
15876
15918
|
CastaliaIngestEdgeSchema = external_exports.object({
|
|
15877
15919
|
fromCanonicalId: external_exports.string().min(6).max(160),
|
|
15878
15920
|
toCanonicalId: external_exports.string().min(6).max(160),
|
|
@@ -15892,7 +15934,17 @@ var init_wire = __esm({
|
|
|
15892
15934
|
* classify the anchor current / pre-change; absent ⇒ the pre-versioning
|
|
15893
15935
|
* contract, unverified. Only meaningful on `ANCHORED_AT`. */
|
|
15894
15936
|
observedAtCommit: external_exports.string().regex(ANCHOR_COMMIT_SHA_RE).optional(),
|
|
15895
|
-
symbolContentHash: external_exports.string().regex(ANCHOR_BODY_HASH_RE).optional()
|
|
15937
|
+
symbolContentHash: external_exports.string().regex(ANCHOR_BODY_HASH_RE).optional(),
|
|
15938
|
+
/** PJ-anchor-labels: the READABLE identity of the anchor's target —
|
|
15939
|
+
* repo-relative path, qualified name (absent for a File), kind and line.
|
|
15940
|
+
* Sent only for a project whose owner opted in; the door strips them again
|
|
15941
|
+
* for any project that has not (the daemon's flag is not trusted alone).
|
|
15942
|
+
* Prefixed `label*` so no local edge attr (`anchorLine` lives there
|
|
15943
|
+
* natively) can ride out under a shared key. */
|
|
15944
|
+
labelRelPath: external_exports.string().regex(ANCHOR_LABEL_PATH_RE).optional(),
|
|
15945
|
+
labelQname: external_exports.string().regex(ANCHOR_LABEL_QNAME_RE).optional(),
|
|
15946
|
+
labelKind: external_exports.enum(ANCHOR_LABEL_KINDS).optional(),
|
|
15947
|
+
labelLine: external_exports.number().int().min(1).max(1e7).optional()
|
|
15896
15948
|
}).optional()
|
|
15897
15949
|
});
|
|
15898
15950
|
SymbolSummarySidecarSchema = external_exports.record(
|
|
@@ -16716,7 +16768,12 @@ __export(src_exports, {
|
|
|
16716
16768
|
AMBIGUOUS_ALIASES: () => AMBIGUOUS_ALIASES,
|
|
16717
16769
|
ANCHOR_BODY_HASH_RE: () => ANCHOR_BODY_HASH_RE,
|
|
16718
16770
|
ANCHOR_COMMIT_SHA_RE: () => ANCHOR_COMMIT_SHA_RE,
|
|
16771
|
+
ANCHOR_LABEL_KEYS: () => ANCHOR_LABEL_KEYS,
|
|
16772
|
+
ANCHOR_LABEL_KINDS: () => ANCHOR_LABEL_KINDS,
|
|
16773
|
+
ANCHOR_LABEL_PATH_RE: () => ANCHOR_LABEL_PATH_RE,
|
|
16774
|
+
ANCHOR_LABEL_QNAME_RE: () => ANCHOR_LABEL_QNAME_RE,
|
|
16719
16775
|
ANCHOR_REFUSAL_REASONS: () => ANCHOR_REFUSAL_REASONS,
|
|
16776
|
+
ANCHOR_SYMBOL_KINDS: () => ANCHOR_SYMBOL_KINDS,
|
|
16720
16777
|
BELIEF_EDGES: () => BELIEF_EDGES,
|
|
16721
16778
|
BRIDGE_EDGES: () => BRIDGE_EDGES,
|
|
16722
16779
|
CAUSAL_EDGES: () => CAUSAL_EDGES,
|
|
@@ -16739,6 +16796,7 @@ __export(src_exports, {
|
|
|
16739
16796
|
EDGE_RULES: () => EDGE_RULES,
|
|
16740
16797
|
EDGE_WEIGHT: () => EDGE_WEIGHT,
|
|
16741
16798
|
EVIDENCE_EDGES: () => EVIDENCE_EDGES,
|
|
16799
|
+
FILE_ANCHOR_QNAME: () => FILE_ANCHOR_QNAME,
|
|
16742
16800
|
GIT_EDGES: () => GIT_EDGES,
|
|
16743
16801
|
GRAPH_EVENT_VOCABULARIES: () => GRAPH_EVENT_VOCABULARIES,
|
|
16744
16802
|
IDENTITY_EDGES: () => IDENTITY_EDGES,
|
|
@@ -16775,6 +16833,7 @@ __export(src_exports, {
|
|
|
16775
16833
|
VALIDATION_SOURCES: () => VALIDATION_SOURCES,
|
|
16776
16834
|
aliasesLongestFirst: () => aliasesLongestFirst,
|
|
16777
16835
|
allEntities: () => allEntities,
|
|
16836
|
+
anchorLabelAttrs: () => anchorLabelAttrs,
|
|
16778
16837
|
anchorVersionAttrs: () => anchorVersionAttrs,
|
|
16779
16838
|
assertGraphEventVocabulary: () => assertGraphEventVocabulary,
|
|
16780
16839
|
buildSpine: () => buildSpine,
|
|
@@ -16796,6 +16855,7 @@ __export(src_exports, {
|
|
|
16796
16855
|
extractIdentifierTokens: () => extractIdentifierTokens,
|
|
16797
16856
|
genericCanonicalId: () => genericCanonicalId,
|
|
16798
16857
|
identityId: () => identityId,
|
|
16858
|
+
isAnchorLabelKind: () => isAnchorLabelKind,
|
|
16799
16859
|
isCausalProtected: () => isCausalProtected,
|
|
16800
16860
|
isCloudWritableNodeLabel: () => isCloudWritableNodeLabel,
|
|
16801
16861
|
isCodeLabel: () => isCodeLabel,
|
|
@@ -16844,6 +16904,7 @@ __export(src_exports, {
|
|
|
16844
16904
|
sidecarDropBucket: () => sidecarDropBucket,
|
|
16845
16905
|
spineDeps: () => spineDeps,
|
|
16846
16906
|
splitPnpmKey: () => splitPnpmKey,
|
|
16907
|
+
stripAnchorLabels: () => stripAnchorLabels,
|
|
16847
16908
|
substituteSymbolSummaries: () => substituteSymbolSummaries,
|
|
16848
16909
|
summarizeIngestResult: () => summarizeIngestResult,
|
|
16849
16910
|
summaryRejectionReason: () => summaryRejectionReason,
|
|
@@ -24956,7 +25017,10 @@ function toWirePayload(batch, runId) {
|
|
|
24956
25017
|
...typeof e.confidence === "number" ? { confidence: clamp012(e.confidence) } : {},
|
|
24957
25018
|
...perContext ? { perContext } : {},
|
|
24958
25019
|
// PJ-anchor-version: the two opaque version stamps ride on anchors only.
|
|
24959
|
-
...e.type === "ANCHORED_AT" ? anchorVersionAttrs(e.attrs) : {}
|
|
25020
|
+
...e.type === "ANCHORED_AT" ? anchorVersionAttrs(e.attrs) : {},
|
|
25021
|
+
// PJ-anchor-labels: readable labels ride only when the producer set the
|
|
25022
|
+
// `label*` keys, which the daemon does only for an opted-in project.
|
|
25023
|
+
...e.type === "ANCHORED_AT" ? anchorLabelAttrs(e.attrs) : {}
|
|
24960
25024
|
}
|
|
24961
25025
|
};
|
|
24962
25026
|
});
|
|
@@ -28768,7 +28832,7 @@ function buildAgentInstruction(opts = {}) {
|
|
|
28768
28832
|
tail
|
|
28769
28833
|
].join("\n");
|
|
28770
28834
|
}
|
|
28771
|
-
var TAG_EXAMPLE, GLOSS;
|
|
28835
|
+
var TAG_EXAMPLE, TAG_OPENERS, GLOSS;
|
|
28772
28836
|
var init_agent_signals = __esm({
|
|
28773
28837
|
"src/agent-signals.ts"() {
|
|
28774
28838
|
"use strict";
|
|
@@ -28824,6 +28888,11 @@ var init_agent_signals = __esm({
|
|
|
28824
28888
|
confirm: (ref) => `(confirm:[${ref}])`,
|
|
28825
28889
|
refute: (ref) => `(refute:[${ref}] one line why)`
|
|
28826
28890
|
};
|
|
28891
|
+
TAG_OPENERS = [
|
|
28892
|
+
...new Set(
|
|
28893
|
+
Object.values(TAG_EXAMPLE).map((example) => /^(\([a-z][\w-]*:|\[[!?])/i.exec(example("x"))?.[1]?.toLowerCase()).filter((opener) => opener !== void 0)
|
|
28894
|
+
)
|
|
28895
|
+
];
|
|
28827
28896
|
GLOSS = {
|
|
28828
28897
|
prior: "a shown prior helped, or you work in a primed language/package",
|
|
28829
28898
|
problem: "a problem you notice or report \u2014 any bug, finding, or thing wrong; about specific code? name the file: [!what's wrong @ src/file.ts:42]",
|
|
@@ -51034,15 +51103,14 @@ function recallForTool(store, command, ctx) {
|
|
|
51034
51103
|
${lines.join("\n")}`;
|
|
51035
51104
|
}
|
|
51036
51105
|
function decideContextInject(args2) {
|
|
51037
|
-
const { event,
|
|
51106
|
+
const { event, sessionId, block, lastInjectedHash } = args2;
|
|
51038
51107
|
if (!block) return null;
|
|
51039
51108
|
if (event === "SessionStart") {
|
|
51040
|
-
lastInjectedHash.set(sessionId, block.hash);
|
|
51041
|
-
|
|
51042
|
-
} else if (lastInjectedHash.get(sessionId) === block.hash) {
|
|
51109
|
+
if (sessionId) lastInjectedHash.set(sessionId, block.hash);
|
|
51110
|
+
} else if (sessionId && lastInjectedHash.get(sessionId) === block.hash) {
|
|
51043
51111
|
return null;
|
|
51044
51112
|
} else {
|
|
51045
|
-
lastInjectedHash.set(sessionId, block.hash);
|
|
51113
|
+
if (sessionId) lastInjectedHash.set(sessionId, block.hash);
|
|
51046
51114
|
}
|
|
51047
51115
|
const additionalContext = "The errata daemon has updated your live workspace context. The block below REPLACES any earlier errata context block in this conversation \u2014 treat it as the current source of truth:\n\n" + block.body;
|
|
51048
51116
|
return { hookEventName: event, additionalContext };
|
|
@@ -70832,8 +70900,8 @@ var init_report_render = __esm({
|
|
|
70832
70900
|
|
|
70833
70901
|
// src/cli.ts
|
|
70834
70902
|
init_src6();
|
|
70835
|
-
import { closeSync as closeSync2, existsSync as
|
|
70836
|
-
import { join as
|
|
70903
|
+
import { closeSync as closeSync2, existsSync as existsSync34, openSync as openSync2, readFileSync as readFileSync33, renameSync as renameSync4, statSync as statSync8 } from "node:fs";
|
|
70904
|
+
import { join as join38, resolve as pathResolve2 } from "node:path";
|
|
70837
70905
|
import { spawn as spawn3 } from "node:child_process";
|
|
70838
70906
|
|
|
70839
70907
|
// src/daemon.ts
|
|
@@ -74082,15 +74150,54 @@ function clauseBefore(sentence, idx) {
|
|
|
74082
74150
|
}
|
|
74083
74151
|
var FIX_RATIONALE_MIN = 12;
|
|
74084
74152
|
var FIX_RATIONALE_WINDOW = 160;
|
|
74153
|
+
var SIBLING_MARKUP_SOURCES = [
|
|
74154
|
+
CITE_GROUP_RE,
|
|
74155
|
+
FLAG_RE,
|
|
74156
|
+
FIX_LONG_RE,
|
|
74157
|
+
CAUSE_LONG_RE,
|
|
74158
|
+
CONFIRM_LONG_RE,
|
|
74159
|
+
REFUTE_LONG_RE,
|
|
74160
|
+
ATTEMPT_RE,
|
|
74161
|
+
CONSTRAINT_RE
|
|
74162
|
+
].map((re) => ({ source: re.source, flags: re.flags.includes("g") ? re.flags : `${re.flags}g` }));
|
|
74163
|
+
function maskSiblingMarkup(sentence, tagStart, tagEnd) {
|
|
74164
|
+
let masked = sentence;
|
|
74165
|
+
for (const { source, flags: flags2 } of SIBLING_MARKUP_SOURCES) {
|
|
74166
|
+
masked = masked.replace(new RegExp(source, flags2), (m, ...rest2) => {
|
|
74167
|
+
const at = rest2.find((v) => typeof v === "number");
|
|
74168
|
+
if (at <= tagStart && at + m.length >= tagEnd) return m;
|
|
74169
|
+
return " ".repeat(m.length);
|
|
74170
|
+
});
|
|
74171
|
+
}
|
|
74172
|
+
return masked;
|
|
74173
|
+
}
|
|
74174
|
+
var RESIDUAL_OPENER_RE = new RegExp(
|
|
74175
|
+
TAG_OPENERS.map((o) => o.startsWith("(") ? String.raw`\(\s*${o.slice(1, -1)}\s*:` : o.replace(/[[\]!?]/g, "\\$&")).join("|"),
|
|
74176
|
+
"i"
|
|
74177
|
+
);
|
|
74085
74178
|
function fixRationaleBefore(sentence, idx) {
|
|
74086
|
-
const
|
|
74179
|
+
const masked = maskSiblingMarkup(sentence, idx, idx + 1);
|
|
74180
|
+
let start2 = Math.max(0, idx - FIX_RATIONALE_WINDOW);
|
|
74181
|
+
if (start2 > 0 && /\S/.test(masked[start2 - 1]) && /\S/.test(masked[start2])) {
|
|
74182
|
+
const ws = masked.slice(start2, idx).search(/\s/);
|
|
74183
|
+
start2 = ws < 0 ? idx : start2 + ws;
|
|
74184
|
+
}
|
|
74185
|
+
const win = masked.slice(start2, idx);
|
|
74087
74186
|
const m = /[.;!?—][^.;!?—]*$/.exec(win);
|
|
74088
74187
|
const clause = m ? win.slice(m.index + 1) : win;
|
|
74089
74188
|
return clause.replace(/\s+/g, " ").trim();
|
|
74090
74189
|
}
|
|
74091
74190
|
function fixRationaleAfter(sentence, endIdx) {
|
|
74092
|
-
|
|
74093
|
-
|
|
74191
|
+
if (/^\s*[)\]}]/.test(sentence.slice(endIdx))) return "";
|
|
74192
|
+
const masked = maskSiblingMarkup(sentence, endIdx - 1, endIdx);
|
|
74193
|
+
let end = Math.min(masked.length, endIdx + FIX_RATIONALE_WINDOW);
|
|
74194
|
+
if (end < masked.length && /\S/.test(masked[end - 1]) && /\S/.test(masked[end])) {
|
|
74195
|
+
const lastWs = masked.slice(endIdx, end).search(/\s\S*$/);
|
|
74196
|
+
end = lastWs < 0 ? endIdx : endIdx + lastWs;
|
|
74197
|
+
}
|
|
74198
|
+
let win = masked.slice(endIdx, end);
|
|
74199
|
+
const residual = RESIDUAL_OPENER_RE.exec(win);
|
|
74200
|
+
if (residual) win = win.slice(0, residual.index);
|
|
74094
74201
|
const stripped = win.replace(/^[\s—:–,-]+/, "");
|
|
74095
74202
|
const m = /^[^.;!?—]*/.exec(stripped);
|
|
74096
74203
|
const clause = (m ? m[0] : stripped).replace(/\s+/g, " ").trim();
|
|
@@ -74102,6 +74209,78 @@ function deriveFixRationale(sentence, startIdx, endIdx) {
|
|
|
74102
74209
|
if (before.length >= FIX_RATIONALE_MIN) return before;
|
|
74103
74210
|
return fixRationaleAfter(sentence, endIdx);
|
|
74104
74211
|
}
|
|
74212
|
+
var LEADING_OPENER_RE = new RegExp(String.raw`^(?:${RESIDUAL_OPENER_RE.source})(?:#[a-z][\w-]{0,63})?\s*`, "i");
|
|
74213
|
+
var WRAPPER_PAIRS = [["(", ")"], ["[", "]"]];
|
|
74214
|
+
var LEADING_HANDLES_RE = /^(?:\[[a-z0-9][\w-]{0,80}\]\s*,?\s*)+/i;
|
|
74215
|
+
function leadingBracketClose(t) {
|
|
74216
|
+
const pair = WRAPPER_PAIRS.find(([open2]) => t.startsWith(open2));
|
|
74217
|
+
if (!pair) return null;
|
|
74218
|
+
let depth = 0;
|
|
74219
|
+
for (let i2 = 0; i2 < t.length; i2++) {
|
|
74220
|
+
if (t[i2] === pair[0]) depth++;
|
|
74221
|
+
else if (t[i2] === pair[1] && --depth === 0) return i2;
|
|
74222
|
+
}
|
|
74223
|
+
return -1;
|
|
74224
|
+
}
|
|
74225
|
+
function trailingBracketStray(t) {
|
|
74226
|
+
const pair = WRAPPER_PAIRS.find(([, close]) => t.endsWith(close));
|
|
74227
|
+
if (!pair) return false;
|
|
74228
|
+
let depth = 0;
|
|
74229
|
+
for (const ch of t.slice(0, -1)) {
|
|
74230
|
+
if (ch === pair[0]) depth++;
|
|
74231
|
+
else if (ch === pair[1] && depth > 0) depth--;
|
|
74232
|
+
}
|
|
74233
|
+
return depth === 0;
|
|
74234
|
+
}
|
|
74235
|
+
function cleanTagText(text) {
|
|
74236
|
+
let t = text.replace(/\s+/g, " ").trim();
|
|
74237
|
+
for (let pass = 0; pass < 8; pass++) {
|
|
74238
|
+
const before = t;
|
|
74239
|
+
const close = leadingBracketClose(t);
|
|
74240
|
+
const opener = close === null ? null : LEADING_OPENER_RE.exec(t);
|
|
74241
|
+
if (close === -1) {
|
|
74242
|
+
t = t.slice(opener ? opener[0].length : 1).trim();
|
|
74243
|
+
} else if (opener && close === t.length - 1) {
|
|
74244
|
+
t = t.slice(opener[0].length, -1).trim();
|
|
74245
|
+
}
|
|
74246
|
+
if (opener && t !== before) t = t.replace(LEADING_HANDLES_RE, "").trim();
|
|
74247
|
+
if (trailingBracketStray(t)) t = t.slice(0, -1).trim();
|
|
74248
|
+
if (t === before) break;
|
|
74249
|
+
}
|
|
74250
|
+
return t;
|
|
74251
|
+
}
|
|
74252
|
+
var TAG_TEXT_FIELDS = [
|
|
74253
|
+
"fixRationale",
|
|
74254
|
+
"statement",
|
|
74255
|
+
"causeText",
|
|
74256
|
+
"causeOf",
|
|
74257
|
+
"patternText",
|
|
74258
|
+
"domainText",
|
|
74259
|
+
"packageText",
|
|
74260
|
+
"componentText"
|
|
74261
|
+
];
|
|
74262
|
+
function cleanEmittedTags(tags) {
|
|
74263
|
+
const kept = [];
|
|
74264
|
+
for (const tag of tags) {
|
|
74265
|
+
let emptied = false;
|
|
74266
|
+
for (const field of TAG_TEXT_FIELDS) {
|
|
74267
|
+
const value = tag[field];
|
|
74268
|
+
if (value === void 0) continue;
|
|
74269
|
+
const cleaned = cleanTagText(value);
|
|
74270
|
+
if (field === "fixRationale" && cleaned.length < FIX_RATIONALE_MIN) {
|
|
74271
|
+
delete tag.fixRationale;
|
|
74272
|
+
continue;
|
|
74273
|
+
}
|
|
74274
|
+
if (cleaned.length === 0) emptied = true;
|
|
74275
|
+
tag[field] = cleaned;
|
|
74276
|
+
}
|
|
74277
|
+
const hasReference = tag.handle !== void 0 || (tag.handles?.length ?? 0) > 0 || (tag.refuteHandles?.length ?? 0) > 0;
|
|
74278
|
+
if (emptied && !hasReference) continue;
|
|
74279
|
+
if (tag.kind === "fix" && !hasReference && tag.fixRationale === void 0) continue;
|
|
74280
|
+
kept.push(tag);
|
|
74281
|
+
}
|
|
74282
|
+
return kept;
|
|
74283
|
+
}
|
|
74105
74284
|
function emptyTagDispositions() {
|
|
74106
74285
|
return {
|
|
74107
74286
|
oversizeSegments: 0,
|
|
@@ -74469,7 +74648,7 @@ function parseInlineTagsWithDispositions(text) {
|
|
|
74469
74648
|
}
|
|
74470
74649
|
for (let i2 = seqStart; i2 < out2.length; i2++) out2[i2].seq = seqNo;
|
|
74471
74650
|
}
|
|
74472
|
-
return { tags: out2, dispositions };
|
|
74651
|
+
return { tags: cleanEmittedTags(out2), dispositions };
|
|
74473
74652
|
}
|
|
74474
74653
|
var LABEL_PAIR = {
|
|
74475
74654
|
"Problem>RootCause": "CAUSED_BY",
|
|
@@ -78143,7 +78322,7 @@ function createWatchBreaker(deps) {
|
|
|
78143
78322
|
}
|
|
78144
78323
|
|
|
78145
78324
|
// src/engine.ts
|
|
78146
|
-
var DAEMON_VERSION = true ? "2.0.6-dev.
|
|
78325
|
+
var DAEMON_VERSION = true ? "2.0.6-dev.2550" : "2.0.0-alpha.0";
|
|
78147
78326
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
78148
78327
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
78149
78328
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -81172,19 +81351,39 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
81172
81351
|
for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
|
|
81173
81352
|
const target = store.getNode(e.to);
|
|
81174
81353
|
if (!target) continue;
|
|
81354
|
+
if (!isAnchorLabelKind(target.label)) continue;
|
|
81355
|
+
const isFile = target.label === "File";
|
|
81356
|
+
if (isFile && !project.anchorLabels) continue;
|
|
81175
81357
|
const relPath = target.attrs["relPath"];
|
|
81176
|
-
const qname = target.attrs["qname"];
|
|
81358
|
+
const qname = isFile ? FILE_ANCHOR_QNAME : target.attrs["qname"];
|
|
81177
81359
|
if (typeof relPath !== "string" || typeof qname !== "string") continue;
|
|
81178
|
-
if (ignored(relPath) || ignored(qname)) continue;
|
|
81179
|
-
|
|
81360
|
+
if (ignored(relPath) || qname !== "" && ignored(qname)) continue;
|
|
81361
|
+
const line = e.attrs?.["anchorLine"];
|
|
81362
|
+
const wireAttrs = {
|
|
81363
|
+
...anchorVersionAttrs(e.attrs),
|
|
81364
|
+
// PJ-anchor-labels: only for an opted-in project, and only through the
|
|
81365
|
+
// shared projection (invalid path/kind ⇒ no label, never half of one).
|
|
81366
|
+
...project.anchorLabels ? anchorLabelAttrs({
|
|
81367
|
+
labelRelPath: normalizeSymbolPath(relPath),
|
|
81368
|
+
labelKind: target.label,
|
|
81369
|
+
...isFile ? {} : { labelQname: qname },
|
|
81370
|
+
...typeof line === "number" ? { labelLine: line } : {}
|
|
81371
|
+
}) : {}
|
|
81372
|
+
};
|
|
81373
|
+
planned.push({
|
|
81374
|
+
e,
|
|
81375
|
+
target,
|
|
81376
|
+
symId: projectSymbolId(project.salt, project.projectId, relPath, qname, target.label),
|
|
81377
|
+
wireAttrs
|
|
81378
|
+
});
|
|
81180
81379
|
}
|
|
81181
81380
|
if (planned.length === 0) continue;
|
|
81182
81381
|
const dg = digest(
|
|
81183
|
-
planned.map(({
|
|
81382
|
+
planned.map(({ symId, wireAttrs }) => `ANCHORED_AT>${symId}>${JSON.stringify(wireAttrs)}`).sort()
|
|
81184
81383
|
);
|
|
81185
81384
|
if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
|
|
81186
81385
|
projectAnchorDigests[sourceId] = dg;
|
|
81187
|
-
for (const { e, target, symId } of planned) {
|
|
81386
|
+
for (const { e, target, symId, wireAttrs } of planned) {
|
|
81188
81387
|
if (!contextSeen.has(symId)) {
|
|
81189
81388
|
contextSeen.add(symId);
|
|
81190
81389
|
contextNodes.push({
|
|
@@ -81211,7 +81410,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
81211
81410
|
stability: "unstable"
|
|
81212
81411
|
});
|
|
81213
81412
|
}
|
|
81214
|
-
anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs:
|
|
81413
|
+
anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs: wireAttrs });
|
|
81215
81414
|
}
|
|
81216
81415
|
}
|
|
81217
81416
|
}
|
|
@@ -81715,7 +81914,7 @@ init_src11();
|
|
|
81715
81914
|
init_src();
|
|
81716
81915
|
init_src11();
|
|
81717
81916
|
var DEFAULT_LIMIT = 50;
|
|
81718
|
-
var
|
|
81917
|
+
var ANCHOR_SYMBOL_KINDS2 = [
|
|
81719
81918
|
"Function",
|
|
81720
81919
|
"Class",
|
|
81721
81920
|
"Method",
|
|
@@ -81736,7 +81935,7 @@ function classifyAnchorVersion(cloudAttrs, localSymbol) {
|
|
|
81736
81935
|
function buildReverseSymbolMap(opts) {
|
|
81737
81936
|
const { store, salt, projectId } = opts;
|
|
81738
81937
|
const reverse = /* @__PURE__ */ new Map();
|
|
81739
|
-
for (const kind of
|
|
81938
|
+
for (const kind of ANCHOR_SYMBOL_KINDS2) {
|
|
81740
81939
|
for (const n of store.findNodeIdentitiesByLabel(kind)) {
|
|
81741
81940
|
const { relPath, qname } = n;
|
|
81742
81941
|
if (relPath === null || qname === null) continue;
|
|
@@ -81746,6 +81945,13 @@ function buildReverseSymbolMap(opts) {
|
|
|
81746
81945
|
if (!reverse.has(twin)) reverse.set(twin, n.id);
|
|
81747
81946
|
}
|
|
81748
81947
|
}
|
|
81948
|
+
for (const n of store.findNodeIdentitiesByLabel("File")) {
|
|
81949
|
+
if (n.relPath === null) continue;
|
|
81950
|
+
const sym = projectSymbolId(salt, projectId, n.relPath, FILE_ANCHOR_QNAME, "File");
|
|
81951
|
+
if (!reverse.has(sym)) reverse.set(sym, n.id);
|
|
81952
|
+
const twin = projectSaltedNodeId(sym, salt);
|
|
81953
|
+
if (!reverse.has(twin)) reverse.set(twin, n.id);
|
|
81954
|
+
}
|
|
81749
81955
|
return reverse;
|
|
81750
81956
|
}
|
|
81751
81957
|
function anchorConfidence(attrs) {
|
|
@@ -84482,12 +84688,21 @@ function withLaunchOrigin(pending) {
|
|
|
84482
84688
|
return LOCAL_BUILD_ENTRY ? { ...pending, localBuildEntry: LOCAL_BUILD_ENTRY } : pending;
|
|
84483
84689
|
}
|
|
84484
84690
|
var projectSymbolSalts = /* @__PURE__ */ new Map();
|
|
84691
|
+
var PROJECT_SALT_REFRESH_MS = 10 * 6e4;
|
|
84485
84692
|
async function resolveProjectSymbolSalt(client, projectId) {
|
|
84486
84693
|
const cached2 = projectSymbolSalts.get(projectId);
|
|
84487
|
-
if (cached2)
|
|
84488
|
-
|
|
84489
|
-
|
|
84490
|
-
|
|
84694
|
+
if (cached2 && Date.now() - cached2.fetchedAt < PROJECT_SALT_REFRESH_MS) {
|
|
84695
|
+
return { projectId, salt: cached2.salt, anchorLabels: cached2.anchorLabels };
|
|
84696
|
+
}
|
|
84697
|
+
try {
|
|
84698
|
+
const res = await client.projectSymbolSalt(projectId);
|
|
84699
|
+
const entry = { salt: res.salt, anchorLabels: res.anchorLabels === true, fetchedAt: Date.now() };
|
|
84700
|
+
projectSymbolSalts.set(projectId, entry);
|
|
84701
|
+
return { projectId, salt: entry.salt, anchorLabels: entry.anchorLabels };
|
|
84702
|
+
} catch (err2) {
|
|
84703
|
+
if (cached2) return { projectId, salt: cached2.salt, anchorLabels: cached2.anchorLabels };
|
|
84704
|
+
throw err2;
|
|
84705
|
+
}
|
|
84491
84706
|
}
|
|
84492
84707
|
var WATERMARK_BATCH = 250;
|
|
84493
84708
|
async function stampBatched(items, stamp) {
|
|
@@ -86612,32 +86827,92 @@ function hookRelayCommand(port, path2) {
|
|
|
86612
86827
|
}
|
|
86613
86828
|
var CODEX_HOOKS_BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
86614
86829
|
var CODEX_HOOKS_END = `# <<< errata hooks`;
|
|
86615
|
-
function buildCodexHooksToml(port) {
|
|
86616
|
-
const
|
|
86617
|
-
const
|
|
86618
|
-
|
|
86619
|
-
[
|
|
86620
|
-
|
|
86621
|
-
|
|
86622
|
-
|
|
86623
|
-
|
|
86624
|
-
|
|
86625
|
-
|
|
86626
|
-
|
|
86627
|
-
[[hooks.
|
|
86628
|
-
|
|
86629
|
-
|
|
86630
|
-
|
|
86631
|
-
|
|
86632
|
-
|
|
86633
|
-
|
|
86634
|
-
|
|
86635
|
-
|
|
86636
|
-
|
|
86637
|
-
|
|
86638
|
-
|
|
86639
|
-
|
|
86830
|
+
function buildCodexHooksToml(port, options) {
|
|
86831
|
+
const platform = options.platform ?? process.platform;
|
|
86832
|
+
const quote = (value) => {
|
|
86833
|
+
if (platform === "win32") {
|
|
86834
|
+
if (/["%\r\n]/.test(value)) throw new Error("Unsupported character in Codex hook path");
|
|
86835
|
+
return '"' + value + '"';
|
|
86836
|
+
}
|
|
86837
|
+
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
86838
|
+
};
|
|
86839
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid hook port");
|
|
86840
|
+
const command = quote(options.nodePath) + " " + quote(options.relayPath) + " " + port;
|
|
86841
|
+
const handlers = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse"].map(
|
|
86842
|
+
(event) => "[[hooks." + event + "]]\n" + (event === "UserPromptSubmit" ? "" : 'matcher = ".*"\n') + "\n[[hooks." + event + '.hooks]]\ntype = "command"\ncommand = ' + JSON.stringify(command) + "\ntimeout = 10\nadditionalContextLimit = 5000\n"
|
|
86843
|
+
);
|
|
86844
|
+
return CODEX_HOOKS_BEGIN + "\n" + handlers.join("\n") + CODEX_HOOKS_END + "\n";
|
|
86845
|
+
}
|
|
86846
|
+
|
|
86847
|
+
// src/codex-hooks.ts
|
|
86848
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync32, writeFileSync as writeFileSync24 } from "node:fs";
|
|
86849
|
+
import { homedir as homedir7 } from "node:os";
|
|
86850
|
+
import { join as join37 } from "node:path";
|
|
86851
|
+
|
|
86852
|
+
// src/codex-hook-relay.ts
|
|
86853
|
+
var CODEX_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks codex
|
|
86854
|
+
import { readFileSync } from 'node:fs';
|
|
86855
|
+
|
|
86856
|
+
try {
|
|
86857
|
+
const payload = JSON.parse(readFileSync(0, 'utf8') || '{}');
|
|
86858
|
+
const port = Number(process.argv[2]);
|
|
86859
|
+
const event = payload.hook_event_name;
|
|
86860
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) process.exit(0);
|
|
86861
|
+
const contexts = [];
|
|
86862
|
+
const post = async (endpoint, relay = false) => {
|
|
86863
|
+
try {
|
|
86864
|
+
const response = await fetch('http://127.0.0.1:' + port + '/api/' + endpoint, {
|
|
86865
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
86866
|
+
body: JSON.stringify(payload), signal: AbortSignal.timeout(2000),
|
|
86867
|
+
});
|
|
86868
|
+
if (!response.ok || !relay) return;
|
|
86869
|
+
const result = await response.json();
|
|
86870
|
+
const context = result.hookSpecificOutput?.additionalContext;
|
|
86871
|
+
if (typeof context === 'string' && context.trim()) contexts.push(context);
|
|
86872
|
+
} catch { /* An unavailable daemon must never block the agent. */ }
|
|
86873
|
+
};
|
|
86874
|
+
if (event === 'PreToolUse' || event === 'PostToolUse') await post('hook', true);
|
|
86875
|
+
if (event === 'PostToolUse') await post('turn');
|
|
86876
|
+
if (['SessionStart', 'UserPromptSubmit', 'PostToolUse'].includes(event)) {
|
|
86877
|
+
// Run after capture, so changes already rendered by the daemon arrive now.
|
|
86878
|
+
// Background extraction finishing later arrives at the next tool boundary.
|
|
86879
|
+
await post('context-inject', true);
|
|
86880
|
+
}
|
|
86881
|
+
if (contexts.length) {
|
|
86882
|
+
process.stdout.write(JSON.stringify({ hookSpecificOutput: {
|
|
86883
|
+
hookEventName: event, additionalContext: contexts.join('\n\n'),
|
|
86884
|
+
} }));
|
|
86885
|
+
}
|
|
86886
|
+
} catch { /* Invalid input is also fail-open. */ }
|
|
86640
86887
|
`;
|
|
86888
|
+
|
|
86889
|
+
// src/codex-hooks.ts
|
|
86890
|
+
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join37(homedir7(), ".codex")) {
|
|
86891
|
+
return existsSync33(join37(root, ".codex")) || existsSync33(codexHome);
|
|
86892
|
+
}
|
|
86893
|
+
function replaceCodexHooks(existing, block) {
|
|
86894
|
+
const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
|
|
86895
|
+
const end = existing.indexOf(CODEX_HOOKS_END);
|
|
86896
|
+
if (begin >= 0 || end >= 0) {
|
|
86897
|
+
if (begin < 0 || end < begin || existing.indexOf(CODEX_HOOKS_BEGIN, begin + CODEX_HOOKS_BEGIN.length) >= 0) {
|
|
86898
|
+
throw new Error(
|
|
86899
|
+
"Incomplete or duplicate errata hooks markers in .codex/config.toml; repair them before reinstalling."
|
|
86900
|
+
);
|
|
86901
|
+
}
|
|
86902
|
+
return existing.slice(0, begin) + block.trimEnd() + existing.slice(end + CODEX_HOOKS_END.length);
|
|
86903
|
+
}
|
|
86904
|
+
return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
|
|
86905
|
+
}
|
|
86906
|
+
function writeCodexHooks(root, port, nodePath = process.execPath) {
|
|
86907
|
+
const dir = join37(root, ".codex");
|
|
86908
|
+
const file2 = join37(dir, "config.toml");
|
|
86909
|
+
const relay = join37(dir, "hooks", "errata-relay.mjs");
|
|
86910
|
+
const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
|
|
86911
|
+
const final = replaceCodexHooks(existsSync33(file2) ? readFileSync32(file2, "utf8") : "", block);
|
|
86912
|
+
mkdirSync9(join37(dir, "hooks"), { recursive: true });
|
|
86913
|
+
writeFileSync24(relay, CODEX_RELAY_SOURCE, "utf8");
|
|
86914
|
+
writeFileSync24(file2, final, "utf8");
|
|
86915
|
+
return file2;
|
|
86641
86916
|
}
|
|
86642
86917
|
|
|
86643
86918
|
// src/opencode-plugin.ts
|
|
@@ -86979,6 +87254,7 @@ Commands:
|
|
|
86979
87254
|
Flags: --project <id> adopt an existing project (fork\u2192upstream);
|
|
86980
87255
|
--remote <name> derive the locator from a non-origin remote;
|
|
86981
87256
|
--name <name> mint a locator-less project; no flags = re-resolve now
|
|
87257
|
+
--skip-hooks leave existing harness configuration unchanged
|
|
86982
87258
|
unlink Detach from the cloud project + disable ambient re-linking
|
|
86983
87259
|
use [<handle>] Set the sticky session active agent the daemon acts as.
|
|
86984
87260
|
No arg lists the agents you can act as + the current one;
|
|
@@ -87044,21 +87320,21 @@ async function cmdInit() {
|
|
|
87044
87320
|
if (!skipHooks) {
|
|
87045
87321
|
console.log("");
|
|
87046
87322
|
console.log("installing harness hooks...");
|
|
87047
|
-
const { existsSync:
|
|
87048
|
-
const { join:
|
|
87323
|
+
const { existsSync: existsSync35 } = await import("node:fs");
|
|
87324
|
+
const { join: join39 } = await import("node:path");
|
|
87049
87325
|
try {
|
|
87050
87326
|
await installClaudeHooks(port);
|
|
87051
87327
|
} catch (err2) {
|
|
87052
87328
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
87053
87329
|
}
|
|
87054
|
-
if (
|
|
87330
|
+
if (existsSync35(join39(ROOT, ".cursor"))) {
|
|
87055
87331
|
try {
|
|
87056
87332
|
await installCursorMcpConfig();
|
|
87057
87333
|
} catch (err2) {
|
|
87058
87334
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
87059
87335
|
}
|
|
87060
87336
|
}
|
|
87061
|
-
if (
|
|
87337
|
+
if (hasCodexConfig(ROOT)) {
|
|
87062
87338
|
try {
|
|
87063
87339
|
await installCodexHooks(port);
|
|
87064
87340
|
} catch (err2) {
|
|
@@ -87235,9 +87511,9 @@ async function cmdStatus() {
|
|
|
87235
87511
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
87236
87512
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
87237
87513
|
}
|
|
87238
|
-
console.log(` graph db: ${
|
|
87239
|
-
console.log(` event log: ${
|
|
87240
|
-
if (
|
|
87514
|
+
console.log(` graph db: ${existsSync34(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
87515
|
+
console.log(` event log: ${existsSync34(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
87516
|
+
if (existsSync34(paths.castalia)) {
|
|
87241
87517
|
try {
|
|
87242
87518
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
87243
87519
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -87872,6 +88148,7 @@ async function cmdLink(args2) {
|
|
|
87872
88148
|
console.log(
|
|
87873
88149
|
`consents: sync=${d.consents.sync} telemetry=${d.consents.telemetry ? "on" : "off"} packages=${applied.config.consent.contributePackages ? "on" : "off"} structure=${d.consents.structure ? "on" : "off"} history=${d.consents.mineHistory ? applied.profile.linkConsents?.contributeHistory ? "mine+contribute" : "mine" : "off"}`
|
|
87874
88150
|
);
|
|
88151
|
+
await refreshLinkedCodexHooks(args2);
|
|
87875
88152
|
if (applied.wroteIgnore) console.log("wrote .errataignore (starter) \u2014 edit it; it is your hard control");
|
|
87876
88153
|
if (!hasCloudCredential(cfg)) {
|
|
87877
88154
|
console.log(" note: run `errata login` so this daemon can sync under the link and report the history stage.");
|
|
@@ -87912,6 +88189,7 @@ async function cmdLink(args2) {
|
|
|
87912
88189
|
profile.projectId = res.project.id;
|
|
87913
88190
|
profile.projectLocator = profile.repoLocator;
|
|
87914
88191
|
saveProfile(ROOT, profile);
|
|
88192
|
+
await refreshLinkedCodexHooks(args2);
|
|
87915
88193
|
console.log(`linked (adopted): ${profile.repoLocator} \u2192 project ${res.project.id} (${res.project.name})`);
|
|
87916
88194
|
return;
|
|
87917
88195
|
}
|
|
@@ -87921,6 +88199,7 @@ async function cmdLink(args2) {
|
|
|
87921
88199
|
profile.projectId = res.project.id;
|
|
87922
88200
|
delete profile.projectLocator;
|
|
87923
88201
|
saveProfile(ROOT, profile);
|
|
88202
|
+
await refreshLinkedCodexHooks(args2);
|
|
87924
88203
|
console.log(`linked (locator-less): project ${res.project.id} (${res.project.name})`);
|
|
87925
88204
|
return;
|
|
87926
88205
|
}
|
|
@@ -87929,6 +88208,7 @@ async function cmdLink(args2) {
|
|
|
87929
88208
|
delete profile.projectLocator;
|
|
87930
88209
|
const out2 = await ensureProjectLink(ROOT, profile, client);
|
|
87931
88210
|
if (out2.linked) {
|
|
88211
|
+
await refreshLinkedCodexHooks(args2);
|
|
87932
88212
|
console.log(`linked: ${profile.repoLocator} \u2192 project ${out2.projectId}${out2.created ? " (created)" : ""}`);
|
|
87933
88213
|
} else {
|
|
87934
88214
|
console.error(`link failed (${out2.reason})${out2.detail ? `: ${out2.detail}` : ""}`);
|
|
@@ -88135,11 +88415,11 @@ function cmdInstallationProfile(args2) {
|
|
|
88135
88415
|
}
|
|
88136
88416
|
async function cmdReview() {
|
|
88137
88417
|
const paths = workspacePaths(ROOT);
|
|
88138
|
-
if (!
|
|
88418
|
+
if (!existsSync34(paths.reviewQueue)) {
|
|
88139
88419
|
console.log("(review queue empty)");
|
|
88140
88420
|
return;
|
|
88141
88421
|
}
|
|
88142
|
-
const queue = JSON.parse(
|
|
88422
|
+
const queue = JSON.parse(readFileSync33(paths.reviewQueue, "utf8"));
|
|
88143
88423
|
if (queue.length === 0) {
|
|
88144
88424
|
console.log("(review queue empty)");
|
|
88145
88425
|
return;
|
|
@@ -88810,7 +89090,7 @@ async function gatherRepo(store, ws) {
|
|
|
88810
89090
|
};
|
|
88811
89091
|
}
|
|
88812
89092
|
async function gatherReportData(generatedAt) {
|
|
88813
|
-
const { existsSync:
|
|
89093
|
+
const { existsSync: existsSync35 } = await import("node:fs");
|
|
88814
89094
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
88815
89095
|
const cfg = loadConfig();
|
|
88816
89096
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -88818,7 +89098,7 @@ async function gatherReportData(generatedAt) {
|
|
|
88818
89098
|
for (const ws of listWorkspaces()) {
|
|
88819
89099
|
if (ws.missing) continue;
|
|
88820
89100
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
88821
|
-
if (!
|
|
89101
|
+
if (!existsSync35(dbPath)) continue;
|
|
88822
89102
|
let store = null;
|
|
88823
89103
|
try {
|
|
88824
89104
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -88849,7 +89129,7 @@ async function gatherReportData(generatedAt) {
|
|
|
88849
89129
|
};
|
|
88850
89130
|
}
|
|
88851
89131
|
async function cmdReport(args2) {
|
|
88852
|
-
const { mkdirSync:
|
|
89132
|
+
const { mkdirSync: mkdirSync10, writeFileSync: writeFileSync25 } = await import("node:fs");
|
|
88853
89133
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
88854
89134
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
88855
89135
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -88860,10 +89140,10 @@ async function cmdReport(args2) {
|
|
|
88860
89140
|
process.exit(2);
|
|
88861
89141
|
}
|
|
88862
89142
|
const outDir = workspacePaths(ROOT).configDir;
|
|
88863
|
-
|
|
89143
|
+
mkdirSync10(outDir, { recursive: true });
|
|
88864
89144
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
88865
|
-
for (const f of files)
|
|
88866
|
-
const indexPath =
|
|
89145
|
+
for (const f of files) writeFileSync25(join38(outDir, f.name), f.html, "utf8");
|
|
89146
|
+
const indexPath = join38(outDir, "report.html");
|
|
88867
89147
|
console.log(`report \u2192 ${indexPath}`);
|
|
88868
89148
|
console.log(
|
|
88869
89149
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -88983,24 +89263,24 @@ async function cmdInstallHooks(args2) {
|
|
|
88983
89263
|
}
|
|
88984
89264
|
}
|
|
88985
89265
|
async function installOpencodePlugin(port) {
|
|
88986
|
-
const { mkdirSync:
|
|
88987
|
-
const { join:
|
|
88988
|
-
const dir =
|
|
88989
|
-
if (!
|
|
88990
|
-
const file2 =
|
|
88991
|
-
if (
|
|
88992
|
-
const head2 =
|
|
89266
|
+
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
|
|
89267
|
+
const { join: join39 } = await import("node:path");
|
|
89268
|
+
const dir = join39(ROOT, ".opencode", "plugin");
|
|
89269
|
+
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
89270
|
+
const file2 = join39(dir, "inerrata.js");
|
|
89271
|
+
if (existsSync35(file2)) {
|
|
89272
|
+
const head2 = readFileSync34(file2, "utf8").split("\n")[0] ?? "";
|
|
88993
89273
|
if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
|
|
88994
89274
|
console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
|
|
88995
89275
|
process.exit(2);
|
|
88996
89276
|
}
|
|
88997
89277
|
}
|
|
88998
|
-
|
|
88999
|
-
const cfgFile =
|
|
89278
|
+
writeFileSync25(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
|
|
89279
|
+
const cfgFile = join39(ROOT, "opencode.json");
|
|
89000
89280
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
89001
|
-
if (
|
|
89281
|
+
if (existsSync35(cfgFile)) {
|
|
89002
89282
|
try {
|
|
89003
|
-
cfg = JSON.parse(
|
|
89283
|
+
cfg = JSON.parse(readFileSync34(cfgFile, "utf8"));
|
|
89004
89284
|
} catch {
|
|
89005
89285
|
console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
|
|
89006
89286
|
process.exit(2);
|
|
@@ -89011,7 +89291,7 @@ async function installOpencodePlugin(port) {
|
|
|
89011
89291
|
if (!hadErrata) {
|
|
89012
89292
|
const inv = errataMcpInvocation();
|
|
89013
89293
|
cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
|
|
89014
|
-
|
|
89294
|
+
writeFileSync25(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
89015
89295
|
}
|
|
89016
89296
|
console.log(`installed OpenCode plugin \u2192 ${file2}`);
|
|
89017
89297
|
if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
|
|
@@ -89031,15 +89311,15 @@ function errataMcpInvocation() {
|
|
|
89031
89311
|
return { command: cmd2, args: args2 };
|
|
89032
89312
|
}
|
|
89033
89313
|
async function installClaudeHooks(port) {
|
|
89034
|
-
const { mkdirSync:
|
|
89035
|
-
const { join:
|
|
89036
|
-
const dir =
|
|
89037
|
-
if (!
|
|
89038
|
-
const file2 =
|
|
89314
|
+
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
|
|
89315
|
+
const { join: join39 } = await import("node:path");
|
|
89316
|
+
const dir = join39(ROOT, ".claude");
|
|
89317
|
+
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
89318
|
+
const file2 = join39(dir, "settings.json");
|
|
89039
89319
|
let settings = {};
|
|
89040
|
-
if (
|
|
89320
|
+
if (existsSync35(file2)) {
|
|
89041
89321
|
try {
|
|
89042
|
-
settings = JSON.parse(
|
|
89322
|
+
settings = JSON.parse(readFileSync34(file2, "utf8"));
|
|
89043
89323
|
} catch {
|
|
89044
89324
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
89045
89325
|
process.exit(2);
|
|
@@ -89085,10 +89365,10 @@ async function installClaudeHooks(port) {
|
|
|
89085
89365
|
dropErrata(list);
|
|
89086
89366
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
89087
89367
|
}
|
|
89088
|
-
|
|
89368
|
+
writeFileSync25(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
89089
89369
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
89090
89370
|
await installClaudeMcpConfig();
|
|
89091
|
-
const claudeMd =
|
|
89371
|
+
const claudeMd = join39(ROOT, "CLAUDE.md");
|
|
89092
89372
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
89093
89373
|
if (recall.kind === "collision") {
|
|
89094
89374
|
console.warn(
|
|
@@ -89100,15 +89380,15 @@ async function installClaudeHooks(port) {
|
|
|
89100
89380
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
89101
89381
|
}
|
|
89102
89382
|
async function installClaudeMcpConfig() {
|
|
89103
|
-
const { mkdirSync:
|
|
89104
|
-
const { join:
|
|
89105
|
-
const file2 =
|
|
89383
|
+
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
|
|
89384
|
+
const { join: join39, dirname: dirname13 } = await import("node:path");
|
|
89385
|
+
const file2 = join39(ROOT, ".mcp.json");
|
|
89106
89386
|
const dir = dirname13(file2);
|
|
89107
|
-
if (!
|
|
89387
|
+
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
89108
89388
|
let cfg = {};
|
|
89109
|
-
if (
|
|
89389
|
+
if (existsSync35(file2)) {
|
|
89110
89390
|
try {
|
|
89111
|
-
cfg = JSON.parse(
|
|
89391
|
+
cfg = JSON.parse(readFileSync34(file2, "utf8"));
|
|
89112
89392
|
} catch {
|
|
89113
89393
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
89114
89394
|
process.exit(2);
|
|
@@ -89116,21 +89396,21 @@ async function installClaudeMcpConfig() {
|
|
|
89116
89396
|
}
|
|
89117
89397
|
cfg.mcpServers ??= {};
|
|
89118
89398
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
89119
|
-
|
|
89399
|
+
writeFileSync25(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
89120
89400
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
89121
89401
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
89122
89402
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
89123
89403
|
}
|
|
89124
89404
|
async function installCursorMcpConfig() {
|
|
89125
|
-
const { mkdirSync:
|
|
89126
|
-
const { join:
|
|
89127
|
-
const dir =
|
|
89128
|
-
if (!
|
|
89129
|
-
const file2 =
|
|
89405
|
+
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
|
|
89406
|
+
const { join: join39 } = await import("node:path");
|
|
89407
|
+
const dir = join39(ROOT, ".cursor");
|
|
89408
|
+
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
89409
|
+
const file2 = join39(dir, "mcp.json");
|
|
89130
89410
|
let cfg = {};
|
|
89131
|
-
if (
|
|
89411
|
+
if (existsSync35(file2)) {
|
|
89132
89412
|
try {
|
|
89133
|
-
cfg = JSON.parse(
|
|
89413
|
+
cfg = JSON.parse(readFileSync34(file2, "utf8"));
|
|
89134
89414
|
} catch {
|
|
89135
89415
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
89136
89416
|
process.exit(2);
|
|
@@ -89138,7 +89418,7 @@ async function installCursorMcpConfig() {
|
|
|
89138
89418
|
}
|
|
89139
89419
|
cfg.mcpServers ??= {};
|
|
89140
89420
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
89141
|
-
|
|
89421
|
+
writeFileSync25(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
89142
89422
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
89143
89423
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
89144
89424
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -89146,39 +89426,21 @@ async function installCursorMcpConfig() {
|
|
|
89146
89426
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
89147
89427
|
}
|
|
89148
89428
|
async function installCodexHooks(port) {
|
|
89149
|
-
const
|
|
89150
|
-
const { join: join38 } = await import("node:path");
|
|
89151
|
-
const dir = join38(ROOT, ".codex");
|
|
89152
|
-
if (!existsSync34(dir)) mkdirSync9(dir, { recursive: true });
|
|
89153
|
-
const file2 = join38(dir, "config.toml");
|
|
89154
|
-
let existing = "";
|
|
89155
|
-
if (existsSync34(file2)) {
|
|
89156
|
-
existing = readFileSync33(file2, "utf8");
|
|
89157
|
-
const beginIdx = existing.indexOf(CODEX_HOOKS_BEGIN);
|
|
89158
|
-
const endIdx = existing.indexOf(CODEX_HOOKS_END);
|
|
89159
|
-
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
89160
|
-
existing = existing.slice(0, beginIdx).trimEnd() + existing.slice(endIdx + CODEX_HOOKS_END.length).trimStart();
|
|
89161
|
-
}
|
|
89162
|
-
}
|
|
89163
|
-
const block = buildCodexHooksToml(port);
|
|
89164
|
-
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
89165
|
-
|
|
89166
|
-
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
89167
|
-
writeFileSync24(file2, final, "utf8");
|
|
89429
|
+
const file2 = writeCodexHooks(ROOT, port);
|
|
89168
89430
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
89169
|
-
console.log(
|
|
89170
|
-
console.log("");
|
|
89171
|
-
console.log(
|
|
89172
|
-
console.log(
|
|
89173
|
-
console.log("");
|
|
89174
|
-
|
|
89175
|
-
|
|
89176
|
-
|
|
89177
|
-
|
|
89178
|
-
|
|
89179
|
-
|
|
89180
|
-
|
|
89181
|
-
|
|
89431
|
+
console.log(" Context loads on SessionStart/UserPromptSubmit and refreshes after tools when changed.");
|
|
89432
|
+
console.log(" Tool capture and /api/turn harvesting remain enabled.");
|
|
89433
|
+
console.log(" Restart/resume Codex to reload config, then review and trust the hooks with /hooks.");
|
|
89434
|
+
console.log(" If your Codex version gates hooks, enable [features] codex_hooks = true.");
|
|
89435
|
+
console.log(" Older Codex versions may not support every event; update if hooks do not fire.");
|
|
89436
|
+
}
|
|
89437
|
+
async function refreshLinkedCodexHooks(args2) {
|
|
89438
|
+
if (args2.includes("--skip-hooks") || !hasCodexConfig(ROOT)) return;
|
|
89439
|
+
try {
|
|
89440
|
+
await installCodexHooks(resolveHookPort());
|
|
89441
|
+
} catch (err2) {
|
|
89442
|
+
console.warn(` Codex hook refresh failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
89443
|
+
}
|
|
89182
89444
|
}
|
|
89183
89445
|
function printAiderInstructions() {
|
|
89184
89446
|
console.log(`Aider doesn't expose programmatic per-tool hooks, so the`);
|
|
@@ -89508,7 +89770,7 @@ async function cmdDash(args2) {
|
|
|
89508
89770
|
await yieldToLoop2();
|
|
89509
89771
|
try {
|
|
89510
89772
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
89511
|
-
const res = bleedRules(
|
|
89773
|
+
const res = bleedRules(join38(r.root, ".claude", "rules"), items);
|
|
89512
89774
|
if (res.written || res.pruned) {
|
|
89513
89775
|
console.log(
|
|
89514
89776
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|
package/package.json
CHANGED
package/pass-worker.mjs
CHANGED
|
@@ -15140,7 +15140,7 @@ var init_symbol_intent = __esm({
|
|
|
15140
15140
|
});
|
|
15141
15141
|
|
|
15142
15142
|
// ../../packages/shared/src/wire.ts
|
|
15143
|
-
var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
|
|
15143
|
+
var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, ANCHOR_SYMBOL_KINDS, ANCHOR_LABEL_KINDS, ANCHOR_LABEL_PATH_RE, ANCHOR_LABEL_QNAME_RE, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
|
|
15144
15144
|
var init_wire = __esm({
|
|
15145
15145
|
"../../packages/shared/src/wire.ts"() {
|
|
15146
15146
|
"use strict";
|
|
@@ -15243,6 +15243,21 @@ var init_wire = __esm({
|
|
|
15243
15243
|
});
|
|
15244
15244
|
ANCHOR_COMMIT_SHA_RE = /^[0-9a-f]{7,40}$/;
|
|
15245
15245
|
ANCHOR_BODY_HASH_RE = /^[0-9a-f]{8,64}$/;
|
|
15246
|
+
ANCHOR_SYMBOL_KINDS = [
|
|
15247
|
+
"Function",
|
|
15248
|
+
"Class",
|
|
15249
|
+
"Method",
|
|
15250
|
+
"Module",
|
|
15251
|
+
"Interface",
|
|
15252
|
+
"Const",
|
|
15253
|
+
"Enum",
|
|
15254
|
+
"TypeAlias",
|
|
15255
|
+
"Namespace",
|
|
15256
|
+
"Property"
|
|
15257
|
+
];
|
|
15258
|
+
ANCHOR_LABEL_KINDS = [...ANCHOR_SYMBOL_KINDS, "File"];
|
|
15259
|
+
ANCHOR_LABEL_PATH_RE = /^(?![/])(?![A-Za-z]:)(?!(?:.*\/)?\.\.(?:\/|$))[^\x00-\x1f\x7f\\`]{1,512}$/;
|
|
15260
|
+
ANCHOR_LABEL_QNAME_RE = /^[^\x00-\x1f\x7f`]{1,256}$/;
|
|
15246
15261
|
CastaliaIngestEdgeSchema = external_exports.object({
|
|
15247
15262
|
fromCanonicalId: external_exports.string().min(6).max(160),
|
|
15248
15263
|
toCanonicalId: external_exports.string().min(6).max(160),
|
|
@@ -15262,7 +15277,17 @@ var init_wire = __esm({
|
|
|
15262
15277
|
* classify the anchor current / pre-change; absent ⇒ the pre-versioning
|
|
15263
15278
|
* contract, unverified. Only meaningful on `ANCHORED_AT`. */
|
|
15264
15279
|
observedAtCommit: external_exports.string().regex(ANCHOR_COMMIT_SHA_RE).optional(),
|
|
15265
|
-
symbolContentHash: external_exports.string().regex(ANCHOR_BODY_HASH_RE).optional()
|
|
15280
|
+
symbolContentHash: external_exports.string().regex(ANCHOR_BODY_HASH_RE).optional(),
|
|
15281
|
+
/** PJ-anchor-labels: the READABLE identity of the anchor's target —
|
|
15282
|
+
* repo-relative path, qualified name (absent for a File), kind and line.
|
|
15283
|
+
* Sent only for a project whose owner opted in; the door strips them again
|
|
15284
|
+
* for any project that has not (the daemon's flag is not trusted alone).
|
|
15285
|
+
* Prefixed `label*` so no local edge attr (`anchorLine` lives there
|
|
15286
|
+
* natively) can ride out under a shared key. */
|
|
15287
|
+
labelRelPath: external_exports.string().regex(ANCHOR_LABEL_PATH_RE).optional(),
|
|
15288
|
+
labelQname: external_exports.string().regex(ANCHOR_LABEL_QNAME_RE).optional(),
|
|
15289
|
+
labelKind: external_exports.enum(ANCHOR_LABEL_KINDS).optional(),
|
|
15290
|
+
labelLine: external_exports.number().int().min(1).max(1e7).optional()
|
|
15266
15291
|
}).optional()
|
|
15267
15292
|
});
|
|
15268
15293
|
SymbolSummarySidecarSchema = external_exports.record(
|