@inerrata-corporation/errata 2.0.22-dev.4135 → 2.0.22-dev.4164
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 +557 -0
- package/errata.mjs +1017 -264
- package/generalize-worker.mjs +550 -0
- package/package.json +1 -1
- package/pass-worker.mjs +589 -2
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/errata.mjs
CHANGED
|
@@ -94,7 +94,7 @@ function toCloudAttrs(attrs) {
|
|
|
94
94
|
}
|
|
95
95
|
return rest2;
|
|
96
96
|
}
|
|
97
|
-
var SEMANTIC_NODE_LABELS, ANCHOR_REFUSAL_REASONS, ROUTING_REASONS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, SOLUTION_STRUCTURE_EDGES, SUSPICION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, EDGE_CONDUCTANCE_OVERRIDES, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
|
|
97
|
+
var SEMANTIC_NODE_LABELS, ANCHOR_REFUSAL_REASONS, ROUTING_REASONS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, PROJECT_SYNC_EDGE_TYPES, SOLUTION_STRUCTURE_EDGES, SUSPICION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, EDGE_CONDUCTANCE_OVERRIDES, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
|
|
98
98
|
var init_castalia = __esm({
|
|
99
99
|
"../../packages/shared/src/castalia.ts"() {
|
|
100
100
|
"use strict";
|
|
@@ -321,6 +321,7 @@ var init_castalia = __esm({
|
|
|
321
321
|
ABSTRACTION_EDGES = ["GENERALIZES", "DERIVED_FROM"];
|
|
322
322
|
DECOMPOSITION_EDGES = ["SPLIT_INTO"];
|
|
323
323
|
TRANSFER_EDGES = ["MAY_RESOLVE"];
|
|
324
|
+
PROJECT_SYNC_EDGE_TYPES = ["SOLVED_BY", "CAUSED_BY", "FIXED_BY", "MAY_RESOLVE"];
|
|
324
325
|
SOLUTION_STRUCTURE_EDGES = ["BUILDS_ON", "SUPERSEDES", "ALTERNATIVE_TO"];
|
|
325
326
|
SUSPICION_EDGES = ["SUSPECTED_LINK", "REGRESSION_OF"];
|
|
326
327
|
TAXONOMY_EDGES = ["IS_A"];
|
|
@@ -17625,6 +17626,7 @@ __export(src_exports, {
|
|
|
17625
17626
|
PROBLEM_RESOLUTION: () => PROBLEM_RESOLUTION,
|
|
17626
17627
|
PROJECT_ONLY_EDGE_TYPES: () => PROJECT_ONLY_EDGE_TYPES,
|
|
17627
17628
|
PROJECT_ONLY_NODE_LABELS: () => PROJECT_ONLY_NODE_LABELS,
|
|
17629
|
+
PROJECT_SYNC_EDGE_TYPES: () => PROJECT_SYNC_EDGE_TYPES,
|
|
17628
17630
|
QUARANTINE_EXTRACTION_SOURCE_PREFIX: () => QUARANTINE_EXTRACTION_SOURCE_PREFIX,
|
|
17629
17631
|
REDACTED_CREDENTIAL: () => REDACTED_CREDENTIAL,
|
|
17630
17632
|
REDACTED_EMAIL: () => REDACTED_EMAIL,
|
|
@@ -18205,6 +18207,603 @@ var init_sqlite_adapter = __esm({
|
|
|
18205
18207
|
}
|
|
18206
18208
|
});
|
|
18207
18209
|
|
|
18210
|
+
// ../../packages/local-shared/src/tag-grammar.ts
|
|
18211
|
+
function tagGrammarCopy() {
|
|
18212
|
+
const copy = [];
|
|
18213
|
+
for (const ref of ["its-handle", "its-id", "h", "id"]) {
|
|
18214
|
+
for (const build of Object.values(TAG_EXAMPLES)) copy.push(build(ref));
|
|
18215
|
+
}
|
|
18216
|
+
for (const v of TAG_VERBS) {
|
|
18217
|
+
copy.push(v.hint);
|
|
18218
|
+
if (v.taughtBy) copy.push(v.taughtBy);
|
|
18219
|
+
for (const q of v.qualifiers ?? []) copy.push(q.note);
|
|
18220
|
+
for (const l of v.lowering) {
|
|
18221
|
+
if (l.note) copy.push(l.note);
|
|
18222
|
+
if (l.knownViolation) copy.push(l.knownViolation.finding);
|
|
18223
|
+
}
|
|
18224
|
+
}
|
|
18225
|
+
for (const f of TAG_FENCES) copy.push(f.hint);
|
|
18226
|
+
return copy;
|
|
18227
|
+
}
|
|
18228
|
+
function normalizeTemplateBody(body2) {
|
|
18229
|
+
return body2.replace(/…|\.{3}/g, " ").replace(/\s+/g, " ").trim().replace(/^[\s,;:—–-]+|[\s,;:.—–-]+$/g, "").toLowerCase();
|
|
18230
|
+
}
|
|
18231
|
+
function deriveTagTemplates(copy) {
|
|
18232
|
+
const bodies = /* @__PURE__ */ new Set();
|
|
18233
|
+
const handles = new Set([...TAG_PLACEHOLDER_HANDLES].map((h) => h.toLowerCase()));
|
|
18234
|
+
for (const text of copy) {
|
|
18235
|
+
for (const m of text.matchAll(BRACKET_TOKEN)) {
|
|
18236
|
+
const token = m[1].trim().toLowerCase();
|
|
18237
|
+
if (!/^[!?]/.test(token) && !REAL_HANDLE_SHAPE.test(token)) handles.add(token);
|
|
18238
|
+
}
|
|
18239
|
+
}
|
|
18240
|
+
for (const text of copy) {
|
|
18241
|
+
for (const m of text.matchAll(TEMPLATE_VERB_GROUP)) {
|
|
18242
|
+
const body2 = normalizeTemplateBody(m[2]);
|
|
18243
|
+
bodies.add(body2);
|
|
18244
|
+
const unthreaded = normalizeTemplateBody(body2.replace(/^#[a-z][\w-]*/i, ""));
|
|
18245
|
+
bodies.add(unthreaded);
|
|
18246
|
+
const rest2 = normalizeTemplateBody(unthreaded.replace(BRACKET_TOKEN, (t, h) => handles.has(h.trim().toLowerCase()) ? " " : t).replace(/,/g, " "));
|
|
18247
|
+
bodies.add(rest2);
|
|
18248
|
+
}
|
|
18249
|
+
}
|
|
18250
|
+
bodies.delete("");
|
|
18251
|
+
return { bodies, handles };
|
|
18252
|
+
}
|
|
18253
|
+
function isTemplateSegment(verb, text, templates) {
|
|
18254
|
+
const t = normalizeTemplateBody(text);
|
|
18255
|
+
if (t === "" || templates.bodies.has(t)) return true;
|
|
18256
|
+
const unthreaded = normalizeTemplateBody(t.replace(/^#[a-z][\w-]*/i, ""));
|
|
18257
|
+
if (unthreaded === "" || templates.bodies.has(unthreaded)) return true;
|
|
18258
|
+
let real = false;
|
|
18259
|
+
let standIn = false;
|
|
18260
|
+
const rest2 = unthreaded.replace(BRACKET_TOKEN, (token, inner) => {
|
|
18261
|
+
const h = inner.trim().toLowerCase();
|
|
18262
|
+
if (/^[!?]/.test(h)) return token;
|
|
18263
|
+
if (templates.handles.has(h) || /…|\.{3}/.test(h) || !REAL_HANDLE_SHAPE.test(h)) standIn = true;
|
|
18264
|
+
else real = true;
|
|
18265
|
+
return " ";
|
|
18266
|
+
});
|
|
18267
|
+
if (standIn || real) return true;
|
|
18268
|
+
const words = normalizeTemplateBody(rest2.replace(ANY_VERB_WORD, " ").replace(/,/g, " "));
|
|
18269
|
+
if (words === "" || templates.bodies.has(words)) return true;
|
|
18270
|
+
const spec = verb ? TAG_VERB_BY_NAME.get(verb) : void 0;
|
|
18271
|
+
if (!spec || spec.handleRequired) return true;
|
|
18272
|
+
return words.length < (spec.minText ?? 2);
|
|
18273
|
+
}
|
|
18274
|
+
function isTemplateTagBody(verb, body2, templates = TAG_TEMPLATES) {
|
|
18275
|
+
const whole = normalizeTemplateBody(body2);
|
|
18276
|
+
if (whole === "" || templates.bodies.has(whole)) return true;
|
|
18277
|
+
const segments = body2.split(JOINED_VERB);
|
|
18278
|
+
return segments.every((seg, i2) => {
|
|
18279
|
+
const lead2 = i2 === 0 ? null : LEADING_VERB.exec(seg);
|
|
18280
|
+
return isTemplateSegment(lead2 ? lead2[1].toLowerCase() : verb, lead2 ? seg.slice(lead2[0].length) : seg, templates);
|
|
18281
|
+
});
|
|
18282
|
+
}
|
|
18283
|
+
function quotesOnlyTemplateTags(span, templates = TAG_TEMPLATES) {
|
|
18284
|
+
let found = false;
|
|
18285
|
+
for (const m of span.matchAll(QUOTED_TAG_OPENER)) {
|
|
18286
|
+
found = true;
|
|
18287
|
+
if (m.index > 0 && /[\w$.\])]/.test(span[m.index - 1])) continue;
|
|
18288
|
+
const bodyStart = m.index + m[0].length;
|
|
18289
|
+
let depth = 1;
|
|
18290
|
+
let close = -1;
|
|
18291
|
+
for (let i2 = bodyStart; i2 < span.length; i2++) {
|
|
18292
|
+
if (span[i2] === "(") depth++;
|
|
18293
|
+
else if (span[i2] === ")" && --depth === 0) {
|
|
18294
|
+
close = i2;
|
|
18295
|
+
break;
|
|
18296
|
+
}
|
|
18297
|
+
}
|
|
18298
|
+
if (close < 0) continue;
|
|
18299
|
+
if (!isTemplateTagBody(m[1]?.toLowerCase() ?? null, span.slice(bodyStart, close), templates)) return false;
|
|
18300
|
+
}
|
|
18301
|
+
return found;
|
|
18302
|
+
}
|
|
18303
|
+
var TAG_CANONICAL_ID_PREFIXES, TAG_HANDLE_SOURCE, TAG_THREAD_SOURCE, TAG_PLACEHOLDER_HANDLES, TAG_EXAMPLES, P, S, RC, CITE_LOWERING, INSTANCE_LOWERING, TRIAGE_TO_RC, TAG_VERBS, TAG_FENCES, TAG_VERB_BY_NAME, TAG_PAREN_VERBS, TAG_GRAMMAR_OPENERS, TAG_QUOTED_PAREN_SOURCE, TAG_QUOTED_RE, TAG_QUOTED_PAREN_RE, TEMPLATE_VERB_GROUP, BRACKET_TOKEN, REAL_HANDLE_SHAPE, TAG_TEMPLATES, VERB_WORDS_SOURCE, JOINED_VERB, LEADING_VERB, ANY_VERB_WORD, QUOTED_TAG_OPENER, TAG_VERDICT_TOKENS;
|
|
18304
|
+
var init_tag_grammar = __esm({
|
|
18305
|
+
"../../packages/local-shared/src/tag-grammar.ts"() {
|
|
18306
|
+
"use strict";
|
|
18307
|
+
TAG_CANONICAL_ID_PREFIXES = ["pat", "sol", "drc", "dcause", "dfix", "dprob", "dvuln", "prob", "claim", "err"];
|
|
18308
|
+
TAG_HANDLE_SOURCE = String.raw`\[([a-z0-9][\w-]{0,80})\]|((?:${TAG_CANONICAL_ID_PREFIXES.join("|")})_[0-9a-f]{6,})`;
|
|
18309
|
+
TAG_THREAD_SOURCE = String.raw`#([a-z][\w-]{0,63})`;
|
|
18310
|
+
TAG_PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
|
|
18311
|
+
"handle",
|
|
18312
|
+
"its-handle",
|
|
18313
|
+
"another",
|
|
18314
|
+
"a-third",
|
|
18315
|
+
"h",
|
|
18316
|
+
"h1",
|
|
18317
|
+
"h2",
|
|
18318
|
+
"id",
|
|
18319
|
+
"its-id",
|
|
18320
|
+
"a",
|
|
18321
|
+
"b",
|
|
18322
|
+
"\u2026",
|
|
18323
|
+
"..."
|
|
18324
|
+
]);
|
|
18325
|
+
TAG_EXAMPLES = {
|
|
18326
|
+
prior: (ref) => `([${ref}])`,
|
|
18327
|
+
problem: () => `[!one line on what's wrong]`,
|
|
18328
|
+
vulnerability: () => `[!vuln: who can do what; observed basis @ path:line]`,
|
|
18329
|
+
suspectedVulnerability: () => `[?vuln: consequence; missing check]`,
|
|
18330
|
+
vulnerabilityThread: () => `[!#v vuln: finding here]`,
|
|
18331
|
+
fix: (ref) => `(fix:[${ref}])`,
|
|
18332
|
+
// CONSTRAINT — the native capture path for a DIFFUSE problem (a constraint/tension/
|
|
18333
|
+
// conflict that shaped a decision). Free text, attaches to the decision sentence the
|
|
18334
|
+
// agent is already writing. Full rationale in the constraint note below + prior-tags.ts.
|
|
18335
|
+
constraint: () => `(constraint: the limitation that forced it)`,
|
|
18336
|
+
// TRIAGE — routes the problem/symptom in scope to its cause. `(cause:[handle])`
|
|
18337
|
+
// links to a cited RootCause/Solution node; `(cause: free text)` mints a RootCause
|
|
18338
|
+
// from the text. Harvested in prior-tags.ts → engine.ts (see the triage note below).
|
|
18339
|
+
triage: (ref) => `(cause:[${ref}])`,
|
|
18340
|
+
// Unlike a bare cause citation, this handle names the Problem being explained.
|
|
18341
|
+
triageExplain: (ref) => `(cause:[${ref}] the mechanism)`,
|
|
18342
|
+
// The MINT form — free-text cause that mints a RootCause. Prime-time surfacing
|
|
18343
|
+
// (recallForFile) pastes this next to an open Problem that has no cause yet, so the
|
|
18344
|
+
// diagnostic moment is cued when the agent is looking at the problem. Kept here so
|
|
18345
|
+
// the grammar can't drift from parseInlineTags' `(cause: …)` acceptance.
|
|
18346
|
+
triageMint: () => `(cause: why it happens)`,
|
|
18347
|
+
// THREAD forms — the witness-declared symptom↔cause/fix binding. A `#id` on the
|
|
18348
|
+
// flag names the diagnosis thread; the same `#id` on a later verb binds to it
|
|
18349
|
+
// explicitly (across sentences AND turns), replacing proximity guessing. Adjacent
|
|
18350
|
+
// tags never need one — the id is for diagnoses that unfold over distance.
|
|
18351
|
+
problemThread: () => `[!#slug one line on what's wrong]`,
|
|
18352
|
+
causeThread: () => `(cause:#slug the mechanism)`,
|
|
18353
|
+
fixThread: (thread = "slug") => `(fix:#${thread} what you changed)`,
|
|
18354
|
+
// ATTEMPT arc — what's being tried and what didn't work. A failed attempt is a
|
|
18355
|
+
// witnessed NEGATIVE result: it saves the next agent the same dead end.
|
|
18356
|
+
tried: () => `(tried: the approach you're attempting)`,
|
|
18357
|
+
failed: () => `(failed: what didn't work and the dead end it rules out)`,
|
|
18358
|
+
// `(failed:[h] …)` on a shown SOLUTION — the refute-by-failure form the context render teaches.
|
|
18359
|
+
failedCite: (ref) => `(failed:[${ref}] what came back)`,
|
|
18360
|
+
// LINK verbs (AC epic) — bind the problem in scope to CANONICAL priors and
|
|
18361
|
+
// abstractions. Multi-target by design: single links are weak; ~3 links to 3
|
|
18362
|
+
// DIFFERENT relevant priors is the target shape (see linkBullet).
|
|
18363
|
+
instance: (ref) => `(instance:[${ref}],[another],[a-third])`,
|
|
18364
|
+
pattern: () => `(pattern: name the general shape)`,
|
|
18365
|
+
// DOMAIN — the abstract area a problem is about; the concept layer an
|
|
18366
|
+
// anchor-less problem clusters on. Mints/resolves a Domain by name.
|
|
18367
|
+
domain: () => `(domain: The Area)`,
|
|
18368
|
+
// PACKAGE/COMPONENT — agent-named public anchors (OM-agent-anchors): the
|
|
18369
|
+
// package a problem is ABOUT (even when not a dependency) and the
|
|
18370
|
+
// framework/product-level unit it concerns. Public spine anchors → the
|
|
18371
|
+
// knowledge can cross to the collective.
|
|
18372
|
+
package: () => `(package: the-package-name)`,
|
|
18373
|
+
component: () => `(component: The Component)`,
|
|
18374
|
+
aids: (ref) => `(aids:[${ref}])`,
|
|
18375
|
+
// SOLUTION-STRUCTURE (SS-structure) — taught in the link bullet; Solution→Solution.
|
|
18376
|
+
buildsOn: (ref) => `(builds-on:[${ref}])`,
|
|
18377
|
+
supersedes: (ref) => `(supersedes:[${ref}])`,
|
|
18378
|
+
alternative: (ref) => `(alternative:[${ref}])`,
|
|
18379
|
+
// VERDICT (VS-verdict-tags) — a judgment on a SHOWN prior, distinct from leaning on it.
|
|
18380
|
+
// `confirm` rides the corroborate channel (it held); `refute` the contradict channel
|
|
18381
|
+
// (it's wrong / didn't hold) and REQUIRES a reason. This is the inline producer the
|
|
18382
|
+
// evidence channels lacked — refute sat dead (contradictionPressure 0) until now, while
|
|
18383
|
+
// lean-on corroboration lived, because only corroboration had an inline path. Grammar
|
|
18384
|
+
// single-sourced with parseInlineTags' CONFIRM_PREFIX/REFUTE_PREFIX.
|
|
18385
|
+
confirm: (ref) => `(confirm:[${ref}])`,
|
|
18386
|
+
refute: (ref) => `(refute:[${ref}] one line why)`,
|
|
18387
|
+
// RETRACT — "not a real problem": the errata-resolved block with a disposition
|
|
18388
|
+
// (parseDesignResolutions, turn.ts). No inline form exists; the block is the grammar.
|
|
18389
|
+
retract: (id) => ["```errata-resolved", `id: ${id}`, "disposition: false_positive", "reason: why it was never a real problem", "```"].join("\n")
|
|
18390
|
+
};
|
|
18391
|
+
P = "Problem";
|
|
18392
|
+
S = "Solution";
|
|
18393
|
+
RC = "RootCause";
|
|
18394
|
+
CITE_LOWERING = [
|
|
18395
|
+
{ target: RC, writes: [{ from: P, edge: "CAUSED_BY", to: RC }] },
|
|
18396
|
+
{ target: S, writes: [{ from: P, edge: "SOLVED_BY", to: S }] },
|
|
18397
|
+
{ target: "Pattern", writes: [{ from: P, edge: "INSTANCE_OF", to: "Pattern" }, { from: "Pattern", edge: "ANCHORED_AT", to: "File" }], note: "cite-anchor promotion after 2 sessions", decision: "d", knownViolation: { edge: "ANCHORED_AT", finding: "motif cite-anchor promotion writes a refused ANCHORED_AT" } },
|
|
18398
|
+
{ target: "Package", writes: [{ from: P, edge: "DEPENDS_ON", to: "Package" }] },
|
|
18399
|
+
{ target: "Language", writes: [{ from: P, edge: "OCCURS_IN", to: "Language" }] },
|
|
18400
|
+
{ target: "Tool", writes: [{ from: P, edge: "CONCERNS", to: "Tool" }] },
|
|
18401
|
+
{ target: "Component", writes: [{ from: P, edge: "CONCERNS", to: "Component" }] },
|
|
18402
|
+
{ target: P, writes: [{ from: P, edge: "RELATES_TO", to: P }, { from: P, edge: "ANCHORED_AT", to: "File" }], note: "corroboration witness + cite-anchor promotion" },
|
|
18403
|
+
{ target: "AntiPattern", writes: [{ from: P, edge: "RELATES_TO", to: "AntiPattern" }, { from: "AntiPattern", edge: "ANCHORED_AT", to: "File" }], decision: "e", knownViolation: { edge: "ANCHORED_AT", finding: "motif cite-anchor promotion writes a refused ANCHORED_AT" } },
|
|
18404
|
+
{ target: "Technique", writes: [{ from: P, edge: "RELATES_TO", to: "Technique" }, { from: "Technique", edge: "ANCHORED_AT", to: "File" }], decision: "e", knownViolation: { edge: "ANCHORED_AT", finding: "motif cite-anchor promotion writes a refused ANCHORED_AT" } },
|
|
18405
|
+
{ target: "Weakness", writes: [{ from: P, edge: "RELATES_TO", to: "Weakness" }], decision: "e" },
|
|
18406
|
+
{ target: "Domain", writes: [{ from: P, edge: "RELATES_TO", to: "Domain" }], decision: "e" },
|
|
18407
|
+
{ target: "Claim", writes: [{ from: P, edge: "RELATES_TO", to: "Claim" }, { from: "Claim", edge: "ANCHORED_AT", to: "File" }] }
|
|
18408
|
+
];
|
|
18409
|
+
INSTANCE_LOWERING = [
|
|
18410
|
+
{ target: "Pattern", writes: [{ from: P, edge: "INSTANCE_OF", to: "Pattern" }] },
|
|
18411
|
+
{ target: P, writes: [{ from: P, edge: "RELATES_TO", to: P }] },
|
|
18412
|
+
{ target: S, writes: [{ from: P, edge: "SOLVED_BY", to: S }], note: "an instance cite on a Solution claims the problem is solved by it", decision: "a" },
|
|
18413
|
+
{ target: RC, writes: [{ from: P, edge: "CAUSED_BY", to: RC }] },
|
|
18414
|
+
{ target: "AntiPattern", writes: [{ from: P, edge: "RELATES_TO", to: "AntiPattern" }], decision: "e" },
|
|
18415
|
+
{ target: "Technique", writes: [{ from: P, edge: "RELATES_TO", to: "Technique" }], decision: "e" },
|
|
18416
|
+
{ target: "Weakness", writes: [{ from: P, edge: "RELATES_TO", to: "Weakness" }], decision: "e" },
|
|
18417
|
+
{ target: "Domain", writes: [{ from: P, edge: "RELATES_TO", to: "Domain" }], decision: "e" },
|
|
18418
|
+
{ target: "Package", writes: [{ from: P, edge: "DEPENDS_ON", to: "Package" }] },
|
|
18419
|
+
{ target: "Component", writes: [{ from: P, edge: "CONCERNS", to: "Component" }] }
|
|
18420
|
+
];
|
|
18421
|
+
TRIAGE_TO_RC = [
|
|
18422
|
+
{ from: P, edge: "TRIAGED_BY", to: "Triage" },
|
|
18423
|
+
{ from: "Triage", edge: "INDICATES", to: RC },
|
|
18424
|
+
{ from: P, edge: "CAUSED_BY", to: RC }
|
|
18425
|
+
];
|
|
18426
|
+
TAG_VERBS = [
|
|
18427
|
+
{
|
|
18428
|
+
verb: "cite",
|
|
18429
|
+
form: "citation",
|
|
18430
|
+
opener: "(",
|
|
18431
|
+
kinds: ["prior"],
|
|
18432
|
+
args: "handles",
|
|
18433
|
+
thread: false,
|
|
18434
|
+
handleRequired: true,
|
|
18435
|
+
lowering: CITE_LOWERING,
|
|
18436
|
+
examples: ["prior"],
|
|
18437
|
+
hint: "cite a shown prior you leaned on: ([its-handle]) \u2014 handles only, no prose inside the parens",
|
|
18438
|
+
taught: "taught"
|
|
18439
|
+
},
|
|
18440
|
+
{
|
|
18441
|
+
verb: "!",
|
|
18442
|
+
form: "flag",
|
|
18443
|
+
opener: "[!",
|
|
18444
|
+
kinds: ["problem", "triage", "vulnerability", "fix", "prior"],
|
|
18445
|
+
args: "flag-body",
|
|
18446
|
+
thread: true,
|
|
18447
|
+
minText: 8,
|
|
18448
|
+
qualifiers: [
|
|
18449
|
+
{ name: "vuln", taught: true, note: "[!vuln: \u2026] \u2192 Vulnerability (asserted)" },
|
|
18450
|
+
{ name: "fixed", taught: false, note: "[!fixed: X] \u2192 read as a self-found fix" },
|
|
18451
|
+
{ name: "resolved", taught: false, note: "[!resolved: X] \u2192 read as a self-found fix" }
|
|
18452
|
+
],
|
|
18453
|
+
lowering: [
|
|
18454
|
+
{ target: P, writes: [], note: "mints a Problem; `@ path[:line]` anchors it (ANCHORED_AT to code)" },
|
|
18455
|
+
{ target: RC, writes: [...TRIAGE_TO_RC, { from: RC, edge: "CAUSED_BY", to: RC }], note: "`<-` segments: first \u2192 triage route, later \u2192 RootCause chain" },
|
|
18456
|
+
{ target: "Vulnerability", writes: [], note: "[!vuln: \u2026]; `<-` causes stay on the finding (vulnerabilityCauses)" }
|
|
18457
|
+
],
|
|
18458
|
+
examples: ["problem", "problemThread", "vulnerability", "vulnerabilityThread"],
|
|
18459
|
+
hint: "flag a problem on one line: [!what's wrong @ path:42]; fold causes with <- ; a fix goes in (fix: \u2026), not [!fixed: \u2026]",
|
|
18460
|
+
taught: "taught"
|
|
18461
|
+
},
|
|
18462
|
+
{
|
|
18463
|
+
verb: "?",
|
|
18464
|
+
form: "flag",
|
|
18465
|
+
opener: "[?",
|
|
18466
|
+
kinds: ["todo", "vulnerability"],
|
|
18467
|
+
args: "flag-body",
|
|
18468
|
+
thread: true,
|
|
18469
|
+
minText: 8,
|
|
18470
|
+
qualifiers: [{ name: "vuln", taught: true, note: "[?vuln: \u2026] \u2192 Vulnerability (suspected)" }],
|
|
18471
|
+
lowering: [{ target: P, writes: [], note: "mints a todo Problem; a fix can close it today", decision: "g" }],
|
|
18472
|
+
examples: ["suspectedVulnerability"],
|
|
18473
|
+
hint: "[?\u2026] marks an open question / todo; [?vuln: consequence; missing check] a suspected vulnerability",
|
|
18474
|
+
taught: "untaught",
|
|
18475
|
+
taughtBy: "only the [?vuln:] form is taught; the bare [?todo] form is not",
|
|
18476
|
+
decisions: ["g"]
|
|
18477
|
+
},
|
|
18478
|
+
{
|
|
18479
|
+
verb: "fix",
|
|
18480
|
+
form: "verb",
|
|
18481
|
+
opener: "(fix:",
|
|
18482
|
+
kinds: ["fix"],
|
|
18483
|
+
args: "handles-text",
|
|
18484
|
+
thread: true,
|
|
18485
|
+
minText: 12,
|
|
18486
|
+
lowering: [
|
|
18487
|
+
{ target: P, writes: [{ from: P, edge: "SOLVED_BY", to: S }], note: "closes the Problem; a note \u226512 chars mints the Solution" },
|
|
18488
|
+
{ target: "Vulnerability", writes: [{ from: "Vulnerability", edge: "SOLVED_BY", to: S }] },
|
|
18489
|
+
{ target: RC, writes: [], note: "dropped: 'fix tag went nowhere' (not a Problem); no tag writes FIXED_BY", decision: "f" }
|
|
18490
|
+
],
|
|
18491
|
+
examples: ["fix", "fixThread"],
|
|
18492
|
+
hint: "one fix per tag: (fix:[its-handle]) or (fix:#thread what you changed) \u2014 put the cause in its own (cause: \u2026)",
|
|
18493
|
+
taught: "taught",
|
|
18494
|
+
decisions: ["f"]
|
|
18495
|
+
},
|
|
18496
|
+
{
|
|
18497
|
+
verb: "cause",
|
|
18498
|
+
form: "verb",
|
|
18499
|
+
opener: "(cause:",
|
|
18500
|
+
kinds: ["triage"],
|
|
18501
|
+
args: "handles-text",
|
|
18502
|
+
thread: true,
|
|
18503
|
+
minText: 8,
|
|
18504
|
+
lowering: [
|
|
18505
|
+
{ target: RC, writes: TRIAGE_TO_RC },
|
|
18506
|
+
{ target: P, writes: [{ from: P, edge: "TRIAGED_BY", to: "Triage" }, { from: "Triage", edge: "INDICATES", to: RC }, { from: P, edge: "CAUSED_BY", to: RC }], note: "(cause:[problem] mechanism) \u2014 the cited Problem is the symptom; the mechanism mints the RootCause" },
|
|
18507
|
+
{ target: S, writes: [{ from: P, edge: "TRIAGED_BY", to: "Triage" }, { from: "Triage", edge: "INDICATES", to: S }], decision: "b", knownViolation: { edge: "INDICATES", finding: "(cause:[solution]) writes a refused INDICATES \u2192 Solution" } }
|
|
18508
|
+
],
|
|
18509
|
+
examples: ["triage", "triageExplain", "triageMint", "causeThread"],
|
|
18510
|
+
hint: "(cause: the mechanism you'd change) or (cause:[root-cause-handle]); bind a distant symptom with (cause:#thread \u2026)",
|
|
18511
|
+
taught: "taught",
|
|
18512
|
+
decisions: ["b"]
|
|
18513
|
+
},
|
|
18514
|
+
{
|
|
18515
|
+
verb: "constraint",
|
|
18516
|
+
form: "verb",
|
|
18517
|
+
opener: "(constraint:",
|
|
18518
|
+
kinds: ["constraint"],
|
|
18519
|
+
args: "text",
|
|
18520
|
+
thread: false,
|
|
18521
|
+
minText: 8,
|
|
18522
|
+
textRequired: true,
|
|
18523
|
+
lowering: [{ target: P, writes: [], note: "mints a constraint-kind Problem" }],
|
|
18524
|
+
examples: ["constraint"],
|
|
18525
|
+
hint: "(constraint: the limitation that forced the decision)",
|
|
18526
|
+
taught: "taught"
|
|
18527
|
+
},
|
|
18528
|
+
{
|
|
18529
|
+
verb: "tried",
|
|
18530
|
+
form: "verb",
|
|
18531
|
+
opener: "(tried:",
|
|
18532
|
+
kinds: ["attempt"],
|
|
18533
|
+
args: "text",
|
|
18534
|
+
thread: true,
|
|
18535
|
+
minText: 8,
|
|
18536
|
+
textRequired: true,
|
|
18537
|
+
lowering: [{ target: P, writes: [], note: "journals an attempt on the bound problem" }],
|
|
18538
|
+
examples: ["tried"],
|
|
18539
|
+
hint: "(tried: the approach) \u2014 bind with (tried:#thread \u2026)",
|
|
18540
|
+
taught: "taught"
|
|
18541
|
+
},
|
|
18542
|
+
{
|
|
18543
|
+
verb: "failed",
|
|
18544
|
+
form: "verb",
|
|
18545
|
+
opener: "(failed:",
|
|
18546
|
+
kinds: ["failure"],
|
|
18547
|
+
args: "handles-text",
|
|
18548
|
+
thread: true,
|
|
18549
|
+
minText: 8,
|
|
18550
|
+
textRequired: true,
|
|
18551
|
+
lowering: [
|
|
18552
|
+
{ target: P, writes: [], note: "journals a failed attempt on the bound problem" },
|
|
18553
|
+
{ target: S, writes: [], note: "(failed:[h]) refutes the cited prior (contradictionPressure); skips the label gate today", decision: "j" }
|
|
18554
|
+
],
|
|
18555
|
+
examples: ["failed", "failedCite"],
|
|
18556
|
+
hint: "(failed: what didn't work); (failed:[solution] what came back) refutes a shown fix",
|
|
18557
|
+
taught: "taught",
|
|
18558
|
+
decisions: ["j"]
|
|
18559
|
+
},
|
|
18560
|
+
{
|
|
18561
|
+
verb: "instance",
|
|
18562
|
+
form: "verb",
|
|
18563
|
+
opener: "(instance:",
|
|
18564
|
+
kinds: ["instance"],
|
|
18565
|
+
args: "handles",
|
|
18566
|
+
thread: false,
|
|
18567
|
+
handleRequired: true,
|
|
18568
|
+
lowering: INSTANCE_LOWERING,
|
|
18569
|
+
examples: ["instance"],
|
|
18570
|
+
hint: "(instance:[h1],[h2],[h3]) \u2014 ~3 DIFFERENT shown priors this problem instantiates; handles only",
|
|
18571
|
+
taught: "taught",
|
|
18572
|
+
decisions: ["a", "e"]
|
|
18573
|
+
},
|
|
18574
|
+
{
|
|
18575
|
+
verb: "pattern",
|
|
18576
|
+
form: "verb",
|
|
18577
|
+
opener: "(pattern:",
|
|
18578
|
+
kinds: ["pattern"],
|
|
18579
|
+
args: "handle-or-text",
|
|
18580
|
+
thread: false,
|
|
18581
|
+
minText: 3,
|
|
18582
|
+
lowering: [{ target: "Pattern", writes: [{ from: P, edge: "INSTANCE_OF", to: "Pattern" }], note: "a handle must be a Pattern; free text resolves-or-mints one" }],
|
|
18583
|
+
examples: ["pattern"],
|
|
18584
|
+
hint: "(pattern: name the general shape) or (pattern:[shown-pattern])",
|
|
18585
|
+
taught: "taught"
|
|
18586
|
+
},
|
|
18587
|
+
{
|
|
18588
|
+
verb: "domain",
|
|
18589
|
+
form: "verb",
|
|
18590
|
+
opener: "(domain:",
|
|
18591
|
+
kinds: ["domain"],
|
|
18592
|
+
args: "text",
|
|
18593
|
+
thread: false,
|
|
18594
|
+
minText: 2,
|
|
18595
|
+
textRequired: true,
|
|
18596
|
+
lowering: [{ target: "Domain", writes: [{ from: P, edge: "PERTAIN_TO", to: "Domain" }], note: '(domain:#t X) mints a Domain named "#t X" today', decision: "k" }],
|
|
18597
|
+
examples: ["domain"],
|
|
18598
|
+
hint: "(domain: The Area) \u2014 Title Case, no thread",
|
|
18599
|
+
taught: "taught",
|
|
18600
|
+
decisions: ["k"]
|
|
18601
|
+
},
|
|
18602
|
+
{
|
|
18603
|
+
verb: "package",
|
|
18604
|
+
form: "verb",
|
|
18605
|
+
opener: "(package:",
|
|
18606
|
+
kinds: ["package"],
|
|
18607
|
+
args: "text",
|
|
18608
|
+
thread: false,
|
|
18609
|
+
minText: 2,
|
|
18610
|
+
textRequired: true,
|
|
18611
|
+
lowering: [{ target: "Package", writes: [{ from: P, edge: "DEPENDS_ON", to: "Package" }], note: "means 'concerns', written as DEPENDS_ON", decision: "c" }],
|
|
18612
|
+
examples: ["package"],
|
|
18613
|
+
hint: "(package: the-package-name) \u2014 the public package it's about",
|
|
18614
|
+
taught: "taught",
|
|
18615
|
+
decisions: ["c"]
|
|
18616
|
+
},
|
|
18617
|
+
{
|
|
18618
|
+
verb: "component",
|
|
18619
|
+
form: "verb",
|
|
18620
|
+
opener: "(component:",
|
|
18621
|
+
kinds: ["component"],
|
|
18622
|
+
args: "text",
|
|
18623
|
+
thread: false,
|
|
18624
|
+
minText: 2,
|
|
18625
|
+
textRequired: true,
|
|
18626
|
+
lowering: [{ target: "Component", writes: [{ from: P, edge: "CONCERNS", to: "Component" }] }],
|
|
18627
|
+
examples: ["component"],
|
|
18628
|
+
hint: "(component: The Component) \u2014 the framework/product unit",
|
|
18629
|
+
taught: "taught"
|
|
18630
|
+
},
|
|
18631
|
+
{
|
|
18632
|
+
verb: "aids",
|
|
18633
|
+
form: "verb",
|
|
18634
|
+
opener: "(aids:",
|
|
18635
|
+
kinds: ["transfer"],
|
|
18636
|
+
args: "handles",
|
|
18637
|
+
thread: true,
|
|
18638
|
+
handleRequired: true,
|
|
18639
|
+
lowering: [{ target: P, writes: [{ from: S, edge: "MAY_RESOLVE", to: P }], note: "source = the Solution in scope; non-Problem targets are skipped" }],
|
|
18640
|
+
examples: ["aids"],
|
|
18641
|
+
hint: "(aids:[problem-handle],\u2026) \u2014 other shown problems your fix might also resolve",
|
|
18642
|
+
taught: "taught"
|
|
18643
|
+
},
|
|
18644
|
+
{
|
|
18645
|
+
verb: "builds-on",
|
|
18646
|
+
form: "verb",
|
|
18647
|
+
opener: "(builds-on:",
|
|
18648
|
+
kinds: ["builds-on"],
|
|
18649
|
+
args: "handles",
|
|
18650
|
+
thread: true,
|
|
18651
|
+
handleRequired: true,
|
|
18652
|
+
lowering: [{ target: S, writes: [{ from: S, edge: "BUILDS_ON", to: S }] }],
|
|
18653
|
+
examples: ["buildsOn"],
|
|
18654
|
+
hint: "(builds-on:[shown-solution]) \u2014 your fix layers on it",
|
|
18655
|
+
taught: "taught",
|
|
18656
|
+
taughtBy: "linkBullet instruction text"
|
|
18657
|
+
},
|
|
18658
|
+
{
|
|
18659
|
+
verb: "supersedes",
|
|
18660
|
+
form: "verb",
|
|
18661
|
+
opener: "(supersedes:",
|
|
18662
|
+
kinds: ["supersedes"],
|
|
18663
|
+
args: "handles",
|
|
18664
|
+
thread: true,
|
|
18665
|
+
handleRequired: true,
|
|
18666
|
+
lowering: [{ target: S, writes: [{ from: S, edge: "SUPERSEDES", to: S }] }],
|
|
18667
|
+
examples: ["supersedes"],
|
|
18668
|
+
hint: "(supersedes:[shown-solution]) \u2014 your fix replaces it",
|
|
18669
|
+
taught: "taught",
|
|
18670
|
+
taughtBy: "linkBullet instruction text"
|
|
18671
|
+
},
|
|
18672
|
+
{
|
|
18673
|
+
verb: "alternative",
|
|
18674
|
+
form: "verb",
|
|
18675
|
+
opener: "(alternative:",
|
|
18676
|
+
kinds: ["alternative"],
|
|
18677
|
+
args: "handles",
|
|
18678
|
+
thread: true,
|
|
18679
|
+
handleRequired: true,
|
|
18680
|
+
lowering: [{ target: S, writes: [{ from: S, edge: "ALTERNATIVE_TO", to: S }] }],
|
|
18681
|
+
examples: ["alternative"],
|
|
18682
|
+
hint: "(alternative:[shown-solution]) \u2014 a different valid approach",
|
|
18683
|
+
taught: "taught",
|
|
18684
|
+
taughtBy: "linkBullet instruction text"
|
|
18685
|
+
},
|
|
18686
|
+
{
|
|
18687
|
+
verb: "confirm",
|
|
18688
|
+
form: "verb",
|
|
18689
|
+
opener: "(confirm:",
|
|
18690
|
+
kinds: ["confirm"],
|
|
18691
|
+
args: "handles",
|
|
18692
|
+
thread: false,
|
|
18693
|
+
handleRequired: true,
|
|
18694
|
+
lowering: [{ target: S, writes: [], note: "corroboration witness (corroborationCount), no edge" }],
|
|
18695
|
+
examples: ["confirm"],
|
|
18696
|
+
hint: "(confirm:[shown-prior]) \u2014 it held",
|
|
18697
|
+
taught: "taught",
|
|
18698
|
+
taughtBy: "verdictBullet + context render",
|
|
18699
|
+
decisions: ["j"]
|
|
18700
|
+
},
|
|
18701
|
+
{
|
|
18702
|
+
verb: "refute",
|
|
18703
|
+
form: "verb",
|
|
18704
|
+
opener: "(refute:",
|
|
18705
|
+
kinds: ["refute"],
|
|
18706
|
+
args: "handles-text",
|
|
18707
|
+
thread: false,
|
|
18708
|
+
minText: 4,
|
|
18709
|
+
handleRequired: true,
|
|
18710
|
+
textRequired: true,
|
|
18711
|
+
lowering: [{ target: S, writes: [], note: "contradiction witness (contradictionPressure), no edge; reason stays local" }],
|
|
18712
|
+
examples: ["refute"],
|
|
18713
|
+
hint: "(refute:[shown-prior] one line why) \u2014 the reason is required",
|
|
18714
|
+
taught: "taught",
|
|
18715
|
+
taughtBy: "verdictBullet + context render",
|
|
18716
|
+
decisions: ["j"]
|
|
18717
|
+
}
|
|
18718
|
+
];
|
|
18719
|
+
TAG_FENCES = [
|
|
18720
|
+
{
|
|
18721
|
+
fence: "errata-problem",
|
|
18722
|
+
fields: ["problem", "cause", "fix", "anchor", "kind"],
|
|
18723
|
+
required: [["problem"]],
|
|
18724
|
+
taught: "untaught",
|
|
18725
|
+
parser: "apps/daemon/src/turn.ts parseDesignFlags",
|
|
18726
|
+
decisions: ["h"],
|
|
18727
|
+
hint: "use an inline [!\u2026] flag instead (errata-problem cause ids never meet inline ids)"
|
|
18728
|
+
},
|
|
18729
|
+
{
|
|
18730
|
+
fence: "errata-resolved",
|
|
18731
|
+
fields: ["id", "problem", "fix", "disposition", "reason"],
|
|
18732
|
+
required: [["id", "problem"]],
|
|
18733
|
+
taught: "taught",
|
|
18734
|
+
taughtBy: "retract form only (TAG_EXAMPLE.retract); the fix form is untaught",
|
|
18735
|
+
parser: "apps/daemon/src/turn.ts parseDesignResolutions",
|
|
18736
|
+
hint: "```errata-resolved with id: and disposition: false_positive | invalid, reason: \u2026"
|
|
18737
|
+
},
|
|
18738
|
+
{
|
|
18739
|
+
fence: "errata-triage",
|
|
18740
|
+
fields: ["presenting", "cause", "test", "fix", "drift", "route"],
|
|
18741
|
+
required: [["presenting", "route"], ["cause", "test"]],
|
|
18742
|
+
taught: "taught",
|
|
18743
|
+
taughtBy: "MCP errata_triage tool copy",
|
|
18744
|
+
parser: "packages/local-graph/src/triage.ts parseTriageFences",
|
|
18745
|
+
hint: "```errata-triage with presenting: and cause: (or route: + test: to answer one)"
|
|
18746
|
+
},
|
|
18747
|
+
{
|
|
18748
|
+
fence: "errata-abstraction",
|
|
18749
|
+
fields: ["candidate", "principle", "covers"],
|
|
18750
|
+
required: [["candidate"], ["principle"], ["covers"]],
|
|
18751
|
+
taught: "taught",
|
|
18752
|
+
taughtBy: "MCP errata_pending_abstractions tool copy",
|
|
18753
|
+
parser: "packages/local-graph/src/abstraction.ts parseAbstractionFences",
|
|
18754
|
+
hint: "```errata-abstraction with candidate:, principle:, covers: (all required)"
|
|
18755
|
+
},
|
|
18756
|
+
{
|
|
18757
|
+
fence: "errata-intent",
|
|
18758
|
+
fields: ["intent"],
|
|
18759
|
+
required: [["intent"]],
|
|
18760
|
+
taught: "taught",
|
|
18761
|
+
parser: "packages/local-graph/src/intent.ts parseIntentFences",
|
|
18762
|
+
hint: "```errata-intent with intent: what you're about to do"
|
|
18763
|
+
},
|
|
18764
|
+
{
|
|
18765
|
+
fence: "errata-share",
|
|
18766
|
+
fields: ["priors"],
|
|
18767
|
+
required: [["priors"]],
|
|
18768
|
+
taught: "taught",
|
|
18769
|
+
taughtBy: "subagent hand-off copy",
|
|
18770
|
+
parser: "packages/local-graph/src/intent.ts parseShareFence",
|
|
18771
|
+
hint: "```errata-share with priors: all | [h1], [h2]"
|
|
18772
|
+
}
|
|
18773
|
+
];
|
|
18774
|
+
TAG_VERB_BY_NAME = new Map(
|
|
18775
|
+
TAG_VERBS.filter((v) => v.form === "verb").map((v) => [v.verb, v])
|
|
18776
|
+
);
|
|
18777
|
+
TAG_PAREN_VERBS = [...TAG_VERB_BY_NAME.keys()].sort((a, b) => b.length - a.length);
|
|
18778
|
+
TAG_GRAMMAR_OPENERS = [
|
|
18779
|
+
...new Set(TAG_VERBS.filter((v) => v.form !== "citation").map((v) => v.opener))
|
|
18780
|
+
];
|
|
18781
|
+
TAG_QUOTED_PAREN_SOURCE = String.raw`\(\s*(?:${TAG_PAREN_VERBS.map((v) => v.replace(/-/g, "\\-")).join("|")})\s*:|\(\[`;
|
|
18782
|
+
TAG_QUOTED_RE = new RegExp(String.raw`\[[!?]|` + TAG_QUOTED_PAREN_SOURCE, "i");
|
|
18783
|
+
TAG_QUOTED_PAREN_RE = new RegExp(TAG_QUOTED_PAREN_SOURCE, "i");
|
|
18784
|
+
TEMPLATE_VERB_GROUP = new RegExp(
|
|
18785
|
+
String.raw`\(\s*(${TAG_PAREN_VERBS.map((v) => v.replace(/-/g, "\\-")).join("|")})\s*:((?:[^()\n]|\([^()\n]*\))*)\)`,
|
|
18786
|
+
"gi"
|
|
18787
|
+
);
|
|
18788
|
+
BRACKET_TOKEN = /\[([^\]\n]{1,80})\]/g;
|
|
18789
|
+
REAL_HANDLE_SHAPE = new RegExp(
|
|
18790
|
+
String.raw`^(?:[a-z0-9]+(?:-[a-z0-9]+)*-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:${TAG_CANONICAL_ID_PREFIXES.join("|")})_[0-9a-f]{6,})$`,
|
|
18791
|
+
"i"
|
|
18792
|
+
);
|
|
18793
|
+
TAG_TEMPLATES = deriveTagTemplates(tagGrammarCopy());
|
|
18794
|
+
VERB_WORDS_SOURCE = TAG_PAREN_VERBS.map((v) => v.replace(/-/g, "\\-")).join("|");
|
|
18795
|
+
JOINED_VERB = new RegExp(String.raw`[,;]\s*(?=(?:${VERB_WORDS_SOURCE})\s*:)`, "i");
|
|
18796
|
+
LEADING_VERB = new RegExp(String.raw`^\s*(${VERB_WORDS_SOURCE})\s*:`, "i");
|
|
18797
|
+
ANY_VERB_WORD = new RegExp(String.raw`\b(?:${VERB_WORDS_SOURCE})\s*:`, "gi");
|
|
18798
|
+
QUOTED_TAG_OPENER = new RegExp(String.raw`\(\s*(?:(${VERB_WORDS_SOURCE})\s*:|(?=\[))`, "gi");
|
|
18799
|
+
TAG_VERDICT_TOKENS = {
|
|
18800
|
+
confirm: (id) => TAG_EXAMPLES.confirm(id),
|
|
18801
|
+
refute: (id) => TAG_EXAMPLES.refute(id),
|
|
18802
|
+
failed: (id) => TAG_EXAMPLES.failedCite(id)
|
|
18803
|
+
};
|
|
18804
|
+
}
|
|
18805
|
+
});
|
|
18806
|
+
|
|
18208
18807
|
// ../../packages/local-shared/src/index.ts
|
|
18209
18808
|
var init_src2 = __esm({
|
|
18210
18809
|
"../../packages/local-shared/src/index.ts"() {
|
|
@@ -18218,6 +18817,7 @@ var init_src2 = __esm({
|
|
|
18218
18817
|
init_review();
|
|
18219
18818
|
init_anchorable();
|
|
18220
18819
|
init_sqlite_adapter();
|
|
18820
|
+
init_tag_grammar();
|
|
18221
18821
|
}
|
|
18222
18822
|
});
|
|
18223
18823
|
|
|
@@ -20854,6 +21454,20 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20854
21454
|
if (revived > 0) this.mutations++;
|
|
20855
21455
|
return revived;
|
|
20856
21456
|
}
|
|
21457
|
+
incomingEdgeCoverage(label, edgeTypes, cloudOnly) {
|
|
21458
|
+
if (edgeTypes.length === 0) return { count: 0, total: 0 };
|
|
21459
|
+
const r = this.db.prepare(
|
|
21460
|
+
`SELECT COUNT(*) AS total,
|
|
21461
|
+
COALESCE(SUM(CASE WHEN EXISTS (
|
|
21462
|
+
SELECT 1 FROM edges e WHERE e.to_id = n.id AND e.valid_to IS NULL
|
|
21463
|
+
AND e.type IN (${edgeTypes.map(() => "?").join(",")})
|
|
21464
|
+
) THEN 1 ELSE 0 END), 0) AS count
|
|
21465
|
+
FROM nodes n
|
|
21466
|
+
WHERE n.label = ? AND n.valid_to IS NULL
|
|
21467
|
+
AND (? = 0 OR json_extract(n.attrs_json, '$.source') = 'cloud')`
|
|
21468
|
+
).get(...edgeTypes, label, cloudOnly ? 1 : 0);
|
|
21469
|
+
return { count: Number(r.count), total: Number(r.total) };
|
|
21470
|
+
}
|
|
20857
21471
|
recentEdgeAttrCoverage(marker, attr, limit) {
|
|
20858
21472
|
const r = this.db.prepare(
|
|
20859
21473
|
`SELECT COUNT(*) AS total,
|
|
@@ -25739,6 +26353,14 @@ var init_principle_sync = __esm({
|
|
|
25739
26353
|
|
|
25740
26354
|
// ../../packages/local-graph/src/mechanism-liveness.ts
|
|
25741
26355
|
function evaluateFed(store, d) {
|
|
26356
|
+
if (d.fedIncoming) {
|
|
26357
|
+
const { count: count2, total } = store.incomingEdgeCoverage?.(
|
|
26358
|
+
d.fedIncoming.label,
|
|
26359
|
+
d.fedIncoming.edgeTypes,
|
|
26360
|
+
d.fedIncoming.cloudOnly
|
|
26361
|
+
) ?? { count: 0, total: 0 };
|
|
26362
|
+
return { count: count2, total, fraction: total === 0 ? 0 : count2 / total };
|
|
26363
|
+
}
|
|
25742
26364
|
if (d.fedEdges) {
|
|
25743
26365
|
const { count: count2, total } = store.recentEdgeAttrCoverage(
|
|
25744
26366
|
d.fedEdges.marker,
|
|
@@ -25790,7 +26412,7 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
|
|
|
25790
26412
|
if (d.configCounter && inv?.lastTotals?.[d.configCounter] === 0) verdict = "unconfigured";
|
|
25791
26413
|
else if ((backlog ?? 0) === 0 && (!hasInput && !d.inputOptional || missingRequiredNodes)) verdict = "no-input";
|
|
25792
26414
|
else if (!inv || inv.runs === 0) verdict = "never-invoked";
|
|
25793
|
-
else if (fed.fraction < (d
|
|
26415
|
+
else if (fed.fraction < minFractionOf(d)) verdict = "starved";
|
|
25794
26416
|
else if (stalled) verdict = "stalled";
|
|
25795
26417
|
else if (effectCount === 0) verdict = "no-effect";
|
|
25796
26418
|
else verdict = "ok";
|
|
@@ -25801,7 +26423,7 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
|
|
|
25801
26423
|
fedCount: fed.count,
|
|
25802
26424
|
fedTotal: fed.total,
|
|
25803
26425
|
fedFraction: fed.fraction,
|
|
25804
|
-
minFraction: d
|
|
26426
|
+
minFraction: minFractionOf(d),
|
|
25805
26427
|
...inv ? { lastInvokedMs: inv.lastTs } : {},
|
|
25806
26428
|
runs: inv?.runs ?? 0,
|
|
25807
26429
|
effectCount,
|
|
@@ -25813,6 +26435,9 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
|
|
|
25813
26435
|
};
|
|
25814
26436
|
});
|
|
25815
26437
|
}
|
|
26438
|
+
function minFractionOf(d) {
|
|
26439
|
+
return d.fedIncoming?.minFraction ?? d.fedEdges?.minFraction ?? d.fed?.minFraction ?? 0;
|
|
26440
|
+
}
|
|
25816
26441
|
function formatMechanismStatus(rows, nowMs) {
|
|
25817
26442
|
return rows.map((r) => {
|
|
25818
26443
|
const pct = (r.fedFraction * 100).toFixed(r.fedFraction < 0.01 ? 2 : 1);
|
|
@@ -26099,6 +26724,25 @@ var init_mechanism_liveness = __esm({
|
|
|
26099
26724
|
// reading is IDLE — correct, and it declares no backlog on purpose.
|
|
26100
26725
|
effectCounter: "alarms",
|
|
26101
26726
|
note: "steady-state IDLE is healthy; the row exists for its invocation age"
|
|
26727
|
+
},
|
|
26728
|
+
{
|
|
26729
|
+
id: "project-causal-sync",
|
|
26730
|
+
what: "lands the cloud project stratum's SOLVED_BY/FIXED_BY edges onto the knowledge the anchor feed mirrors",
|
|
26731
|
+
// PRODUCER: the anchor feed's causal leg — `fetchProjectAnchors` returns the
|
|
26732
|
+
// edges, `syncProjectAnchors` (apps/daemon/src/project-reanchor.ts) lands or
|
|
26733
|
+
// parks them, on the `anchor-pull` beat. CONSUMERS: every local walk that
|
|
26734
|
+
// crosses Problem→Solution — errata_trace/why/burst over the store, and the
|
|
26735
|
+
// passive priming block that renders a problem with its fix. Before
|
|
26736
|
+
// PJ-sync-causal the feed mirrored 5,054 cloud Solutions on the dev checkout
|
|
26737
|
+
// with not one incoming SOLVED_BY: this row would have read 0.0% for months.
|
|
26738
|
+
pass: "anchor-pull",
|
|
26739
|
+
fedIncoming: { label: "Solution", edgeTypes: ["SOLVED_BY", "FIXED_BY"], cloudOnly: true, minFraction: 0.5 },
|
|
26740
|
+
effectCounter: "edgesLanded",
|
|
26741
|
+
// Parked edges waiting on an endpoint — a flat, non-zero backlog is a stratum
|
|
26742
|
+
// whose other ends never arrive here (a cap, or a gate that refuses them).
|
|
26743
|
+
backlogCounter: "edgesPending",
|
|
26744
|
+
requiresNodes: ["Problem"],
|
|
26745
|
+
note: "an orphaned cloud Solution reads as a fix with no problem; the one-time causal re-walk lifts this after the server ships the leg"
|
|
26102
26746
|
}
|
|
26103
26747
|
];
|
|
26104
26748
|
COLUMN_INPUTS = {
|
|
@@ -26743,7 +27387,7 @@ function renderSnapshot(s) {
|
|
|
26743
27387
|
lines.push(` - previously resolved as: ${g.closed.description.slice(0, 120)} \u2014 \`${g.closed.id}\``);
|
|
26744
27388
|
if (g.solution) {
|
|
26745
27389
|
lines.push(
|
|
26746
|
-
` - the fix on record: ${g.solution.description.slice(0, 120)} \u2014 \`${g.solution.id}\` \xB7 fix still holds \u2192
|
|
27390
|
+
` - the fix on record: ${g.solution.description.slice(0, 120)} \u2014 \`${g.solution.id}\` \xB7 fix still holds \u2192 ${TAG_VERDICT_TOKENS.confirm(g.solution.id)} \xB7 hitting it again \u2192 flag it (a second independent witness reopens the close)`
|
|
26747
27391
|
);
|
|
26748
27392
|
} else {
|
|
26749
27393
|
lines.push(
|
|
@@ -26840,7 +27484,7 @@ function renderSnapshot(s) {
|
|
|
26840
27484
|
` - still open \u2014 did this work settle it? fixed \u2192 (fix:[${h.id}]) \xB7 not a real problem \u2192 an \`errata-resolved\` block with \`id: ` + h.id + "`, `disposition: false_positive`, `reason: \u2026` \xB7 still open \u2192 say nothing"
|
|
26841
27485
|
);
|
|
26842
27486
|
} else if (h.verdict === "foreign") {
|
|
26843
|
-
lines.push(` - open in another membrane \u2014 not yours to close:
|
|
27487
|
+
lines.push(` - open in another membrane \u2014 not yours to close: ${TAG_VERDICT_TOKENS.confirm(h.id)} it held \xB7 ${TAG_VERDICT_TOKENS.refute(h.id)}`);
|
|
26844
27488
|
}
|
|
26845
27489
|
}
|
|
26846
27490
|
}
|
|
@@ -26911,7 +27555,7 @@ function renderSnapshot(s) {
|
|
|
26911
27555
|
lines.push(` - \u2713 ${p.description}`);
|
|
26912
27556
|
for (const s2 of w.priors.solutionsByProblem[p.id] ?? []) {
|
|
26913
27557
|
lines.push(
|
|
26914
|
-
` - fixed by: ${s2.description} \u2014 if that fix did NOT hold, refute it:
|
|
27558
|
+
` - fixed by: ${s2.description} \u2014 if that fix did NOT hold, refute it: \`${TAG_VERDICT_TOKENS.failed(s2.id)}\``
|
|
26915
27559
|
);
|
|
26916
27560
|
}
|
|
26917
27561
|
}
|
|
@@ -28396,7 +29040,7 @@ var init_client = __esm({
|
|
|
28396
29040
|
"GET",
|
|
28397
29041
|
`/v2/projects/${encodeURIComponent(projectId)}/anchors?since=${String(Math.max(0, Math.floor(since)))}&limit=${String(limit)}`
|
|
28398
29042
|
);
|
|
28399
|
-
const { nodes } = this.toCastalia({ nodes: res.nodes ?? [], edges: [] });
|
|
29043
|
+
const { nodes, edges } = this.toCastalia({ nodes: res.nodes ?? [], edges: res.edges ?? [] });
|
|
28400
29044
|
const anchors = (res.anchors ?? []).map((a) => ({
|
|
28401
29045
|
from: a.fromCanonicalId,
|
|
28402
29046
|
toSymbolId: a.toSymbolId,
|
|
@@ -28404,7 +29048,7 @@ var init_client = __esm({
|
|
|
28404
29048
|
attrs: a.attrs ?? {},
|
|
28405
29049
|
stampedAt: typeof a.stampedAt === "number" ? a.stampedAt : 0
|
|
28406
29050
|
}));
|
|
28407
|
-
return { nodes, anchors, cursor: typeof res.cursor === "number" ? res.cursor : since };
|
|
29051
|
+
return { nodes, edges, causalLeg: Array.isArray(res.edges), anchors, cursor: typeof res.cursor === "number" ? res.cursor : since };
|
|
28408
29052
|
}
|
|
28409
29053
|
/** Pull cloud-induced skills + the session-bootstrap prime payload. `seed` is the
|
|
28410
29054
|
* canonical ids of the agent's recent problems — the cloud ranks the skills whose
|
|
@@ -33885,7 +34529,7 @@ function linkBullet(ref) {
|
|
|
33885
34529
|
` \xB7 ${TAG_EXAMPLE.package()} \u2014 the PUBLIC package it's about, dependency or not`,
|
|
33886
34530
|
` \xB7 ${TAG_EXAMPLE.component()} \u2014 the framework/product unit`,
|
|
33887
34531
|
` \xB7 (aids:[${ref}],\u2026) \u2014 other problems your fix might also resolve (hypothesis)`,
|
|
33888
|
-
` \xB7 your fix vs a shown solution:
|
|
34532
|
+
` \xB7 your fix vs a shown solution: ${TAG_EXAMPLE.buildsOn(ref)} \xB7 ${TAG_EXAMPLE.supersedes(ref)} \xB7 ${TAG_EXAMPLE.alternative("h")} \u2014 pick one`
|
|
33889
34533
|
].join("\n");
|
|
33890
34534
|
}
|
|
33891
34535
|
function verdictBullet(ref) {
|
|
@@ -33916,75 +34560,13 @@ function buildAgentInstruction(opts = {}) {
|
|
|
33916
34560
|
tail
|
|
33917
34561
|
].join("\n");
|
|
33918
34562
|
}
|
|
33919
|
-
var TAG_EXAMPLE, TAG_OPENERS, GLOSS;
|
|
34563
|
+
var TAG_EXAMPLE, TAG_OPENERS, GLOSS, ALL_SIGNALS, TAG_TEMPLATES2;
|
|
33920
34564
|
var init_agent_signals = __esm({
|
|
33921
34565
|
"src/agent-signals.ts"() {
|
|
33922
34566
|
"use strict";
|
|
33923
|
-
|
|
33924
|
-
|
|
33925
|
-
|
|
33926
|
-
vulnerability: () => `[!vuln: who can do what; observed basis @ path:line]`,
|
|
33927
|
-
suspectedVulnerability: () => `[?vuln: consequence; missing check]`,
|
|
33928
|
-
vulnerabilityThread: () => `[!#v vuln: finding here]`,
|
|
33929
|
-
fix: (ref) => `(fix:[${ref}])`,
|
|
33930
|
-
// CONSTRAINT — the native capture path for a DIFFUSE problem (a constraint/tension/
|
|
33931
|
-
// conflict that shaped a decision). Free text, attaches to the decision sentence the
|
|
33932
|
-
// agent is already writing. Full rationale in the constraint note below + prior-tags.ts.
|
|
33933
|
-
constraint: () => `(constraint: the limitation that forced it)`,
|
|
33934
|
-
// TRIAGE — routes the problem/symptom in scope to its cause. `(cause:[handle])`
|
|
33935
|
-
// links to a cited RootCause/Solution node; `(cause: free text)` mints a RootCause
|
|
33936
|
-
// from the text. Harvested in prior-tags.ts → engine.ts (see the triage note below).
|
|
33937
|
-
triage: (ref) => `(cause:[${ref}])`,
|
|
33938
|
-
// Unlike a bare cause citation, this handle names the Problem being explained.
|
|
33939
|
-
triageExplain: (ref) => `(cause:[${ref}] the mechanism)`,
|
|
33940
|
-
// The MINT form — free-text cause that mints a RootCause. Prime-time surfacing
|
|
33941
|
-
// (recallForFile) pastes this next to an open Problem that has no cause yet, so the
|
|
33942
|
-
// diagnostic moment is cued when the agent is looking at the problem. Kept here so
|
|
33943
|
-
// the grammar can't drift from parseInlineTags' `(cause: …)` acceptance.
|
|
33944
|
-
triageMint: () => `(cause: why it happens)`,
|
|
33945
|
-
// THREAD forms — the witness-declared symptom↔cause/fix binding. A `#id` on the
|
|
33946
|
-
// flag names the diagnosis thread; the same `#id` on a later verb binds to it
|
|
33947
|
-
// explicitly (across sentences AND turns), replacing proximity guessing. Adjacent
|
|
33948
|
-
// tags never need one — the id is for diagnoses that unfold over distance.
|
|
33949
|
-
problemThread: () => `[!#slug one line on what's wrong]`,
|
|
33950
|
-
causeThread: () => `(cause:#slug the mechanism)`,
|
|
33951
|
-
fixThread: (thread = "slug") => `(fix:#${thread} what you changed)`,
|
|
33952
|
-
// ATTEMPT arc — what's being tried and what didn't work. A failed attempt is a
|
|
33953
|
-
// witnessed NEGATIVE result: it saves the next agent the same dead end.
|
|
33954
|
-
tried: () => `(tried: the approach you're attempting)`,
|
|
33955
|
-
failed: () => `(failed: what didn't work and the dead end it rules out)`,
|
|
33956
|
-
// LINK verbs (AC epic) — bind the problem in scope to CANONICAL priors and
|
|
33957
|
-
// abstractions. Multi-target by design: single links are weak; ~3 links to 3
|
|
33958
|
-
// DIFFERENT relevant priors is the target shape (see linkBullet).
|
|
33959
|
-
instance: (ref) => `(instance:[${ref}],[another],[a-third])`,
|
|
33960
|
-
pattern: () => `(pattern: name the general shape)`,
|
|
33961
|
-
// DOMAIN — the abstract area a problem is about; the concept layer an
|
|
33962
|
-
// anchor-less problem clusters on. Mints/resolves a Domain by name.
|
|
33963
|
-
domain: () => `(domain: The Area)`,
|
|
33964
|
-
// PACKAGE/COMPONENT — agent-named public anchors (OM-agent-anchors): the
|
|
33965
|
-
// package a problem is ABOUT (even when not a dependency) and the
|
|
33966
|
-
// framework/product-level unit it concerns. Public spine anchors → the
|
|
33967
|
-
// knowledge can cross to the collective.
|
|
33968
|
-
package: () => `(package: the-package-name)`,
|
|
33969
|
-
component: () => `(component: The Component)`,
|
|
33970
|
-
aids: (ref) => `(aids:[${ref}])`,
|
|
33971
|
-
// VERDICT (VS-verdict-tags) — a judgment on a SHOWN prior, distinct from leaning on it.
|
|
33972
|
-
// `confirm` rides the corroborate channel (it held); `refute` the contradict channel
|
|
33973
|
-
// (it's wrong / didn't hold) and REQUIRES a reason. This is the inline producer the
|
|
33974
|
-
// evidence channels lacked — refute sat dead (contradictionPressure 0) until now, while
|
|
33975
|
-
// lean-on corroboration lived, because only corroboration had an inline path. Grammar
|
|
33976
|
-
// single-sourced with parseInlineTags' CONFIRM_PREFIX/REFUTE_PREFIX.
|
|
33977
|
-
confirm: (ref) => `(confirm:[${ref}])`,
|
|
33978
|
-
refute: (ref) => `(refute:[${ref}] one line why)`,
|
|
33979
|
-
// RETRACT — "not a real problem": the errata-resolved block with a disposition
|
|
33980
|
-
// (parseDesignResolutions, turn.ts). No inline form exists; the block is the grammar.
|
|
33981
|
-
retract: (id) => ["```errata-resolved", `id: ${id}`, "disposition: false_positive", "reason: why it was never a real problem", "```"].join("\n")
|
|
33982
|
-
};
|
|
33983
|
-
TAG_OPENERS = [
|
|
33984
|
-
...new Set(
|
|
33985
|
-
Object.values(TAG_EXAMPLE).map((example) => /^(\([a-z][\w-]*:|\[[!?])/i.exec(example("x"))?.[1]?.toLowerCase()).filter((opener) => opener !== void 0)
|
|
33986
|
-
)
|
|
33987
|
-
];
|
|
34567
|
+
init_src2();
|
|
34568
|
+
TAG_EXAMPLE = TAG_EXAMPLES;
|
|
34569
|
+
TAG_OPENERS = TAG_GRAMMAR_OPENERS;
|
|
33988
34570
|
GLOSS = {
|
|
33989
34571
|
prior: "a shown prior helped, or you work in a primed language/package",
|
|
33990
34572
|
// "even in code you just wrote" names the implementation phase explicitly. Field
|
|
@@ -34021,6 +34603,12 @@ var init_agent_signals = __esm({
|
|
|
34021
34603
|
link: "the problem you flagged is an instance of priors/abstractions you can name \u2014 (instance:[h1],[h2],\u2026) / (pattern: \u2026) / (aids:[h]); rendered whole via linkBullet",
|
|
34022
34604
|
verdict: "you can judge a prior we SHOWED you \u2014 confirm it if it held, refute it (with why) if it didn't; rendered whole via verdictBullet"
|
|
34023
34605
|
};
|
|
34606
|
+
ALL_SIGNALS = ["prior", "problem", "vulnerability", "domain", "fix", "constraint", "triage", "attempt", "link", "verdict"];
|
|
34607
|
+
TAG_TEMPLATES2 = deriveTagTemplates([
|
|
34608
|
+
...tagGrammarCopy(),
|
|
34609
|
+
...["its-handle", "its-id"].map((referent) => buildAgentInstruction({ signals: ALL_SIGNALS, referent })),
|
|
34610
|
+
buildFileRecallInstruction()
|
|
34611
|
+
]);
|
|
34024
34612
|
}
|
|
34025
34613
|
});
|
|
34026
34614
|
|
|
@@ -75835,8 +76423,8 @@ var init_report_render = __esm({
|
|
|
75835
76423
|
|
|
75836
76424
|
// src/cli.ts
|
|
75837
76425
|
init_src6();
|
|
75838
|
-
import { closeSync as closeSync3, existsSync as existsSync40, openSync as openSync3, readFileSync as
|
|
75839
|
-
import { join as
|
|
76426
|
+
import { closeSync as closeSync3, existsSync as existsSync40, openSync as openSync3, readFileSync as readFileSync43, renameSync as renameSync8, statSync as statSync13 } from "node:fs";
|
|
76427
|
+
import { join as join50, resolve as pathResolve2 } from "node:path";
|
|
75840
76428
|
import { spawn as spawn5 } from "node:child_process";
|
|
75841
76429
|
|
|
75842
76430
|
// src/daemon.ts
|
|
@@ -77301,9 +77889,9 @@ var NodeFsHandler = class {
|
|
|
77301
77889
|
if (this.fsw.closed) {
|
|
77302
77890
|
return;
|
|
77303
77891
|
}
|
|
77304
|
-
const
|
|
77892
|
+
const dirname18 = sysPath.dirname(file2);
|
|
77305
77893
|
const basename10 = sysPath.basename(file2);
|
|
77306
|
-
const parent = this.fsw._getWatchedDir(
|
|
77894
|
+
const parent = this.fsw._getWatchedDir(dirname18);
|
|
77307
77895
|
let prevStats = stats;
|
|
77308
77896
|
if (parent.has(basename10))
|
|
77309
77897
|
return;
|
|
@@ -77330,7 +77918,7 @@ var NodeFsHandler = class {
|
|
|
77330
77918
|
prevStats = newStats2;
|
|
77331
77919
|
}
|
|
77332
77920
|
} catch (error48) {
|
|
77333
|
-
this.fsw._remove(
|
|
77921
|
+
this.fsw._remove(dirname18, basename10);
|
|
77334
77922
|
}
|
|
77335
77923
|
} else if (parent.has(basename10)) {
|
|
77336
77924
|
const at = newStats.atimeMs;
|
|
@@ -79560,26 +80148,14 @@ init_src5();
|
|
|
79560
80148
|
import { readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "node:fs";
|
|
79561
80149
|
var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
|
|
79562
80150
|
var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
|
|
79563
|
-
var HANDLE_RE2 =
|
|
79564
|
-
var PLACEHOLDER_HANDLES =
|
|
79565
|
-
"handle",
|
|
79566
|
-
"its-handle",
|
|
79567
|
-
"another",
|
|
79568
|
-
"a-third",
|
|
79569
|
-
"h",
|
|
79570
|
-
"h1",
|
|
79571
|
-
"h2",
|
|
79572
|
-
"id",
|
|
79573
|
-
"its-id",
|
|
79574
|
-
"a",
|
|
79575
|
-
"b"
|
|
79576
|
-
]);
|
|
80151
|
+
var HANDLE_RE2 = new RegExp(TAG_HANDLE_SOURCE, "gi");
|
|
80152
|
+
var PLACEHOLDER_HANDLES = TAG_PLACEHOLDER_HANDLES;
|
|
79577
80153
|
var isPlaceholderHandle = (h) => PLACEHOLDER_HANDLES.has(h.toLowerCase());
|
|
79578
80154
|
var FLAG_BODY_HANDLE_RE = /^(?:[a-z0-9]+(?:-[a-z0-9]+){2,}-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})$/i;
|
|
79579
80155
|
var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
|
|
79580
|
-
var CONSTRAINT_RE = /\(\s*constraint:\s*([^()\n]{8,}?)\s*\)/gi;
|
|
79581
80156
|
var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
|
|
79582
80157
|
var NEST2_UNIT = String.raw`(?:[^()\n]|\((?:[^()\n]|\([^()\n]*\))*\))`;
|
|
80158
|
+
var CONSTRAINT_RE = new RegExp(String.raw`\(\s*constraint:\s*(${NEST2_UNIT}{8,}?)\s*\)`, "gi");
|
|
79583
80159
|
var FIX_LONG_RE = new RegExp(String.raw`\(\s*fix:(?:#([a-z][\w-]{0,63}))?\s*(${NEST2_UNIT}{12,}?)\s*\)`, "gi");
|
|
79584
80160
|
var CAUSE_LONG_RE = new RegExp(String.raw`\(\s*cause:(?:#([a-z][\w-]{0,63}))?\s*(${NEST2_UNIT}{8,}?)\s*\)`, "gi");
|
|
79585
80161
|
var CONFIRM_LONG_RE = new RegExp(String.raw`\(\s*confirm:\s*(${NEST2_UNIT}{4,}?)\s*\)`, "gi");
|
|
@@ -79595,7 +80171,7 @@ var BRACKETED_TOKEN_RE = /\[[^\]\n]{1,120}\]/;
|
|
|
79595
80171
|
var CONFIRM_PREFIX = /^\s*confirm:\s*/i;
|
|
79596
80172
|
var REFUTE_PREFIX = /^\s*refute:\s*/i;
|
|
79597
80173
|
var REFUTE_REASON_MIN = 4;
|
|
79598
|
-
var PATTERN_RE =
|
|
80174
|
+
var PATTERN_RE = new RegExp(String.raw`\(\s*pattern:\s*(${NEST2_UNIT}{3,}?)\s*\)`, "gi");
|
|
79599
80175
|
var DOMAIN_RE = /\(\s*domain:\s*([^()\n]{2,}?)\s*\)/gi;
|
|
79600
80176
|
var PACKAGE_RE = /\(\s*package:\s*([^()\n]{2,}?)\s*\)/gi;
|
|
79601
80177
|
var COMPONENT_RE = /\(\s*component:\s*([^()\n]{2,}?)\s*\)/gi;
|
|
@@ -79688,6 +80264,10 @@ function deriveFixRationale(sentence, startIdx, endIdx) {
|
|
|
79688
80264
|
if (before.length >= FIX_RATIONALE_MIN) return before;
|
|
79689
80265
|
return fixRationaleAfter(sentence, endIdx);
|
|
79690
80266
|
}
|
|
80267
|
+
var TAG_GROUP_OPENER_RE = new RegExp(
|
|
80268
|
+
TAG_OPENERS.filter((o) => o.startsWith("(")).map((o) => String.raw`\(\s*${o.slice(1, -1).replace(/-/g, "\\-")}\s*:`).join("|"),
|
|
80269
|
+
"gi"
|
|
80270
|
+
);
|
|
79691
80271
|
var LEADING_OPENER_RE = new RegExp(String.raw`^(?:${RESIDUAL_OPENER_RE.source})(?:#[a-z][\w-]{0,63})?\s*`, "i");
|
|
79692
80272
|
var WRAPPER_PAIRS = [["(", ")"], ["[", "]"]];
|
|
79693
80273
|
var LEADING_HANDLES_RE = /^(?:\[[a-z0-9][\w-]{0,80}\]\s*,?\s*)+/i;
|
|
@@ -79826,19 +80406,41 @@ function addTagDispositions(a, b) {
|
|
|
79826
80406
|
function parseInlineTags(text) {
|
|
79827
80407
|
return parseInlineTagsWithDispositions(text).tags;
|
|
79828
80408
|
}
|
|
80409
|
+
function tagGroupSpans(line) {
|
|
80410
|
+
const spans = [];
|
|
80411
|
+
let after = 0;
|
|
80412
|
+
for (const m of line.matchAll(TAG_GROUP_OPENER_RE)) {
|
|
80413
|
+
const start2 = m.index;
|
|
80414
|
+
if (start2 < after) continue;
|
|
80415
|
+
let depth = 0;
|
|
80416
|
+
const limit = Math.min(line.length, start2 + 4e3);
|
|
80417
|
+
for (let i2 = start2; i2 < limit; i2++) {
|
|
80418
|
+
if (line[i2] === "(") depth++;
|
|
80419
|
+
else if (line[i2] === ")" && --depth === 0) {
|
|
80420
|
+
spans.push({ start: start2, end: i2 + 1 });
|
|
80421
|
+
after = i2 + 1;
|
|
80422
|
+
break;
|
|
80423
|
+
}
|
|
80424
|
+
}
|
|
80425
|
+
}
|
|
80426
|
+
return spans;
|
|
80427
|
+
}
|
|
79829
80428
|
function* captureSentences(text) {
|
|
79830
80429
|
for (const line of text.split(/\n+/)) {
|
|
79831
80430
|
if (line.length > 2e4) {
|
|
79832
80431
|
yield line;
|
|
79833
80432
|
continue;
|
|
79834
80433
|
}
|
|
79835
|
-
const flags2 = [
|
|
80434
|
+
const flags2 = [
|
|
80435
|
+
...[...flagScanView(line).matchAll(new RegExp(FLAG_RE.source, FLAG_RE.flags))].map((m) => ({ start: m.index, end: m.index + m[0].length })),
|
|
80436
|
+
...tagGroupSpans(line)
|
|
80437
|
+
].sort((a, b) => a.start - b.start);
|
|
79836
80438
|
let flag = 0;
|
|
79837
80439
|
let start2 = 0;
|
|
79838
80440
|
for (const boundary of line.matchAll(/(?<=[.!?])\s+(?!\(fix:)/g)) {
|
|
79839
80441
|
const index = boundary.index;
|
|
79840
80442
|
while (flags2[flag] && flags2[flag].end <= index) flag++;
|
|
79841
|
-
if (flags2
|
|
80443
|
+
if (flags2.slice(flag).some((f) => f.start < index && index < f.end)) continue;
|
|
79842
80444
|
yield line.slice(start2, index);
|
|
79843
80445
|
start2 = index + boundary[0].length;
|
|
79844
80446
|
}
|
|
@@ -79857,22 +80459,28 @@ function parseInlineTagsWithDispositions(text) {
|
|
|
79857
80459
|
continue;
|
|
79858
80460
|
}
|
|
79859
80461
|
const seqStart = out2.length;
|
|
79860
|
-
const
|
|
79861
|
-
|
|
79862
|
-
|
|
80462
|
+
const original = raw2;
|
|
80463
|
+
const flagView = flagScanView(raw2);
|
|
80464
|
+
const flagSpans = [...flagView.matchAll(new RegExp(FLAG_RE.source, FLAG_RE.flags))].map((m) => [m.index, m.index + m[0].length]);
|
|
80465
|
+
const sentence = raw2.replace(/`[^`]*`/g, (m, at) => {
|
|
80466
|
+
if (!TAG_QUOTED_RE.test(m)) return m;
|
|
80467
|
+
if (!TAG_QUOTED_PAREN_RE.test(m)) {
|
|
79863
80468
|
dispositions.codeSpanNeutralized++;
|
|
79864
80469
|
return m;
|
|
79865
80470
|
}
|
|
80471
|
+
const inFlag = flagSpans.some(([a2, b]) => a2 < at && at < b);
|
|
80472
|
+
if (!inFlag && !/\[[!?]/.test(m) && !quotesOnlyTemplateTags(m, TAG_TEMPLATES2)) return m;
|
|
79866
80473
|
dispositions.codeSpanNeutralized++;
|
|
79867
|
-
return " ";
|
|
80474
|
+
return m.replace(/[()[\]]/g, " ");
|
|
79868
80475
|
});
|
|
79869
|
-
const sfield =
|
|
80476
|
+
const sfield = raw2.replace(/\s+/g, " ").trim().slice(0, 160);
|
|
79870
80477
|
const citeMatched = /* @__PURE__ */ new Set();
|
|
79871
|
-
const
|
|
80478
|
+
const codeOnly = [...sentence.matchAll(/`[^`]*`/g)].filter((m) => !TAG_QUOTED_PAREN_RE.test(m[0])).map((m) => [m.index, m.index + m[0].length]);
|
|
79872
80479
|
CITE_GROUP_RE.lastIndex = 0;
|
|
79873
80480
|
let g;
|
|
79874
80481
|
while ((g = CITE_GROUP_RE.exec(sentence)) !== null) {
|
|
79875
80482
|
citeMatched.add(g.index);
|
|
80483
|
+
if (codeOnly.some(([a2, b]) => a2 < g.index && g.index < b)) continue;
|
|
79876
80484
|
let content = g[1];
|
|
79877
80485
|
if (/^\s*pattern:/i.test(content)) continue;
|
|
79878
80486
|
if (/^\s*failed:/i.test(content)) continue;
|
|
@@ -79957,6 +80565,7 @@ function parseInlineTagsWithDispositions(text) {
|
|
|
79957
80565
|
let h;
|
|
79958
80566
|
let emittedHandle = false;
|
|
79959
80567
|
while ((h = HANDLE_RE2.exec(content)) !== null) {
|
|
80568
|
+
if (content[h.index + h[0].length] === "(") continue;
|
|
79960
80569
|
const handle2 = h[1] ?? h[2];
|
|
79961
80570
|
if (handle2 && isPlaceholderHandle(handle2)) {
|
|
79962
80571
|
dispositions.placeholderEcho++;
|
|
@@ -80062,10 +80671,9 @@ function parseInlineTagsWithDispositions(text) {
|
|
|
80062
80671
|
}
|
|
80063
80672
|
}
|
|
80064
80673
|
FLAG_RE.lastIndex = 0;
|
|
80065
|
-
const flagView = flagScanView(sentence);
|
|
80066
80674
|
let f;
|
|
80067
80675
|
while ((f = FLAG_RE.exec(flagView)) !== null) {
|
|
80068
|
-
f[3] =
|
|
80676
|
+
f[3] = original.slice(...f.indices[3]);
|
|
80069
80677
|
const flagThread = f[2];
|
|
80070
80678
|
const raw3 = f[3].trim();
|
|
80071
80679
|
if (/^vuln\b/i.test(raw3)) {
|
|
@@ -85224,7 +85832,7 @@ function createWatchBreaker(deps) {
|
|
|
85224
85832
|
}
|
|
85225
85833
|
|
|
85226
85834
|
// src/engine.ts
|
|
85227
|
-
var DAEMON_VERSION = true ? "2.0.22-dev.
|
|
85835
|
+
var DAEMON_VERSION = true ? "2.0.22-dev.4164" : "2.0.0-alpha.0";
|
|
85228
85836
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
85229
85837
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
85230
85838
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -88350,7 +88958,7 @@ function invalidateInstanceReceipt(current, destination, failedId, mirrorLegacy)
|
|
|
88350
88958
|
// src/multi.ts
|
|
88351
88959
|
init_dist();
|
|
88352
88960
|
init_src5();
|
|
88353
|
-
import { existsSync as existsSync34, writeFileSync as
|
|
88961
|
+
import { existsSync as existsSync34, writeFileSync as writeFileSync27 } from "node:fs";
|
|
88354
88962
|
import { resolve as pathResolve } from "node:path";
|
|
88355
88963
|
|
|
88356
88964
|
// src/principle-sync.ts
|
|
@@ -89840,7 +90448,6 @@ function liveCloudClient(src) {
|
|
|
89840
90448
|
init_identity2();
|
|
89841
90449
|
|
|
89842
90450
|
// src/project-hydrate.ts
|
|
89843
|
-
init_src11();
|
|
89844
90451
|
init_profile2();
|
|
89845
90452
|
|
|
89846
90453
|
// src/project-reanchor.ts
|
|
@@ -89915,6 +90522,62 @@ async function syncHistoryCorrections(opts) {
|
|
|
89915
90522
|
}
|
|
89916
90523
|
}
|
|
89917
90524
|
|
|
90525
|
+
// src/project-reanchor.ts
|
|
90526
|
+
init_paths();
|
|
90527
|
+
|
|
90528
|
+
// src/project-sync-landing.ts
|
|
90529
|
+
init_src11();
|
|
90530
|
+
function landCloudNode(store, n, isOwnTwin) {
|
|
90531
|
+
if (store.getNode(n.id)) return "present";
|
|
90532
|
+
if (isOwnTwin) return "own";
|
|
90533
|
+
store.mergeNode(n);
|
|
90534
|
+
return "landed";
|
|
90535
|
+
}
|
|
90536
|
+
function landCloudEdge(store, e, from, to) {
|
|
90537
|
+
if (store.outEdges(from, [e.type]).some((x) => x.to === to)) return false;
|
|
90538
|
+
const id = from === e.from && to === e.to ? e.id : edgeId(from, e.type, to);
|
|
90539
|
+
if (store.getEdge(id)) return false;
|
|
90540
|
+
store.mergeEdge({ ...e, id, from, to, attrs: { ...e.attrs, source: "cloud" } });
|
|
90541
|
+
return true;
|
|
90542
|
+
}
|
|
90543
|
+
|
|
90544
|
+
// src/causal-edge-queue.ts
|
|
90545
|
+
import { readFileSync as readFileSync35, renameSync as renameSync5, writeFileSync as writeFileSync25 } from "node:fs";
|
|
90546
|
+
import { dirname as dirname13, join as join39 } from "node:path";
|
|
90547
|
+
var CAUSAL_EDGE_QUEUE_CAP = 5e3;
|
|
90548
|
+
var CAUSAL_EDGE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
90549
|
+
function causalEdgeQueuePath(workspaceConfigDir) {
|
|
90550
|
+
return join39(workspaceConfigDir, "causal-edge-queue.json");
|
|
90551
|
+
}
|
|
90552
|
+
function parkedEdgeKey(e) {
|
|
90553
|
+
return `${e.from}|${e.type}|${e.to}`;
|
|
90554
|
+
}
|
|
90555
|
+
function loadCausalEdgeQueue(path3) {
|
|
90556
|
+
let raw2;
|
|
90557
|
+
try {
|
|
90558
|
+
raw2 = JSON.parse(readFileSync35(path3, "utf8"));
|
|
90559
|
+
} catch {
|
|
90560
|
+
return [];
|
|
90561
|
+
}
|
|
90562
|
+
if (!Array.isArray(raw2)) return [];
|
|
90563
|
+
return raw2.filter(
|
|
90564
|
+
(p) => !!p && typeof p === "object" && typeof p.ts === "number" && typeof p.edge?.from === "string" && typeof p.edge?.to === "string" && typeof p.edge?.type === "string"
|
|
90565
|
+
);
|
|
90566
|
+
}
|
|
90567
|
+
function saveCausalEdgeQueue(path3, queue) {
|
|
90568
|
+
try {
|
|
90569
|
+
const tmp = join39(dirname13(path3), `.${Date.now()}.causal-edge-queue.tmp`);
|
|
90570
|
+
writeFileSync25(tmp, JSON.stringify(queue), "utf8");
|
|
90571
|
+
renameSync5(tmp, path3);
|
|
90572
|
+
} catch {
|
|
90573
|
+
}
|
|
90574
|
+
}
|
|
90575
|
+
function pruneCausalEdgeQueue(queue, now) {
|
|
90576
|
+
const live3 = queue.filter((p) => now - p.ts < CAUSAL_EDGE_TTL_MS);
|
|
90577
|
+
if (live3.length <= CAUSAL_EDGE_QUEUE_CAP) return live3;
|
|
90578
|
+
return [...live3].sort((a, b) => a.ts - b.ts).slice(live3.length - CAUSAL_EDGE_QUEUE_CAP);
|
|
90579
|
+
}
|
|
90580
|
+
|
|
89918
90581
|
// src/project-reanchor.ts
|
|
89919
90582
|
var DEFAULT_LIMIT = 50;
|
|
89920
90583
|
var ANCHOR_SYMBOL_KINDS2 = [
|
|
@@ -90114,10 +90777,12 @@ async function reanchorProject(opts) {
|
|
|
90114
90777
|
}
|
|
90115
90778
|
var SYNC_PAGE = 200;
|
|
90116
90779
|
var SYNC_MAX_PAGES = 25;
|
|
90780
|
+
var SYNC_EDGE_TYPES = new Set(PROJECT_SYNC_EDGE_TYPES);
|
|
90117
90781
|
async function syncProjectAnchors(opts) {
|
|
90118
90782
|
const { root, profile, store, cloud, salt } = opts;
|
|
90119
90783
|
if (!profile.projectId) return { synced: false, reason: "no-project" };
|
|
90120
90784
|
const projectId = profile.projectId;
|
|
90785
|
+
const clock = opts.now ?? Date.now;
|
|
90121
90786
|
const key = `${projectId}|${salt}`;
|
|
90122
90787
|
const reverse = cachedMap(
|
|
90123
90788
|
reverseCache,
|
|
@@ -90126,23 +90791,95 @@ async function syncProjectAnchors(opts) {
|
|
|
90126
90791
|
() => buildReverseSymbolMap({ store, salt, projectId })
|
|
90127
90792
|
);
|
|
90128
90793
|
const own = cachedMap(ownCache, store, salt, () => collectLastWinsYielding(ownKnowledgeEntries({ store, salt })));
|
|
90794
|
+
const resolveKnowledge = async (id) => store.getNode(id) ? id : lookupLive(store, own, id);
|
|
90795
|
+
const queuePath = opts.edgeQueuePath ?? causalEdgeQueuePath(workspacePaths(root).configDir);
|
|
90796
|
+
let parked = pruneCausalEdgeQueue(loadCausalEdgeQueue(queuePath), clock());
|
|
90797
|
+
let parkedDirty = false;
|
|
90798
|
+
const parkedKeys = new Set(parked.map((p) => parkedEdgeKey(p.edge)));
|
|
90129
90799
|
const limit = opts.limit ?? SYNC_PAGE;
|
|
90130
90800
|
const maxPages = opts.maxPages ?? SYNC_MAX_PAGES;
|
|
90131
90801
|
let anchors = 0;
|
|
90132
90802
|
let updated = 0;
|
|
90133
90803
|
let dropped = 0;
|
|
90134
90804
|
let landed = 0;
|
|
90135
|
-
let
|
|
90805
|
+
let edgesLanded = 0;
|
|
90806
|
+
let edgesParked = 0;
|
|
90807
|
+
let edgesReplayed = 0;
|
|
90808
|
+
let persistedCursor = 0;
|
|
90809
|
+
let cursor = 0;
|
|
90810
|
+
let backfillPending = false;
|
|
90811
|
+
let backfillStarted = false;
|
|
90812
|
+
const settleEdges = async (incoming) => {
|
|
90813
|
+
for (const e of incoming) {
|
|
90814
|
+
if (!SYNC_EDGE_TYPES.has(e.type)) continue;
|
|
90815
|
+
const from = await resolveKnowledge(e.from);
|
|
90816
|
+
const to = from ? await resolveKnowledge(e.to) : null;
|
|
90817
|
+
const k = parkedEdgeKey(e);
|
|
90818
|
+
if (from && to) {
|
|
90819
|
+
if (from !== to && landCloudEdge(store, e, from, to)) edgesLanded++;
|
|
90820
|
+
if (parkedKeys.delete(k)) {
|
|
90821
|
+
parked = parked.filter((p) => parkedEdgeKey(p.edge) !== k);
|
|
90822
|
+
parkedDirty = true;
|
|
90823
|
+
}
|
|
90824
|
+
} else if (!parkedKeys.has(k)) {
|
|
90825
|
+
parkedKeys.add(k);
|
|
90826
|
+
parked.push({ edge: e, ts: clock() });
|
|
90827
|
+
parkedDirty = true;
|
|
90828
|
+
edgesParked++;
|
|
90829
|
+
}
|
|
90830
|
+
}
|
|
90831
|
+
if (parked.length === 0) return;
|
|
90832
|
+
const still = [];
|
|
90833
|
+
for (const p of parked) {
|
|
90834
|
+
const from = await resolveKnowledge(p.edge.from);
|
|
90835
|
+
const to = from ? await resolveKnowledge(p.edge.to) : null;
|
|
90836
|
+
if (from && to) {
|
|
90837
|
+
if (from !== to && landCloudEdge(store, p.edge, from, to)) edgesReplayed++;
|
|
90838
|
+
parkedKeys.delete(parkedEdgeKey(p.edge));
|
|
90839
|
+
parkedDirty = true;
|
|
90840
|
+
} else {
|
|
90841
|
+
still.push(p);
|
|
90842
|
+
}
|
|
90843
|
+
}
|
|
90844
|
+
parked = still;
|
|
90845
|
+
};
|
|
90846
|
+
const flushParked = () => {
|
|
90847
|
+
if (!parkedDirty) return;
|
|
90848
|
+
parked = pruneCausalEdgeQueue(parked, clock());
|
|
90849
|
+
saveCausalEdgeQueue(queuePath, parked);
|
|
90850
|
+
parkedDirty = false;
|
|
90851
|
+
};
|
|
90136
90852
|
try {
|
|
90137
90853
|
await syncHistoryCorrections({ root, profile, store, cloud, ...opts.correctionMirrors ? { mirrors: opts.correctionMirrors } : {} });
|
|
90854
|
+
persistedCursor = profile.projectAnchorCursor ?? 0;
|
|
90855
|
+
backfillPending = !profile.projectCausalBackfillAt;
|
|
90856
|
+
cursor = backfillPending ? 0 : persistedCursor;
|
|
90138
90857
|
for (let page = 0; page < maxPages; page++) {
|
|
90858
|
+
if (page > 0) await new Promise((r) => setImmediate(r));
|
|
90139
90859
|
const res = await cloud.getProjectAnchors(projectId, cursor, limit);
|
|
90860
|
+
if (backfillPending) {
|
|
90861
|
+
backfillPending = false;
|
|
90862
|
+
if (res.causalLeg) {
|
|
90863
|
+
profile.projectCausalBackfillAt = clock();
|
|
90864
|
+
profile.projectAnchorCursor = 0;
|
|
90865
|
+
saveProfile(root, profile);
|
|
90866
|
+
backfillStarted = persistedCursor > 0;
|
|
90867
|
+
} else if (cursor !== persistedCursor) {
|
|
90868
|
+
cursor = persistedCursor;
|
|
90869
|
+
page--;
|
|
90870
|
+
continue;
|
|
90871
|
+
}
|
|
90872
|
+
}
|
|
90140
90873
|
if (res.anchors.length === 0) break;
|
|
90141
90874
|
if ((await reverse.get()).size === 0 && (await reverse.refresh()).size === 0) {
|
|
90142
90875
|
return { synced: false, reason: "no-local-symbols" };
|
|
90143
90876
|
}
|
|
90144
|
-
const
|
|
90145
|
-
|
|
90877
|
+
for (const node2 of res.nodes) {
|
|
90878
|
+
if (store.getNode(node2.id)) continue;
|
|
90879
|
+
const ownTwin = await lookupLive(store, own, node2.id) !== null;
|
|
90880
|
+
if (landCloudNode(store, node2, ownTwin) === "landed") landed++;
|
|
90881
|
+
}
|
|
90882
|
+
const now = clock();
|
|
90146
90883
|
for (const a of res.anchors) {
|
|
90147
90884
|
if (a.type !== "ANCHORED_AT") continue;
|
|
90148
90885
|
const localTo = await lookupLive(store, reverse, a.toSymbolId);
|
|
@@ -90150,16 +90887,10 @@ async function syncProjectAnchors(opts) {
|
|
|
90150
90887
|
dropped++;
|
|
90151
90888
|
continue;
|
|
90152
90889
|
}
|
|
90153
|
-
|
|
90890
|
+
const from = await resolveKnowledge(a.from);
|
|
90154
90891
|
if (!from) {
|
|
90155
|
-
|
|
90156
|
-
|
|
90157
|
-
dropped++;
|
|
90158
|
-
continue;
|
|
90159
|
-
}
|
|
90160
|
-
store.mergeNode(node2);
|
|
90161
|
-
landed++;
|
|
90162
|
-
from = node2.id;
|
|
90892
|
+
dropped++;
|
|
90893
|
+
continue;
|
|
90163
90894
|
}
|
|
90164
90895
|
const existing = existingAnchor(store, from, localTo);
|
|
90165
90896
|
const id = existing?.id ?? edgeId(from, "ANCHORED_AT", localTo);
|
|
@@ -90191,6 +90922,8 @@ async function syncProjectAnchors(opts) {
|
|
|
90191
90922
|
if (existing) updated++;
|
|
90192
90923
|
else anchors++;
|
|
90193
90924
|
}
|
|
90925
|
+
await settleEdges(res.edges ?? []);
|
|
90926
|
+
flushParked();
|
|
90194
90927
|
const next = typeof res.cursor === "number" && res.cursor > cursor ? res.cursor : cursor;
|
|
90195
90928
|
if (next !== cursor) {
|
|
90196
90929
|
cursor = next;
|
|
@@ -90199,8 +90932,23 @@ async function syncProjectAnchors(opts) {
|
|
|
90199
90932
|
}
|
|
90200
90933
|
if (res.anchors.length < limit) break;
|
|
90201
90934
|
}
|
|
90202
|
-
|
|
90935
|
+
await settleEdges([]);
|
|
90936
|
+
flushParked();
|
|
90937
|
+
return {
|
|
90938
|
+
synced: true,
|
|
90939
|
+
anchors,
|
|
90940
|
+
updated,
|
|
90941
|
+
dropped,
|
|
90942
|
+
landed,
|
|
90943
|
+
cursor,
|
|
90944
|
+
edgesLanded,
|
|
90945
|
+
edgesParked,
|
|
90946
|
+
edgesReplayed,
|
|
90947
|
+
edgesPending: parked.length,
|
|
90948
|
+
backfillStarted
|
|
90949
|
+
};
|
|
90203
90950
|
} catch (err2) {
|
|
90951
|
+
flushParked();
|
|
90204
90952
|
return { synced: false, reason: "error", detail: err2 instanceof Error ? err2.message : String(err2) };
|
|
90205
90953
|
}
|
|
90206
90954
|
}
|
|
@@ -90218,24 +90966,16 @@ async function hydrateProject(opts) {
|
|
|
90218
90966
|
let landedNodes = 0;
|
|
90219
90967
|
let ownNodes = 0;
|
|
90220
90968
|
for (const n of res.nodes) {
|
|
90221
|
-
|
|
90222
|
-
if (own
|
|
90223
|
-
|
|
90224
|
-
continue;
|
|
90225
|
-
}
|
|
90226
|
-
store.mergeNode(n);
|
|
90227
|
-
landedNodes++;
|
|
90969
|
+
const landing = landCloudNode(store, n, own.has(n.id));
|
|
90970
|
+
if (landing === "own") ownNodes++;
|
|
90971
|
+
else if (landing === "landed") landedNodes++;
|
|
90228
90972
|
}
|
|
90229
90973
|
let landedEdges = 0;
|
|
90230
90974
|
for (const e of res.edges) {
|
|
90231
90975
|
const from = localId(e.from);
|
|
90232
90976
|
const to = localId(e.to);
|
|
90233
90977
|
if (!from || !to) continue;
|
|
90234
|
-
if (store
|
|
90235
|
-
const id = from === e.from && to === e.to ? e.id : edgeId(from, e.type, to);
|
|
90236
|
-
if (store.getEdge(id)) continue;
|
|
90237
|
-
store.mergeEdge({ ...e, id, from, to });
|
|
90238
|
-
landedEdges++;
|
|
90978
|
+
if (landCloudEdge(store, e, from, to)) landedEdges++;
|
|
90239
90979
|
}
|
|
90240
90980
|
profile.projectHydratedAt = Date.now();
|
|
90241
90981
|
saveProfile(root, profile);
|
|
@@ -90499,8 +91239,8 @@ async function syncHistoryRevisionPage(opts) {
|
|
|
90499
91239
|
init_src7();
|
|
90500
91240
|
init_src();
|
|
90501
91241
|
import { execFile as execFile6 } from "node:child_process";
|
|
90502
|
-
import { readFileSync as
|
|
90503
|
-
import { join as
|
|
91242
|
+
import { readFileSync as readFileSync36 } from "node:fs";
|
|
91243
|
+
import { join as join40 } from "node:path";
|
|
90504
91244
|
import { promisify as promisify5 } from "node:util";
|
|
90505
91245
|
|
|
90506
91246
|
// src/history-walk.ts
|
|
@@ -91052,7 +91792,7 @@ async function defaultGit(root, args2) {
|
|
|
91052
91792
|
function readIgnoreLines(root, profile) {
|
|
91053
91793
|
let lines = [];
|
|
91054
91794
|
try {
|
|
91055
|
-
lines =
|
|
91795
|
+
lines = readFileSync36(join40(root, ".errataignore"), "utf8").split("\n");
|
|
91056
91796
|
} catch {
|
|
91057
91797
|
}
|
|
91058
91798
|
return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
@@ -91628,8 +92368,8 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
|
|
|
91628
92368
|
init_cloud_auth();
|
|
91629
92369
|
import { createHash as createHash19 } from "node:crypto";
|
|
91630
92370
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
91631
|
-
import { existsSync as existsSync32, writeFileSync as
|
|
91632
|
-
import { join as
|
|
92371
|
+
import { existsSync as existsSync32, writeFileSync as writeFileSync26 } from "node:fs";
|
|
92372
|
+
import { join as join41 } from "node:path";
|
|
91633
92373
|
|
|
91634
92374
|
// src/device-poll.ts
|
|
91635
92375
|
var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
|
|
@@ -92088,9 +92828,9 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
|
|
|
92088
92828
|
delete nextProfile.projectLinkHold;
|
|
92089
92829
|
let wroteIgnore = false;
|
|
92090
92830
|
if (decision.writeIgnoreStarter !== false) {
|
|
92091
|
-
const target =
|
|
92831
|
+
const target = join41(root, ".errataignore");
|
|
92092
92832
|
if (!existsSync32(target)) {
|
|
92093
|
-
|
|
92833
|
+
writeFileSync26(target, IGNORE_STARTER, "utf8");
|
|
92094
92834
|
wroteIgnore = true;
|
|
92095
92835
|
}
|
|
92096
92836
|
}
|
|
@@ -92104,12 +92844,12 @@ init_registry();
|
|
|
92104
92844
|
// src/adopt.ts
|
|
92105
92845
|
init_git_remote();
|
|
92106
92846
|
import { existsSync as existsSync33 } from "node:fs";
|
|
92107
|
-
import { dirname as
|
|
92847
|
+
import { dirname as dirname14, join as join42 } from "node:path";
|
|
92108
92848
|
function findGitRoot(absPath) {
|
|
92109
92849
|
let dir = absPath;
|
|
92110
92850
|
for (let depth = 0; depth < 64; depth++) {
|
|
92111
|
-
if (existsSync33(
|
|
92112
|
-
const parent =
|
|
92851
|
+
if (existsSync33(join42(dir, ".git"))) return dir;
|
|
92852
|
+
const parent = dirname14(dir);
|
|
92113
92853
|
if (parent === dir) return null;
|
|
92114
92854
|
dir = parent;
|
|
92115
92855
|
}
|
|
@@ -92826,7 +93566,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
92826
93566
|
records.push(rec);
|
|
92827
93567
|
void ambientLinkAll();
|
|
92828
93568
|
try {
|
|
92829
|
-
|
|
93569
|
+
writeFileSync27(
|
|
92830
93570
|
rec.engine.paths.daemonLock,
|
|
92831
93571
|
daemonLockPayload({
|
|
92832
93572
|
pid: process.pid,
|
|
@@ -93205,7 +93945,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
93205
93945
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
93206
93946
|
try {
|
|
93207
93947
|
ensureDir(globalDir());
|
|
93208
|
-
|
|
93948
|
+
writeFileSync27(
|
|
93209
93949
|
lockPath,
|
|
93210
93950
|
daemonLockPayload({ pid: process.pid, webUiUrl: baseUrl, processStartedAt: PROCESS_STARTED_AT, entry: SELF_ENTRY, version: DAEMON_VERSION }),
|
|
93211
93951
|
"utf8"
|
|
@@ -93214,7 +93954,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
93214
93954
|
}
|
|
93215
93955
|
for (const r of records) {
|
|
93216
93956
|
try {
|
|
93217
|
-
|
|
93957
|
+
writeFileSync27(
|
|
93218
93958
|
r.engine.paths.daemonLock,
|
|
93219
93959
|
daemonLockPayload({
|
|
93220
93960
|
pid: process.pid,
|
|
@@ -93256,6 +93996,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
93256
93996
|
const lastAnchorPull = /* @__PURE__ */ new Map();
|
|
93257
93997
|
const pullProjectAnchors = async (r, client, salt) => {
|
|
93258
93998
|
const donePass = markPass(`anchor-pull:${r.engine.profile.name}`);
|
|
93999
|
+
const pullStartedAt = Date.now();
|
|
93259
94000
|
const beforeCorrections = r.engine.profile.projectHistoryCorrectionCursor ?? 0;
|
|
93260
94001
|
const sync = await syncProjectAnchors({
|
|
93261
94002
|
root: r.root,
|
|
@@ -93277,10 +94018,22 @@ async function startMultiDaemon(opts = {}) {
|
|
|
93277
94018
|
console.warn(`[errata] history revision reconciliation failed for ${r.engine.profile.name}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
93278
94019
|
}
|
|
93279
94020
|
if (sync.synced) {
|
|
93280
|
-
|
|
94021
|
+
appendPassLedger(r.engine.paths.configDir, "anchor-pull", Date.now() - pullStartedAt, {
|
|
94022
|
+
anchorsLanded: sync.anchors,
|
|
94023
|
+
anchorsUpdated: sync.updated,
|
|
94024
|
+
nodesLanded: sync.landed,
|
|
94025
|
+
edgesLanded: sync.edgesLanded + sync.edgesReplayed,
|
|
94026
|
+
edgesParked: sync.edgesParked,
|
|
94027
|
+
edgesReplayed: sync.edgesReplayed,
|
|
94028
|
+
edgesPending: sync.edgesPending
|
|
94029
|
+
});
|
|
94030
|
+
if (sync.backfillStarted) {
|
|
94031
|
+
console.log(`[errata] causal re-walk started for ${r.engine.profile.name} \u2014 anchor cursor reset to 0 once`);
|
|
94032
|
+
}
|
|
94033
|
+
if (sync.anchors + sync.updated + sync.landed + sync.edgesLanded + sync.edgesReplayed > 0) {
|
|
93281
94034
|
r.engine.markContextDirty();
|
|
93282
94035
|
console.log(
|
|
93283
|
-
`[errata] anchors pulled for ${r.engine.profile.name} \u2014 ${sync.anchors} new, ${sync.updated} re-versioned, ${sync.dropped} unresolved (${sync.landed} priors landed, cursor ${sync.cursor})`
|
|
94036
|
+
`[errata] anchors pulled for ${r.engine.profile.name} \u2014 ${sync.anchors} new, ${sync.updated} re-versioned, ${sync.dropped} unresolved (${sync.landed} priors landed, ${sync.edgesLanded + sync.edgesReplayed} causal edges landed, ${sync.edgesPending} parked, cursor ${sync.cursor})`
|
|
93284
94037
|
);
|
|
93285
94038
|
}
|
|
93286
94039
|
} else if (sync.reason === "error") {
|
|
@@ -94696,7 +95449,7 @@ import { spawnSync as spawnSync2 } from "node:child_process";
|
|
|
94696
95449
|
|
|
94697
95450
|
// src/codex-runtime.ts
|
|
94698
95451
|
import { readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
|
|
94699
|
-
import { join as
|
|
95452
|
+
import { join as join43 } from "node:path";
|
|
94700
95453
|
function resolveCodexExecutable(options = {}) {
|
|
94701
95454
|
const platform = options.platform ?? process.platform;
|
|
94702
95455
|
const env2 = options.env ?? process.env;
|
|
@@ -94711,13 +95464,13 @@ function resolveCodexExecutable(options = {}) {
|
|
|
94711
95464
|
};
|
|
94712
95465
|
for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
|
|
94713
95466
|
if (!dir.trim()) continue;
|
|
94714
|
-
const path3 =
|
|
95467
|
+
const path3 = join43(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
|
|
94715
95468
|
if (fileTime(path3) !== null) return path3;
|
|
94716
95469
|
}
|
|
94717
95470
|
if (!env2["LOCALAPPDATA"]) return "codex";
|
|
94718
|
-
const root =
|
|
95471
|
+
const root = join43(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
|
|
94719
95472
|
try {
|
|
94720
|
-
const candidates = readdirSync13(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
95473
|
+
const candidates = readdirSync13(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join43(root, entry.name, "codex.exe")).map((path3) => ({ path: path3, mtime: fileTime(path3) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
|
|
94721
95474
|
return candidates[0]?.path ?? "codex";
|
|
94722
95475
|
} catch {
|
|
94723
95476
|
return "codex";
|
|
@@ -94856,14 +95609,14 @@ async function diagnoseInstallation(cfg, dependencies) {
|
|
|
94856
95609
|
|
|
94857
95610
|
// src/codex-doctor.ts
|
|
94858
95611
|
import { spawn as spawn4 } from "node:child_process";
|
|
94859
|
-
import { readFileSync as
|
|
94860
|
-
import { join as
|
|
95612
|
+
import { readFileSync as readFileSync38, statSync as statSync11 } from "node:fs";
|
|
95613
|
+
import { join as join45 } from "node:path";
|
|
94861
95614
|
import { createInterface } from "node:readline";
|
|
94862
95615
|
|
|
94863
95616
|
// src/codex-hooks.ts
|
|
94864
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as
|
|
95617
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync37, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync28 } from "node:fs";
|
|
94865
95618
|
import { homedir as homedir7 } from "node:os";
|
|
94866
|
-
import { join as
|
|
95619
|
+
import { join as join44 } from "node:path";
|
|
94867
95620
|
|
|
94868
95621
|
// src/hook-commands.ts
|
|
94869
95622
|
function hookCurlCommand(port, path3 = "/api/hook") {
|
|
@@ -95067,34 +95820,34 @@ function buildCodexRelaySource(workspaceRoot) {
|
|
|
95067
95820
|
init_checkout_root();
|
|
95068
95821
|
var CODEX_HOOK_REVIEW_HELP = "Codex desktop: Settings > Hooks, select this project, expand each event and Trust the Errata hook. CLI users can use /hooks.";
|
|
95069
95822
|
function writeRelay(file2, source) {
|
|
95070
|
-
if (existsSync35(file2) &&
|
|
95823
|
+
if (existsSync35(file2) && readFileSync37(file2, "utf8") === source) return;
|
|
95071
95824
|
const temp = `${file2}.${process.pid}.tmp`;
|
|
95072
95825
|
try {
|
|
95073
|
-
|
|
95074
|
-
|
|
95826
|
+
writeFileSync28(temp, source, { encoding: "utf8", mode: 384 });
|
|
95827
|
+
renameSync6(temp, file2);
|
|
95075
95828
|
} finally {
|
|
95076
95829
|
if (existsSync35(temp)) unlinkSync5(temp);
|
|
95077
95830
|
}
|
|
95078
95831
|
}
|
|
95079
95832
|
function refreshCodexRelay(root) {
|
|
95080
|
-
const config2 =
|
|
95833
|
+
const config2 = join44(root, ".codex", "config.toml");
|
|
95081
95834
|
if (!existsSync35(config2)) return "absent";
|
|
95082
|
-
const existing =
|
|
95835
|
+
const existing = readFileSync37(config2, "utf8");
|
|
95083
95836
|
if (!existing.includes(CODEX_HOOKS_BEGIN) && !existing.includes(CODEX_HOOKS_END)) return "absent";
|
|
95084
95837
|
replaceCodexHooks(existing, "");
|
|
95085
|
-
const relay =
|
|
95086
|
-
const prior = existsSync35(relay) ?
|
|
95838
|
+
const relay = join44(root, ".codex", "hooks", "errata-relay.mjs");
|
|
95839
|
+
const prior = existsSync35(relay) ? readFileSync37(relay, "utf8") : "";
|
|
95087
95840
|
if (prior && !prior.startsWith("// errata-managed: regenerated by errata install-hooks codex")) {
|
|
95088
95841
|
throw new Error("Codex relay is not Errata-managed; preserved it. Run errata install-hooks codex to explicitly replace it.");
|
|
95089
95842
|
}
|
|
95090
95843
|
const source = buildCodexRelaySource(checkoutRootOf(root));
|
|
95091
95844
|
if (prior === source) return "current";
|
|
95092
|
-
mkdirSync9(
|
|
95845
|
+
mkdirSync9(join44(root, ".codex", "hooks"), { recursive: true });
|
|
95093
95846
|
writeRelay(relay, source);
|
|
95094
95847
|
return "updated";
|
|
95095
95848
|
}
|
|
95096
|
-
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] ||
|
|
95097
|
-
return existsSync35(
|
|
95849
|
+
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join44(homedir7(), ".codex")) {
|
|
95850
|
+
return existsSync35(join44(root, ".codex")) || existsSync35(codexHome);
|
|
95098
95851
|
}
|
|
95099
95852
|
function replaceCodexHooks(existing, block) {
|
|
95100
95853
|
const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
|
|
@@ -95110,14 +95863,14 @@ function replaceCodexHooks(existing, block) {
|
|
|
95110
95863
|
return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
|
|
95111
95864
|
}
|
|
95112
95865
|
function writeCodexHooks(root, port, nodePath = process.execPath) {
|
|
95113
|
-
const dir =
|
|
95114
|
-
const file2 =
|
|
95115
|
-
const relay =
|
|
95866
|
+
const dir = join44(root, ".codex");
|
|
95867
|
+
const file2 = join44(dir, "config.toml");
|
|
95868
|
+
const relay = join44(dir, "hooks", "errata-relay.mjs");
|
|
95116
95869
|
const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
|
|
95117
|
-
const final = replaceCodexHooks(existsSync35(file2) ?
|
|
95118
|
-
mkdirSync9(
|
|
95870
|
+
const final = replaceCodexHooks(existsSync35(file2) ? readFileSync37(file2, "utf8") : "", block);
|
|
95871
|
+
mkdirSync9(join44(dir, "hooks"), { recursive: true });
|
|
95119
95872
|
writeRelay(relay, buildCodexRelaySource(checkoutRootOf(root)));
|
|
95120
|
-
if (!existsSync35(file2) ||
|
|
95873
|
+
if (!existsSync35(file2) || readFileSync37(file2, "utf8") !== final) writeFileSync28(file2, final, "utf8");
|
|
95121
95874
|
return file2;
|
|
95122
95875
|
}
|
|
95123
95876
|
|
|
@@ -95126,7 +95879,7 @@ init_checkout_root();
|
|
|
95126
95879
|
function inspectCodexRelay(cwd) {
|
|
95127
95880
|
const root = nearestGitRoot(cwd) ?? cwd;
|
|
95128
95881
|
try {
|
|
95129
|
-
const source =
|
|
95882
|
+
const source = readFileSync38(join45(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
|
|
95130
95883
|
if (source === buildCodexRelaySource(checkoutRootOf(root))) {
|
|
95131
95884
|
return { id: "codex_relay", status: "pass", detail: "Installed Codex relay matches this Errata version" };
|
|
95132
95885
|
}
|
|
@@ -95137,8 +95890,8 @@ function inspectCodexRelay(cwd) {
|
|
|
95137
95890
|
function inspectCodexContext(cwd) {
|
|
95138
95891
|
const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
|
|
95139
95892
|
try {
|
|
95140
|
-
const file2 =
|
|
95141
|
-
if (statSync11(file2).size <= 128 * 1024 &&
|
|
95893
|
+
const file2 = join45(root, ".errata", "context.md");
|
|
95894
|
+
if (statSync11(file2).size <= 128 * 1024 && readFileSync38(file2, "utf8").trim()) {
|
|
95142
95895
|
return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
|
|
95143
95896
|
}
|
|
95144
95897
|
} catch {
|
|
@@ -95316,9 +96069,9 @@ function consolidationGapMs(lastPassMs, policy) {
|
|
|
95316
96069
|
|
|
95317
96070
|
// src/codex-context-plugin.ts
|
|
95318
96071
|
import { createHash as createHash20 } from "node:crypto";
|
|
95319
|
-
import { cpSync as cpSync2, existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as
|
|
96072
|
+
import { cpSync as cpSync2, existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync39, renameSync as renameSync7, writeFileSync as writeFileSync29 } from "node:fs";
|
|
95320
96073
|
import { homedir as homedir8 } from "node:os";
|
|
95321
|
-
import { join as
|
|
96074
|
+
import { join as join46 } from "node:path";
|
|
95322
96075
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
95323
96076
|
|
|
95324
96077
|
// ../../node_modules/.pnpm/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
|
|
@@ -96016,23 +96769,23 @@ var NAME = "errata-context";
|
|
|
96016
96769
|
var PREFIX2 = `./.errata/plugins/${NAME}/`;
|
|
96017
96770
|
var object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
96018
96771
|
function readText(file2) {
|
|
96019
|
-
return existsSync36(file2) ?
|
|
96772
|
+
return existsSync36(file2) ? readFileSync39(file2, "utf8") : "";
|
|
96020
96773
|
}
|
|
96021
96774
|
function writeChanged(file2, content) {
|
|
96022
96775
|
if (readText(file2) === content) return;
|
|
96023
96776
|
const temp = `${file2}.${process.pid}.tmp`;
|
|
96024
|
-
|
|
96025
|
-
|
|
96777
|
+
writeFileSync29(temp, content, "utf8");
|
|
96778
|
+
renameSync7(temp, file2);
|
|
96026
96779
|
}
|
|
96027
96780
|
function bundledContextPlugin() {
|
|
96028
96781
|
const packaged = fileURLToPath2(new URL("./resources/context-plugin/", import.meta.url));
|
|
96029
|
-
if (existsSync36(
|
|
96782
|
+
if (existsSync36(join46(packaged, ".codex-plugin/plugin.json"))) return packaged;
|
|
96030
96783
|
return fileURLToPath2(new URL("../dist/resources/context-plugin/", import.meta.url));
|
|
96031
96784
|
}
|
|
96032
96785
|
function refreshCodexContextPlugin(root) {
|
|
96033
|
-
const file2 =
|
|
96786
|
+
const file2 = join46(root, ".agents", "plugins", "marketplace.json");
|
|
96034
96787
|
if (!existsSync36(file2)) return false;
|
|
96035
|
-
const marketplace = JSON.parse(
|
|
96788
|
+
const marketplace = JSON.parse(readFileSync39(file2, "utf8"));
|
|
96036
96789
|
const entries = Array.isArray(marketplace.plugins) ? marketplace.plugins : [];
|
|
96037
96790
|
const entry = entries.map(object2).find((value) => value.name === NAME && String(object2(value.source).path).startsWith(PREFIX2));
|
|
96038
96791
|
if (!entry) return false;
|
|
@@ -96043,24 +96796,24 @@ function refreshCodexContextPlugin(root) {
|
|
|
96043
96796
|
function installCodexContextPlugin(root, options = {}) {
|
|
96044
96797
|
const bundle = options.bundle ?? bundledContextPlugin();
|
|
96045
96798
|
const manifest = JSON.parse(
|
|
96046
|
-
|
|
96799
|
+
readFileSync39(join46(bundle, ".codex-plugin/plugin.json"), "utf8")
|
|
96047
96800
|
);
|
|
96048
96801
|
if (manifest.name !== NAME || typeof manifest.version !== "string" || !/^[\w.-]+$/.test(manifest.version)) {
|
|
96049
96802
|
throw new Error("Invalid bundled Errata Context manifest.");
|
|
96050
96803
|
}
|
|
96051
|
-
const checksums =
|
|
96804
|
+
const checksums = readFileSync39(join46(bundle, "SHA256SUMS"), "utf8");
|
|
96052
96805
|
for (const line of checksums.trim().split("\n")) {
|
|
96053
96806
|
const match2 = /^([a-f0-9]{64}) ([\w./-]+)$/.exec(line);
|
|
96054
96807
|
if (!match2 || match2[2].startsWith("/") || match2[2].split("/").includes("..")) {
|
|
96055
96808
|
throw new Error("Invalid bundled Errata Context checksum manifest.");
|
|
96056
96809
|
}
|
|
96057
|
-
const actual = createHash20("sha256").update(
|
|
96810
|
+
const actual = createHash20("sha256").update(readFileSync39(join46(bundle, match2[2]))).digest("hex");
|
|
96058
96811
|
if (actual !== match2[1])
|
|
96059
96812
|
throw new Error(`Bundled Errata Context checksum mismatch: ${match2[2]}`);
|
|
96060
96813
|
}
|
|
96061
96814
|
const release = `${manifest.version}-${createHash20("sha256").update(checksums).digest("hex").slice(0, 12)}`;
|
|
96062
|
-
const plugin =
|
|
96063
|
-
const marketplaceFile =
|
|
96815
|
+
const plugin = join46(root, ".errata", "plugins", NAME, release);
|
|
96816
|
+
const marketplaceFile = join46(root, ".agents", "plugins", "marketplace.json");
|
|
96064
96817
|
const priorMarketplace = readText(marketplaceFile);
|
|
96065
96818
|
const marketplace = priorMarketplace ? JSON.parse(priorMarketplace) : {
|
|
96066
96819
|
name: "errata-local",
|
|
@@ -96081,12 +96834,12 @@ function installCodexContextPlugin(root, options = {}) {
|
|
|
96081
96834
|
);
|
|
96082
96835
|
}
|
|
96083
96836
|
const key = `${NAME}@${marketplace.name}`;
|
|
96084
|
-
const configFile =
|
|
96837
|
+
const configFile = join46(root, ".codex", "config.toml");
|
|
96085
96838
|
const config2 = readText(configFile);
|
|
96086
96839
|
const parsed = parse4(config2);
|
|
96087
96840
|
const plugins = object2(parsed.plugins);
|
|
96088
|
-
const codexHome = options.codexHome ?? process.env["CODEX_HOME"] ??
|
|
96089
|
-
const globalPlugins = object2(parse4(readText(
|
|
96841
|
+
const codexHome = options.codexHome ?? process.env["CODEX_HOME"] ?? join46(homedir8(), ".codex");
|
|
96842
|
+
const globalPlugins = object2(parse4(readText(join46(codexHome, "config.toml"))).plugins);
|
|
96090
96843
|
const disabledGlobally = Object.entries(globalPlugins).some(
|
|
96091
96844
|
([name2, value]) => (name2 === NAME || name2.startsWith(`${NAME}@`)) && object2(value).enabled === false
|
|
96092
96845
|
);
|
|
@@ -96110,13 +96863,13 @@ enabled = ${enabled}
|
|
|
96110
96863
|
mkdirSync10(plugin, { recursive: true });
|
|
96111
96864
|
cpSync2(bundle, plugin, { recursive: true });
|
|
96112
96865
|
writeChanged(
|
|
96113
|
-
|
|
96866
|
+
join46(plugin, ".mcp.json"),
|
|
96114
96867
|
JSON.stringify(
|
|
96115
96868
|
{
|
|
96116
96869
|
mcpServers: {
|
|
96117
96870
|
errata_context: {
|
|
96118
96871
|
command: options.nodePath ?? process.execPath,
|
|
96119
|
-
args: [
|
|
96872
|
+
args: [join46(plugin, "dist", "mcp-server.mjs")],
|
|
96120
96873
|
env: { ERRATA_WORKSPACE: root, ERRATA_CONTEXT_VERSION: manifest.version }
|
|
96121
96874
|
}
|
|
96122
96875
|
}
|
|
@@ -96125,8 +96878,8 @@ enabled = ${enabled}
|
|
|
96125
96878
|
2
|
|
96126
96879
|
) + "\n"
|
|
96127
96880
|
);
|
|
96128
|
-
mkdirSync10(
|
|
96129
|
-
mkdirSync10(
|
|
96881
|
+
mkdirSync10(join46(root, ".agents", "plugins"), { recursive: true });
|
|
96882
|
+
mkdirSync10(join46(root, ".codex"), { recursive: true });
|
|
96130
96883
|
writeChanged(marketplaceFile, JSON.stringify(marketplace, null, 2) + "\n");
|
|
96131
96884
|
writeChanged(configFile, nextConfig);
|
|
96132
96885
|
return { plugin, enabled, marketplace: marketplaceFile };
|
|
@@ -96134,15 +96887,15 @@ enabled = ${enabled}
|
|
|
96134
96887
|
|
|
96135
96888
|
// src/codex-hook-refresh.ts
|
|
96136
96889
|
init_checkout_root();
|
|
96137
|
-
import { existsSync as existsSync37, readdirSync as readdirSync14, readFileSync as
|
|
96138
|
-
import { dirname as
|
|
96890
|
+
import { existsSync as existsSync37, readdirSync as readdirSync14, readFileSync as readFileSync40 } from "node:fs";
|
|
96891
|
+
import { dirname as dirname15, join as join47, resolve as resolve8 } from "node:path";
|
|
96139
96892
|
init_registry();
|
|
96140
96893
|
function codexHookRoots(roots) {
|
|
96141
96894
|
const found = new Set(roots.map((root) => resolve8(root)));
|
|
96142
96895
|
for (const root of [...found]) {
|
|
96143
96896
|
const main2 = mainCheckoutOfWorktree(root) ?? root;
|
|
96144
96897
|
found.add(main2);
|
|
96145
|
-
const dir =
|
|
96898
|
+
const dir = join47(main2, ".git", "worktrees");
|
|
96146
96899
|
if (!existsSync37(dir)) continue;
|
|
96147
96900
|
let names;
|
|
96148
96901
|
try {
|
|
@@ -96152,7 +96905,7 @@ function codexHookRoots(roots) {
|
|
|
96152
96905
|
}
|
|
96153
96906
|
for (const name2 of names) {
|
|
96154
96907
|
try {
|
|
96155
|
-
const checkout =
|
|
96908
|
+
const checkout = dirname15(readFileSync40(join47(dir, name2, "gitdir"), "utf8").trim());
|
|
96156
96909
|
if (mainCheckoutOfWorktree(checkout) === main2) found.add(checkout);
|
|
96157
96910
|
} catch {
|
|
96158
96911
|
}
|
|
@@ -96174,9 +96927,9 @@ function refreshInstalledCodexRelays(roots = listWorkspaceEntries().map((entry)
|
|
|
96174
96927
|
}
|
|
96175
96928
|
|
|
96176
96929
|
// src/claude-statusline.ts
|
|
96177
|
-
import { existsSync as existsSync38, mkdirSync as mkdirSync11, readFileSync as
|
|
96930
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync11, readFileSync as readFileSync41, writeFileSync as writeFileSync30 } from "node:fs";
|
|
96178
96931
|
import { homedir as homedir9 } from "node:os";
|
|
96179
|
-
import { dirname as
|
|
96932
|
+
import { dirname as dirname16, join as join48 } from "node:path";
|
|
96180
96933
|
var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
|
|
96181
96934
|
import { readFileSync } from 'node:fs';
|
|
96182
96935
|
|
|
@@ -96224,8 +96977,8 @@ function isSameInstall(value, relay) {
|
|
|
96224
96977
|
return command.includes(relay.replace(/\\/g, "/").toLowerCase());
|
|
96225
96978
|
}
|
|
96226
96979
|
function userClaudeSettingsPath() {
|
|
96227
|
-
const base = process.env["CLAUDE_CONFIG_DIR"] ??
|
|
96228
|
-
return
|
|
96980
|
+
const base = process.env["CLAUDE_CONFIG_DIR"] ?? join48(homedir9(), ".claude");
|
|
96981
|
+
return join48(base, "settings.json");
|
|
96229
96982
|
}
|
|
96230
96983
|
function ensureUserStatusLine(opts) {
|
|
96231
96984
|
const env2 = opts.env ?? process.env;
|
|
@@ -96235,21 +96988,21 @@ function ensureUserStatusLine(opts) {
|
|
|
96235
96988
|
let settings = {};
|
|
96236
96989
|
if (existsSync38(settingsPath)) {
|
|
96237
96990
|
try {
|
|
96238
|
-
const parsed = JSON.parse(
|
|
96991
|
+
const parsed = JSON.parse(readFileSync41(settingsPath, "utf8"));
|
|
96239
96992
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
|
|
96240
96993
|
settings = parsed;
|
|
96241
96994
|
} catch {
|
|
96242
96995
|
return "unreadable";
|
|
96243
96996
|
}
|
|
96244
96997
|
}
|
|
96245
|
-
const relay =
|
|
96998
|
+
const relay = join48(opts.relayDir, STATUSLINE_RELAY_FILE);
|
|
96246
96999
|
const keep = (value) => value !== void 0 && (!isErrataStatusLine(value) || !isSameInstall(value, relay));
|
|
96247
97000
|
const ownMain = keep(settings["statusLine"]);
|
|
96248
97001
|
const ownRows = keep(settings["subagentStatusLine"]);
|
|
96249
97002
|
if (ownMain && ownRows) return "kept-own";
|
|
96250
97003
|
mkdirSync11(opts.relayDir, { recursive: true });
|
|
96251
|
-
if (!existsSync38(relay) ||
|
|
96252
|
-
|
|
97004
|
+
if (!existsSync38(relay) || readFileSync41(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
|
|
97005
|
+
writeFileSync30(relay, STATUSLINE_RELAY_SOURCE, "utf8");
|
|
96253
97006
|
}
|
|
96254
97007
|
const nodePath = opts.nodePath ?? process.execPath;
|
|
96255
97008
|
const next = {
|
|
@@ -96260,8 +97013,8 @@ function ensureUserStatusLine(opts) {
|
|
|
96260
97013
|
return ownMain ? "kept-own" : "unchanged";
|
|
96261
97014
|
}
|
|
96262
97015
|
Object.assign(settings, next);
|
|
96263
|
-
mkdirSync11(
|
|
96264
|
-
|
|
97016
|
+
mkdirSync11(dirname16(settingsPath), { recursive: true });
|
|
97017
|
+
writeFileSync30(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
96265
97018
|
return "installed";
|
|
96266
97019
|
}
|
|
96267
97020
|
function describeStatusLineOutcome(outcome) {
|
|
@@ -96281,8 +97034,8 @@ function describeStatusLineOutcome(outcome) {
|
|
|
96281
97034
|
|
|
96282
97035
|
// src/claude-mods.ts
|
|
96283
97036
|
import { createHash as createHash21 } from "node:crypto";
|
|
96284
|
-
import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as
|
|
96285
|
-
import { delimiter as delimiter2, dirname as
|
|
97037
|
+
import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as readFileSync42, readdirSync as readdirSync15, rmSync as rmSync4, statSync as statSync12, writeFileSync as writeFileSync31 } from "node:fs";
|
|
97038
|
+
import { delimiter as delimiter2, dirname as dirname17, join as join49, relative as relative8, resolve as resolve9, sep as sep5 } from "node:path";
|
|
96286
97039
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
96287
97040
|
var CLAUDE_PLUGIN_DIRS_ENV = "CLAUDE_CODE_PLUGIN_DIRS";
|
|
96288
97041
|
var HASH_FILE = ".errata-mod-hash";
|
|
@@ -96297,7 +97050,7 @@ function isEngineOwned(relPath) {
|
|
|
96297
97050
|
function listFiles(root, dir = root) {
|
|
96298
97051
|
const out2 = [];
|
|
96299
97052
|
for (const name2 of readdirSync15(dir)) {
|
|
96300
|
-
const abs =
|
|
97053
|
+
const abs = join49(dir, name2);
|
|
96301
97054
|
if (isEngineOwned(relative8(root, abs))) continue;
|
|
96302
97055
|
if (statSync12(abs).isDirectory()) out2.push(...listFiles(root, abs));
|
|
96303
97056
|
else out2.push(abs);
|
|
@@ -96309,14 +97062,14 @@ function modHash(dir) {
|
|
|
96309
97062
|
for (const abs of listFiles(dir).sort()) {
|
|
96310
97063
|
h.update(relative8(dir, abs).split(sep5).join("/"));
|
|
96311
97064
|
h.update("\0");
|
|
96312
|
-
h.update(
|
|
97065
|
+
h.update(readFileSync42(abs));
|
|
96313
97066
|
h.update("\0");
|
|
96314
97067
|
}
|
|
96315
97068
|
return h.digest("hex");
|
|
96316
97069
|
}
|
|
96317
97070
|
function bundledMods(bundleDir) {
|
|
96318
97071
|
if (!existsSync39(bundleDir)) return [];
|
|
96319
|
-
return readdirSync15(bundleDir).filter((name2) => existsSync39(
|
|
97072
|
+
return readdirSync15(bundleDir).filter((name2) => existsSync39(join49(bundleDir, name2, ".claude-plugin", "plugin.json")));
|
|
96320
97073
|
}
|
|
96321
97074
|
function sameDir(a, b) {
|
|
96322
97075
|
const norm = (p) => resolve9(p).replace(/[\\/]+$/, "").toLowerCase();
|
|
@@ -96333,7 +97086,7 @@ function off(env2) {
|
|
|
96333
97086
|
function readSettings(path3) {
|
|
96334
97087
|
if (!existsSync39(path3)) return {};
|
|
96335
97088
|
try {
|
|
96336
|
-
const parsed = JSON.parse(
|
|
97089
|
+
const parsed = JSON.parse(readFileSync42(path3, "utf8"));
|
|
96337
97090
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
96338
97091
|
return parsed;
|
|
96339
97092
|
} catch {
|
|
@@ -96357,13 +97110,13 @@ function currentDirs(settings) {
|
|
|
96357
97110
|
return raw2.split(delimiter2).map((s) => s.trim()).filter(Boolean);
|
|
96358
97111
|
}
|
|
96359
97112
|
function writeSettings(path3, settings) {
|
|
96360
|
-
mkdirSync12(
|
|
96361
|
-
|
|
97113
|
+
mkdirSync12(dirname17(path3), { recursive: true });
|
|
97114
|
+
writeFileSync31(path3, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
96362
97115
|
}
|
|
96363
97116
|
function ensureClaudeMods(opts) {
|
|
96364
97117
|
const env2 = opts.env ?? process.env;
|
|
96365
97118
|
const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
|
|
96366
|
-
const modsRoot =
|
|
97119
|
+
const modsRoot = join49(opts.installRoot, "claude-mods");
|
|
96367
97120
|
if (off(env2)) {
|
|
96368
97121
|
const settings2 = readSettings(settingsPath);
|
|
96369
97122
|
if (!settings2) return { kind: "unreadable" };
|
|
@@ -96380,14 +97133,14 @@ function ensureClaudeMods(opts) {
|
|
|
96380
97133
|
let changed = false;
|
|
96381
97134
|
const installed = [];
|
|
96382
97135
|
for (const name2 of names) {
|
|
96383
|
-
const src =
|
|
96384
|
-
const dest =
|
|
97136
|
+
const src = join49(bundleDir, name2);
|
|
97137
|
+
const dest = join49(modsRoot, name2);
|
|
96385
97138
|
const hash2 = modHash(src);
|
|
96386
|
-
const hashFile =
|
|
96387
|
-
if (!existsSync39(hashFile) ||
|
|
97139
|
+
const hashFile = join49(dest, HASH_FILE);
|
|
97140
|
+
if (!existsSync39(hashFile) || readFileSync42(hashFile, "utf8") !== hash2) {
|
|
96388
97141
|
rmSync4(dest, { recursive: true, force: true });
|
|
96389
97142
|
cpSync3(src, dest, { recursive: true, filter: (p) => !isEngineOwned(relative8(src, p)) });
|
|
96390
|
-
|
|
97143
|
+
writeFileSync31(hashFile, hash2, "utf8");
|
|
96391
97144
|
changed = true;
|
|
96392
97145
|
}
|
|
96393
97146
|
installed.push(dest);
|
|
@@ -96808,9 +97561,9 @@ function resolveHookPort(explicit) {
|
|
|
96808
97561
|
}
|
|
96809
97562
|
}
|
|
96810
97563
|
}
|
|
96811
|
-
const settingsPath =
|
|
97564
|
+
const settingsPath = join50(ROOT, ".claude", "settings.json");
|
|
96812
97565
|
try {
|
|
96813
|
-
if (existsSync40(settingsPath)) return installedHookPort(
|
|
97566
|
+
if (existsSync40(settingsPath)) return installedHookPort(readFileSync43(settingsPath, "utf8")) ?? 7891;
|
|
96814
97567
|
} catch {
|
|
96815
97568
|
}
|
|
96816
97569
|
return 7891;
|
|
@@ -96836,13 +97589,13 @@ async function cmdInit() {
|
|
|
96836
97589
|
console.log("");
|
|
96837
97590
|
console.log("installing harness hooks...");
|
|
96838
97591
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
96839
|
-
const { join:
|
|
97592
|
+
const { join: join51 } = await import("node:path");
|
|
96840
97593
|
try {
|
|
96841
97594
|
await installClaudeHooks(port);
|
|
96842
97595
|
} catch (err2) {
|
|
96843
97596
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
96844
97597
|
}
|
|
96845
|
-
if (existsSync41(
|
|
97598
|
+
if (existsSync41(join51(ROOT, ".cursor"))) {
|
|
96846
97599
|
try {
|
|
96847
97600
|
await installCursorMcpConfig();
|
|
96848
97601
|
} catch (err2) {
|
|
@@ -98064,7 +98817,7 @@ async function cmdReview() {
|
|
|
98064
98817
|
console.log("(review queue empty)");
|
|
98065
98818
|
return;
|
|
98066
98819
|
}
|
|
98067
|
-
const queue = JSON.parse(
|
|
98820
|
+
const queue = JSON.parse(readFileSync43(paths.reviewQueue, "utf8"));
|
|
98068
98821
|
if (queue.length === 0) {
|
|
98069
98822
|
console.log("(review queue empty)");
|
|
98070
98823
|
return;
|
|
@@ -98803,7 +99556,7 @@ async function gatherReportData(generatedAt) {
|
|
|
98803
99556
|
};
|
|
98804
99557
|
}
|
|
98805
99558
|
async function cmdReport(args2) {
|
|
98806
|
-
const { mkdirSync: mkdirSync13, writeFileSync:
|
|
99559
|
+
const { mkdirSync: mkdirSync13, writeFileSync: writeFileSync32 } = await import("node:fs");
|
|
98807
99560
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
98808
99561
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
98809
99562
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -98816,8 +99569,8 @@ async function cmdReport(args2) {
|
|
|
98816
99569
|
const outDir = workspacePaths(ROOT).configDir;
|
|
98817
99570
|
mkdirSync13(outDir, { recursive: true });
|
|
98818
99571
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
98819
|
-
for (const f of files)
|
|
98820
|
-
const indexPath =
|
|
99572
|
+
for (const f of files) writeFileSync32(join50(outDir, f.name), f.html, "utf8");
|
|
99573
|
+
const indexPath = join50(outDir, "report.html");
|
|
98821
99574
|
console.log(`report \u2192 ${indexPath}`);
|
|
98822
99575
|
console.log(
|
|
98823
99576
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -98873,7 +99626,7 @@ function spawnDaemonDetached(options = {}) {
|
|
|
98873
99626
|
try {
|
|
98874
99627
|
const logPath = daemonLogPath();
|
|
98875
99628
|
try {
|
|
98876
|
-
if (statSync13(logPath).size > 5 * 1024 * 1024)
|
|
99629
|
+
if (statSync13(logPath).size > 5 * 1024 * 1024) renameSync8(logPath, `${logPath}.1`);
|
|
98877
99630
|
} catch {
|
|
98878
99631
|
}
|
|
98879
99632
|
out2 = openSync3(logPath, "a");
|
|
@@ -98942,24 +99695,24 @@ async function cmdInstallHooks(args2) {
|
|
|
98942
99695
|
}
|
|
98943
99696
|
}
|
|
98944
99697
|
async function installOpencodePlugin(port) {
|
|
98945
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
98946
|
-
const { join:
|
|
98947
|
-
const dir =
|
|
99698
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
|
|
99699
|
+
const { join: join51 } = await import("node:path");
|
|
99700
|
+
const dir = join51(ROOT, ".opencode", "plugin");
|
|
98948
99701
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
98949
|
-
const file2 =
|
|
99702
|
+
const file2 = join51(dir, "inerrata.js");
|
|
98950
99703
|
if (existsSync41(file2)) {
|
|
98951
|
-
const head2 =
|
|
99704
|
+
const head2 = readFileSync44(file2, "utf8").split("\n")[0] ?? "";
|
|
98952
99705
|
if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
|
|
98953
99706
|
console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
|
|
98954
99707
|
process.exit(2);
|
|
98955
99708
|
}
|
|
98956
99709
|
}
|
|
98957
|
-
|
|
98958
|
-
const cfgFile =
|
|
99710
|
+
writeFileSync32(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
|
|
99711
|
+
const cfgFile = join51(ROOT, "opencode.json");
|
|
98959
99712
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
98960
99713
|
if (existsSync41(cfgFile)) {
|
|
98961
99714
|
try {
|
|
98962
|
-
cfg = JSON.parse(
|
|
99715
|
+
cfg = JSON.parse(readFileSync44(cfgFile, "utf8"));
|
|
98963
99716
|
} catch {
|
|
98964
99717
|
console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
|
|
98965
99718
|
process.exit(2);
|
|
@@ -98970,7 +99723,7 @@ async function installOpencodePlugin(port) {
|
|
|
98970
99723
|
if (!hadErrata) {
|
|
98971
99724
|
const inv = errataMcpInvocation();
|
|
98972
99725
|
cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
|
|
98973
|
-
|
|
99726
|
+
writeFileSync32(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
98974
99727
|
}
|
|
98975
99728
|
console.log(`installed OpenCode plugin \u2192 ${file2}`);
|
|
98976
99729
|
if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
|
|
@@ -99005,15 +99758,15 @@ function installClaudeMods() {
|
|
|
99005
99758
|
}
|
|
99006
99759
|
}
|
|
99007
99760
|
async function installClaudeHooks(port) {
|
|
99008
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
99009
|
-
const { join:
|
|
99010
|
-
const dir =
|
|
99761
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
|
|
99762
|
+
const { join: join51 } = await import("node:path");
|
|
99763
|
+
const dir = join51(ROOT, ".claude");
|
|
99011
99764
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
99012
|
-
const file2 =
|
|
99765
|
+
const file2 = join51(dir, "settings.json");
|
|
99013
99766
|
let settings = {};
|
|
99014
99767
|
if (existsSync41(file2)) {
|
|
99015
99768
|
try {
|
|
99016
|
-
settings = JSON.parse(
|
|
99769
|
+
settings = JSON.parse(readFileSync44(file2, "utf8"));
|
|
99017
99770
|
} catch {
|
|
99018
99771
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
99019
99772
|
process.exit(2);
|
|
@@ -99062,12 +99815,12 @@ async function installClaudeHooks(port) {
|
|
|
99062
99815
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
99063
99816
|
}
|
|
99064
99817
|
removeProjectStatusLine(settings);
|
|
99065
|
-
|
|
99818
|
+
writeFileSync32(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
99066
99819
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
99067
99820
|
console.log(` ${ensureStatusLine(port)}`);
|
|
99068
99821
|
console.log(` ${installClaudeMods().line}`);
|
|
99069
99822
|
await installClaudeMcpConfig();
|
|
99070
|
-
const claudeMd =
|
|
99823
|
+
const claudeMd = join51(ROOT, "CLAUDE.md");
|
|
99071
99824
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
99072
99825
|
if (recall.kind === "collision") {
|
|
99073
99826
|
console.warn(
|
|
@@ -99079,15 +99832,15 @@ async function installClaudeHooks(port) {
|
|
|
99079
99832
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
99080
99833
|
}
|
|
99081
99834
|
async function installClaudeMcpConfig() {
|
|
99082
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
99083
|
-
const { join:
|
|
99084
|
-
const file2 =
|
|
99085
|
-
const dir =
|
|
99835
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
|
|
99836
|
+
const { join: join51, dirname: dirname18 } = await import("node:path");
|
|
99837
|
+
const file2 = join51(ROOT, ".mcp.json");
|
|
99838
|
+
const dir = dirname18(file2);
|
|
99086
99839
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
99087
99840
|
let cfg = {};
|
|
99088
99841
|
if (existsSync41(file2)) {
|
|
99089
99842
|
try {
|
|
99090
|
-
cfg = JSON.parse(
|
|
99843
|
+
cfg = JSON.parse(readFileSync44(file2, "utf8"));
|
|
99091
99844
|
} catch {
|
|
99092
99845
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
99093
99846
|
process.exit(2);
|
|
@@ -99095,21 +99848,21 @@ async function installClaudeMcpConfig() {
|
|
|
99095
99848
|
}
|
|
99096
99849
|
cfg.mcpServers ??= {};
|
|
99097
99850
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
99098
|
-
|
|
99851
|
+
writeFileSync32(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
99099
99852
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
99100
99853
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
99101
99854
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
99102
99855
|
}
|
|
99103
99856
|
async function installCursorMcpConfig() {
|
|
99104
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
99105
|
-
const { join:
|
|
99106
|
-
const dir =
|
|
99857
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
|
|
99858
|
+
const { join: join51 } = await import("node:path");
|
|
99859
|
+
const dir = join51(ROOT, ".cursor");
|
|
99107
99860
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
99108
|
-
const file2 =
|
|
99861
|
+
const file2 = join51(dir, "mcp.json");
|
|
99109
99862
|
let cfg = {};
|
|
99110
99863
|
if (existsSync41(file2)) {
|
|
99111
99864
|
try {
|
|
99112
|
-
cfg = JSON.parse(
|
|
99865
|
+
cfg = JSON.parse(readFileSync44(file2, "utf8"));
|
|
99113
99866
|
} catch {
|
|
99114
99867
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
99115
99868
|
process.exit(2);
|
|
@@ -99117,7 +99870,7 @@ async function installCursorMcpConfig() {
|
|
|
99117
99870
|
}
|
|
99118
99871
|
cfg.mcpServers ??= {};
|
|
99119
99872
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
99120
|
-
|
|
99873
|
+
writeFileSync32(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
99121
99874
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
99122
99875
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
99123
99876
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -99128,7 +99881,7 @@ async function installCodexHooks(port) {
|
|
|
99128
99881
|
const gitRoot = nearestGitRoot(process.cwd());
|
|
99129
99882
|
const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
|
|
99130
99883
|
const file2 = writeCodexHooks(hookRoot, port);
|
|
99131
|
-
const instructions = writeManagedBlock(
|
|
99884
|
+
const instructions = writeManagedBlock(join50(hookRoot, "AGENTS.md"), {
|
|
99132
99885
|
body: AGENTS_POINTER_BODY,
|
|
99133
99886
|
stable: true
|
|
99134
99887
|
});
|
|
@@ -99574,9 +100327,9 @@ async function cmdDash(args2) {
|
|
|
99574
100327
|
await yieldToLoop2();
|
|
99575
100328
|
try {
|
|
99576
100329
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile, {
|
|
99577
|
-
atCommit: readGitRefState(
|
|
100330
|
+
atCommit: readGitRefState(join50(r.root, ".git")).sha ?? void 0
|
|
99578
100331
|
});
|
|
99579
|
-
const res = bleedRules(
|
|
100332
|
+
const res = bleedRules(join50(r.root, ".claude", "rules"), items);
|
|
99580
100333
|
if (res.written || res.pruned) {
|
|
99581
100334
|
console.log(
|
|
99582
100335
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|