kibi-runtime 2.7.0 → 2.9.0
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/dist/index.js
CHANGED
|
@@ -565,7 +565,7 @@ var init_contracts = __esm(() => {
|
|
|
565
565
|
"resolve_schema_reference",
|
|
566
566
|
"record_ontology_gap",
|
|
567
567
|
"review_nonlogical",
|
|
568
|
-
"
|
|
568
|
+
"replace_grounding"
|
|
569
569
|
]
|
|
570
570
|
},
|
|
571
571
|
recommendedPredicateSchema: { type: ["object", "null"] },
|
|
@@ -577,6 +577,10 @@ var init_contracts = __esm(() => {
|
|
|
577
577
|
},
|
|
578
578
|
existingGrounding: recordArray,
|
|
579
579
|
replacementPlan: { type: ["object", "null"] },
|
|
580
|
+
bindingHints: {
|
|
581
|
+
...recordArray,
|
|
582
|
+
description: "On provide_argument_bindings: one entry per unbound argument of the recommended candidate with its type, declared constants (allowedValues) when the vocabulary is closed, schema example values and the reason the current value was not accepted. Empty otherwise."
|
|
583
|
+
},
|
|
580
584
|
warnings: stringArray
|
|
581
585
|
}),
|
|
582
586
|
kb_plan_bootstrap: objectData({
|
|
@@ -27400,6 +27404,7 @@ var init_candidate_helpers = __esm(() => {
|
|
|
27400
27404
|
});
|
|
27401
27405
|
|
|
27402
27406
|
// ../cli/dist/operations/bootstrap/requirement-claims.js
|
|
27407
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
27403
27408
|
function normalizeClaimStatement(statement) {
|
|
27404
27409
|
return statement.replace(/^\s*(?:[-*+]|\d+[.)])\s+/, "").replace(/^\s*\[(?: |x)\]\s*/i, "").trim();
|
|
27405
27410
|
}
|
|
@@ -27446,6 +27451,205 @@ function claimFor(statement, source, confidence, provenance) {
|
|
|
27446
27451
|
provenance
|
|
27447
27452
|
};
|
|
27448
27453
|
}
|
|
27454
|
+
function snakeSegment(value) {
|
|
27455
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
27456
|
+
}
|
|
27457
|
+
function fitsAspect(words) {
|
|
27458
|
+
return words.length > 0 && words.length <= MAX_ASPECT_WORDS && words.join("_").length <= MAX_ASPECT_CHARS;
|
|
27459
|
+
}
|
|
27460
|
+
function trimStopWords(words) {
|
|
27461
|
+
let start = 0;
|
|
27462
|
+
let end = words.length;
|
|
27463
|
+
while (start < end && ASPECT_STOP_WORDS.has(words[start] ?? ""))
|
|
27464
|
+
start += 1;
|
|
27465
|
+
while (end > start && ASPECT_STOP_WORDS.has(words[end - 1] ?? ""))
|
|
27466
|
+
end -= 1;
|
|
27467
|
+
return words.slice(start, end);
|
|
27468
|
+
}
|
|
27469
|
+
function shortenSubjectAspect(aspect) {
|
|
27470
|
+
const words = aspect.split("_").filter(Boolean);
|
|
27471
|
+
if (fitsAspect(words))
|
|
27472
|
+
return aspect;
|
|
27473
|
+
const boundary = words.findIndex((word, index) => index > 0 && ASPECT_BOUNDARY_WORDS.has(word) && trimStopWords(words.slice(0, index)).length > 0);
|
|
27474
|
+
const head = trimStopWords(boundary < 0 ? words : words.slice(0, boundary));
|
|
27475
|
+
if (fitsAspect(head))
|
|
27476
|
+
return head.join("_");
|
|
27477
|
+
const content = head.filter((word) => !ASPECT_STOP_WORDS.has(word) && !(word.length > 4 && word.endsWith("ly")));
|
|
27478
|
+
if (fitsAspect(content))
|
|
27479
|
+
return content.join("_");
|
|
27480
|
+
const picked = Array.from(new Set([content[0], ...content.slice(-(MAX_ASPECT_WORDS - 2))])).filter((word) => typeof word === "string");
|
|
27481
|
+
while (picked.length > 1 && picked.join("_").length > MAX_ASPECT_CHARS)
|
|
27482
|
+
picked.splice(1, 1);
|
|
27483
|
+
const short = picked.join("_");
|
|
27484
|
+
return short.length > 0 ? short.slice(0, MAX_ASPECT_CHARS).replace(/_+$/, "") : (words[0] ?? aspect).slice(0, MAX_ASPECT_CHARS);
|
|
27485
|
+
}
|
|
27486
|
+
function withShortAspect(component, aspect) {
|
|
27487
|
+
const full = `${component}.${aspect}`;
|
|
27488
|
+
const short = shortenSubjectAspect(aspect);
|
|
27489
|
+
const candidate = `${component}.${short}`;
|
|
27490
|
+
if (!isConventionalSubjectKey(candidate))
|
|
27491
|
+
return {
|
|
27492
|
+
ok: false,
|
|
27493
|
+
reason: `subject key "${candidate}" does not follow component.aspect[.sub]`
|
|
27494
|
+
};
|
|
27495
|
+
return short === aspect ? { ok: true, subjectKey: candidate } : { ok: true, subjectKey: candidate, shortenedFrom: full };
|
|
27496
|
+
}
|
|
27497
|
+
function resolveBootstrapSubjectKey(subject, propertyKey, component) {
|
|
27498
|
+
const stripped = subject.trim().replace(/^(?:the|a|an)\s+/i, "");
|
|
27499
|
+
let key;
|
|
27500
|
+
try {
|
|
27501
|
+
key = normalizeSubjectKey2(stripped);
|
|
27502
|
+
} catch {
|
|
27503
|
+
return { ok: false, reason: `subject "${subject}" has no usable words` };
|
|
27504
|
+
}
|
|
27505
|
+
if (isConventionalSubjectKey(key))
|
|
27506
|
+
return { ok: true, subjectKey: key };
|
|
27507
|
+
const flat = key.replace(/\./g, "_");
|
|
27508
|
+
const comp = component === undefined ? "" : snakeSegment(component);
|
|
27509
|
+
const property = snakeSegment(propertyKey);
|
|
27510
|
+
if (comp) {
|
|
27511
|
+
const aspect = flat === comp ? property : flat.startsWith(`${comp}_`) ? flat.slice(comp.length + 1) : flat;
|
|
27512
|
+
return withShortAspect(comp, aspect);
|
|
27513
|
+
}
|
|
27514
|
+
if (/^[a-z][a-z0-9]*$/.test(flat) && property)
|
|
27515
|
+
return withShortAspect(flat, property);
|
|
27516
|
+
return {
|
|
27517
|
+
ok: false,
|
|
27518
|
+
reason: `subject key "${flat}" names no component, so it would violate component.aspect[.sub]`
|
|
27519
|
+
};
|
|
27520
|
+
}
|
|
27521
|
+
|
|
27522
|
+
class SubjectKeyRegistry {
|
|
27523
|
+
owners = new Map;
|
|
27524
|
+
assigned = new Map;
|
|
27525
|
+
assign(resolution) {
|
|
27526
|
+
const identity = resolution.shortenedFrom ?? resolution.subjectKey;
|
|
27527
|
+
const known = this.assigned.get(identity);
|
|
27528
|
+
if (known !== undefined)
|
|
27529
|
+
return { subjectKey: known };
|
|
27530
|
+
const owner = this.owners.get(resolution.subjectKey);
|
|
27531
|
+
if (owner === undefined || owner === identity) {
|
|
27532
|
+
this.owners.set(resolution.subjectKey, identity);
|
|
27533
|
+
this.assigned.set(identity, resolution.subjectKey);
|
|
27534
|
+
return { subjectKey: resolution.subjectKey };
|
|
27535
|
+
}
|
|
27536
|
+
const used = new Set(resolution.subjectKey.split(/[._]/));
|
|
27537
|
+
const fullWords = identity.split(".").slice(1).join("_").split("_");
|
|
27538
|
+
const qualifier = fullWords.find((word) => /^[a-z][a-z0-9]*$/.test(word) && !used.has(word) && !ASPECT_STOP_WORDS.has(word) && !ASPECT_BOUNDARY_WORDS.has(word) && !this.owners.has(`${resolution.subjectKey}.${word}`));
|
|
27539
|
+
const subjectKey = `${resolution.subjectKey}.${qualifier ?? `k${digest(identity)}`}`;
|
|
27540
|
+
this.owners.set(subjectKey, identity);
|
|
27541
|
+
this.assigned.set(identity, subjectKey);
|
|
27542
|
+
return { subjectKey, collidedWith: resolution.subjectKey };
|
|
27543
|
+
}
|
|
27544
|
+
}
|
|
27545
|
+
function digest(value) {
|
|
27546
|
+
return createHash15("sha256").update(value).digest("hex").slice(0, 6);
|
|
27547
|
+
}
|
|
27548
|
+
function planSubjectKey(subject, propertyKey, component, registry, location) {
|
|
27549
|
+
const resolved = resolveBootstrapSubjectKey(subject, propertyKey, component);
|
|
27550
|
+
if (!resolved.ok)
|
|
27551
|
+
return { resolution: resolved, diagnostics: [] };
|
|
27552
|
+
const diagnostics = [];
|
|
27553
|
+
const assigned = registry?.assign(resolved) ?? {
|
|
27554
|
+
subjectKey: resolved.subjectKey
|
|
27555
|
+
};
|
|
27556
|
+
if (resolved.shortenedFrom)
|
|
27557
|
+
diagnostics.push(`subject-key-shortened: claim at ${location} would have the subject key ${resolved.shortenedFrom}; its aspect is longer than ${MAX_ASPECT_WORDS} words or ${MAX_ASPECT_CHARS} characters, so the plan uses ${assigned.subjectKey}. Rename the subject after apply if another noun phrase fits better.`);
|
|
27558
|
+
if (assigned.collidedWith)
|
|
27559
|
+
diagnostics.push(`subject-key-disambiguated: claim at ${location} names a different subject than an earlier claim keyed ${assigned.collidedWith}, so the plan uses ${assigned.subjectKey} instead of reusing that key.`);
|
|
27560
|
+
return {
|
|
27561
|
+
resolution: {
|
|
27562
|
+
ok: true,
|
|
27563
|
+
subjectKey: assigned.subjectKey,
|
|
27564
|
+
...resolved.shortenedFrom ? { shortenedFrom: resolved.shortenedFrom } : {}
|
|
27565
|
+
},
|
|
27566
|
+
diagnostics
|
|
27567
|
+
};
|
|
27568
|
+
}
|
|
27569
|
+
var MAX_ASPECT_WORDS = 4, MAX_ASPECT_CHARS = 40, ASPECT_BOUNDARY_WORDS, ASPECT_STOP_WORDS;
|
|
27570
|
+
var init_requirement_claims = __esm(() => {
|
|
27571
|
+
init_strict_modeling();
|
|
27572
|
+
ASPECT_BOUNDARY_WORDS = new Set([
|
|
27573
|
+
"when",
|
|
27574
|
+
"whenever",
|
|
27575
|
+
"while",
|
|
27576
|
+
"if",
|
|
27577
|
+
"unless",
|
|
27578
|
+
"without",
|
|
27579
|
+
"after",
|
|
27580
|
+
"before",
|
|
27581
|
+
"until",
|
|
27582
|
+
"because",
|
|
27583
|
+
"once",
|
|
27584
|
+
"as",
|
|
27585
|
+
"by",
|
|
27586
|
+
"via",
|
|
27587
|
+
"during",
|
|
27588
|
+
"except",
|
|
27589
|
+
"so",
|
|
27590
|
+
"that",
|
|
27591
|
+
"which",
|
|
27592
|
+
"who",
|
|
27593
|
+
"where",
|
|
27594
|
+
"since",
|
|
27595
|
+
"for",
|
|
27596
|
+
"and",
|
|
27597
|
+
"or"
|
|
27598
|
+
]);
|
|
27599
|
+
ASPECT_STOP_WORDS = new Set([
|
|
27600
|
+
"a",
|
|
27601
|
+
"an",
|
|
27602
|
+
"the",
|
|
27603
|
+
"be",
|
|
27604
|
+
"is",
|
|
27605
|
+
"are",
|
|
27606
|
+
"was",
|
|
27607
|
+
"were",
|
|
27608
|
+
"been",
|
|
27609
|
+
"being",
|
|
27610
|
+
"to",
|
|
27611
|
+
"of",
|
|
27612
|
+
"in",
|
|
27613
|
+
"on",
|
|
27614
|
+
"at",
|
|
27615
|
+
"with",
|
|
27616
|
+
"from",
|
|
27617
|
+
"into",
|
|
27618
|
+
"its",
|
|
27619
|
+
"it",
|
|
27620
|
+
"their",
|
|
27621
|
+
"they",
|
|
27622
|
+
"them",
|
|
27623
|
+
"this",
|
|
27624
|
+
"these",
|
|
27625
|
+
"those",
|
|
27626
|
+
"can",
|
|
27627
|
+
"could",
|
|
27628
|
+
"will",
|
|
27629
|
+
"would",
|
|
27630
|
+
"may",
|
|
27631
|
+
"might",
|
|
27632
|
+
"must",
|
|
27633
|
+
"shall",
|
|
27634
|
+
"should",
|
|
27635
|
+
"do",
|
|
27636
|
+
"does",
|
|
27637
|
+
"has",
|
|
27638
|
+
"have",
|
|
27639
|
+
"had",
|
|
27640
|
+
"any",
|
|
27641
|
+
"all",
|
|
27642
|
+
"each",
|
|
27643
|
+
"every",
|
|
27644
|
+
"some",
|
|
27645
|
+
"only",
|
|
27646
|
+
"also",
|
|
27647
|
+
"then",
|
|
27648
|
+
"than",
|
|
27649
|
+
"not",
|
|
27650
|
+
"no"
|
|
27651
|
+
]);
|
|
27652
|
+
});
|
|
27449
27653
|
|
|
27450
27654
|
// ../cli/dist/operations/bootstrap/markdown-candidates.js
|
|
27451
27655
|
import path25 from "node:path";
|
|
@@ -27501,7 +27705,20 @@ function genericHeadingCandidate(item, heading, line, existingIds, minConfidence
|
|
|
27501
27705
|
]
|
|
27502
27706
|
};
|
|
27503
27707
|
}
|
|
27504
|
-
function
|
|
27708
|
+
function markdownComponentHint(relativePath) {
|
|
27709
|
+
const segments = relativePath.split(/[\\/]+/).filter((segment) => segment.length > 0);
|
|
27710
|
+
const stem = (segments.pop() ?? "").replace(/\.[^.]*$/, "");
|
|
27711
|
+
for (const name of [stem, ...segments.reverse()]) {
|
|
27712
|
+
const normalized = name.toLowerCase().replace(/^[._-]+/, "");
|
|
27713
|
+
if (!/^[a-z]/.test(normalized))
|
|
27714
|
+
continue;
|
|
27715
|
+
if (GENERIC_DOCUMENT_NAMES.has(normalized))
|
|
27716
|
+
continue;
|
|
27717
|
+
return normalized;
|
|
27718
|
+
}
|
|
27719
|
+
return;
|
|
27720
|
+
}
|
|
27721
|
+
function requirementCandidate(item, statement, line, heading, headingLine, existingIds, minConfidence, subjectKeys, diagnostics) {
|
|
27505
27722
|
const relativePath = item.relativePath ?? item.label;
|
|
27506
27723
|
const base = /\bshall\b/i.test(statement) ? 0.86 : /\bmust\b/i.test(statement) ? 0.84 : 0.78;
|
|
27507
27724
|
const confidence = Math.min(0.95, base + (heading && /requirements?|constraints?|polic(?:y|ies)|rules?/i.test(heading) ? 0.08 : 0));
|
|
@@ -27510,9 +27727,17 @@ function requirementCandidate(item, statement, line, heading, headingLine, exist
|
|
|
27510
27727
|
const claim = claimFor(statement, relativePath, confidence, `${relativePath}#L${line}`);
|
|
27511
27728
|
if (!claim)
|
|
27512
27729
|
return null;
|
|
27513
|
-
const
|
|
27730
|
+
const planned = planSubjectKey(claim.subjectKey, claim.propertyKey, markdownComponentHint(relativePath), subjectKeys, `${relativePath}#L${line}`);
|
|
27731
|
+
const subjectKey = planned.resolution;
|
|
27732
|
+
if (!subjectKey.ok)
|
|
27733
|
+
throw new Error(`${subjectKey.reason}; author it with kb_model and a component.aspect subjectKey`);
|
|
27734
|
+
const writeSet = buildStrictWriteSet({
|
|
27735
|
+
claim: { ...claim, subjectKey: subjectKey.subjectKey },
|
|
27736
|
+
statement
|
|
27737
|
+
});
|
|
27514
27738
|
if (!writeSet.isStrict)
|
|
27515
27739
|
return null;
|
|
27740
|
+
diagnostics.push(...planned.diagnostics);
|
|
27516
27741
|
return {
|
|
27517
27742
|
candidateId: `norm:${writeSet.req.id.toLowerCase()}`,
|
|
27518
27743
|
entityType: "req",
|
|
@@ -27533,7 +27758,7 @@ function requirementCandidate(item, statement, line, heading, headingLine, exist
|
|
|
27533
27758
|
applyPlan: strictPlan(writeSet).map((step) => step.type === "req" ? withDocumentBody(step, provenanceRequirementBody(statement, bootstrapProvenance("generic markdown", `${relativePath} line ${line}${heading ? ` under the heading "${heading}"` : ""}`, confidence), `${relativePath}#L${line}`)) : step)
|
|
27534
27759
|
};
|
|
27535
27760
|
}
|
|
27536
|
-
function markdownCandidates(item, existingIds, minConfidence) {
|
|
27761
|
+
function markdownCandidates(item, existingIds, minConfidence, subjectKeys) {
|
|
27537
27762
|
const candidates = [];
|
|
27538
27763
|
const sourceOnlySignals = [];
|
|
27539
27764
|
const diagnostics = [];
|
|
@@ -27562,7 +27787,7 @@ function markdownCandidates(item, existingIds, minConfidence) {
|
|
|
27562
27787
|
if (!statement || !/\b(must|shall|should)\b/i.test(statement))
|
|
27563
27788
|
continue;
|
|
27564
27789
|
try {
|
|
27565
|
-
const candidate = requirementCandidate(item, statement, index + 1, heading, headingLine, existingIds, minConfidence);
|
|
27790
|
+
const candidate = requirementCandidate(item, statement, index + 1, heading, headingLine, existingIds, minConfidence, subjectKeys, diagnostics);
|
|
27566
27791
|
if (candidate) {
|
|
27567
27792
|
if (!candidate.applyPlan.some((payload) => payload.type === "req" && existingIds.has(String(payload.id))))
|
|
27568
27793
|
candidates.push(candidate);
|
|
@@ -27589,9 +27814,33 @@ function markdownCandidates(item, existingIds, minConfidence) {
|
|
|
27589
27814
|
}
|
|
27590
27815
|
return { candidates, sourceOnlySignals, diagnostics, suppressed: [] };
|
|
27591
27816
|
}
|
|
27817
|
+
var GENERIC_DOCUMENT_NAMES;
|
|
27592
27818
|
var init_markdown_candidates = __esm(() => {
|
|
27593
27819
|
init_strict_modeling();
|
|
27594
27820
|
init_candidate_helpers();
|
|
27821
|
+
init_requirement_claims();
|
|
27822
|
+
GENERIC_DOCUMENT_NAMES = new Set([
|
|
27823
|
+
"readme",
|
|
27824
|
+
"index",
|
|
27825
|
+
"overview",
|
|
27826
|
+
"requirements",
|
|
27827
|
+
"requirement",
|
|
27828
|
+
"spec",
|
|
27829
|
+
"specs",
|
|
27830
|
+
"specification",
|
|
27831
|
+
"notes",
|
|
27832
|
+
"changelog",
|
|
27833
|
+
"contributing",
|
|
27834
|
+
"agents",
|
|
27835
|
+
"claude",
|
|
27836
|
+
"todo",
|
|
27837
|
+
"docs",
|
|
27838
|
+
"doc",
|
|
27839
|
+
"documentation",
|
|
27840
|
+
"src",
|
|
27841
|
+
"packages",
|
|
27842
|
+
"github"
|
|
27843
|
+
]);
|
|
27595
27844
|
});
|
|
27596
27845
|
|
|
27597
27846
|
// ../cli/dist/operations/bootstrap/candidates.js
|
|
@@ -27669,7 +27918,7 @@ function providerCandidate(item, existingIds, minConfidence) {
|
|
|
27669
27918
|
}
|
|
27670
27919
|
];
|
|
27671
27920
|
}
|
|
27672
|
-
function buildBootstrapCandidates(evidence, existingIds, minConfidence, includeGenericMarkdown) {
|
|
27921
|
+
function buildBootstrapCandidates(evidence, existingIds, minConfidence, includeGenericMarkdown, subjectKeys) {
|
|
27673
27922
|
const candidates = [];
|
|
27674
27923
|
const sourceOnlySignals = [];
|
|
27675
27924
|
const diagnostics = [];
|
|
@@ -27692,7 +27941,7 @@ function buildBootstrapCandidates(evidence, existingIds, minConfidence, includeG
|
|
|
27692
27941
|
}
|
|
27693
27942
|
}
|
|
27694
27943
|
if (item.kind === "generic_markdown" && includeGenericMarkdown) {
|
|
27695
|
-
const built = markdownCandidates(item, existingIds, minConfidence);
|
|
27944
|
+
const built = markdownCandidates(item, existingIds, minConfidence, subjectKeys);
|
|
27696
27945
|
candidates.push(...built.candidates);
|
|
27697
27946
|
sourceOnlySignals.push(...built.sourceOnlySignals);
|
|
27698
27947
|
diagnostics.push(...built.diagnostics);
|
|
@@ -27940,13 +28189,13 @@ var init_discovery_evidence = __esm(() => {
|
|
|
27940
28189
|
});
|
|
27941
28190
|
|
|
27942
28191
|
// ../cli/dist/operations/bootstrap/types.js
|
|
27943
|
-
import { createHash as
|
|
28192
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
27944
28193
|
function bootstrapPlanHash(plan) {
|
|
27945
28194
|
const { planHash: _ignored, ...body } = plan;
|
|
27946
|
-
return
|
|
28195
|
+
return createHash16("sha256").update(canonicalize(body)).digest("hex");
|
|
27947
28196
|
}
|
|
27948
28197
|
function bootstrapEmptyKbSnapshotId(input) {
|
|
27949
|
-
return `empty-source-state-${
|
|
28198
|
+
return `empty-source-state-${createHash16("sha256").update(canonicalize({
|
|
27950
28199
|
version: "kibi.empty-source-state.v1",
|
|
27951
28200
|
branch: input.branch,
|
|
27952
28201
|
workspaceSnapshot: input.workspaceSnapshot,
|
|
@@ -28083,7 +28332,7 @@ var init_discovery = __esm(() => {
|
|
|
28083
28332
|
});
|
|
28084
28333
|
|
|
28085
28334
|
// ../cli/dist/operations/bootstrap/intent-claims.js
|
|
28086
|
-
import { createHash as
|
|
28335
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
28087
28336
|
function citation(source, claim) {
|
|
28088
28337
|
return [
|
|
28089
28338
|
`intent_claim:${source.id}:${claim.reference}`,
|
|
@@ -28092,12 +28341,13 @@ function citation(source, claim) {
|
|
|
28092
28341
|
...source.connector ? [`connector:${source.connector}`] : []
|
|
28093
28342
|
];
|
|
28094
28343
|
}
|
|
28095
|
-
function
|
|
28096
|
-
return
|
|
28344
|
+
function digest2(...parts) {
|
|
28345
|
+
return createHash17("sha256").update(parts.join("\x00")).digest("hex").slice(0, 16).toUpperCase();
|
|
28097
28346
|
}
|
|
28098
28347
|
function claimBody(source, claim) {
|
|
28099
28348
|
return renderRequirementBody({
|
|
28100
28349
|
statement: claim.statement,
|
|
28350
|
+
context: claim.rationale,
|
|
28101
28351
|
source: {
|
|
28102
28352
|
excerpt: claim.excerpt,
|
|
28103
28353
|
title: source.title,
|
|
@@ -28108,8 +28358,14 @@ function claimBody(source, claim) {
|
|
|
28108
28358
|
function withClaimBody(step, body) {
|
|
28109
28359
|
return { ...step, document: { body } };
|
|
28110
28360
|
}
|
|
28361
|
+
function withRationale(step, rationale) {
|
|
28362
|
+
if (!rationale)
|
|
28363
|
+
return step;
|
|
28364
|
+
const properties = step.properties !== null && typeof step.properties === "object" ? step.properties : {};
|
|
28365
|
+
return { ...step, properties: { ...properties, rationale } };
|
|
28366
|
+
}
|
|
28111
28367
|
function reviewClaimCandidate(source, claim, kind, confidence) {
|
|
28112
|
-
const id = `FACT-BOOTSTRAP-${kind === "open_question" ? "QUESTION" : "OBSERVATION"}-${
|
|
28368
|
+
const id = `FACT-BOOTSTRAP-${kind === "open_question" ? "QUESTION" : "OBSERVATION"}-${digest2(source.id, claim.reference, claim.statement)}`;
|
|
28113
28369
|
const entity = {
|
|
28114
28370
|
type: "fact",
|
|
28115
28371
|
id,
|
|
@@ -28154,7 +28410,7 @@ function conflictCandidates(declared, sources, existingIds, minConfidence) {
|
|
|
28154
28410
|
diagnostics.push(`Conflict "${conflict.note}" cites claim(s) not declared in intentClaims: ${undeclared.map((ref) => `${ref.sourceId}:${ref.reference}`).join(", ")}; declare them or correct the reference.`);
|
|
28155
28411
|
continue;
|
|
28156
28412
|
}
|
|
28157
|
-
const id = `FACT-BOOTSTRAP-CONFLICT-${
|
|
28413
|
+
const id = `FACT-BOOTSTRAP-CONFLICT-${digest2(...[...refs].sort(), conflict.note)}`;
|
|
28158
28414
|
const candidateId = `conflict:${id.toLowerCase()}`;
|
|
28159
28415
|
if (confidence < minConfidence) {
|
|
28160
28416
|
suppressed.push({
|
|
@@ -28229,7 +28485,7 @@ ${evidenceLines.join(`
|
|
|
28229
28485
|
}
|
|
28230
28486
|
return { candidates, sourceOnlySignals: [], suppressed, diagnostics };
|
|
28231
28487
|
}
|
|
28232
|
-
function buildIntentClaimCandidates(declared, existingIds, minConfidence) {
|
|
28488
|
+
function buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys) {
|
|
28233
28489
|
const sources = new Map((declared.knowledgeSources ?? []).map((source) => [source.id, source]));
|
|
28234
28490
|
const candidates = [];
|
|
28235
28491
|
const sourceOnlySignals = [];
|
|
@@ -28285,9 +28541,17 @@ function buildIntentClaimCandidates(declared, existingIds, minConfidence) {
|
|
|
28285
28541
|
let writeSet = null;
|
|
28286
28542
|
try {
|
|
28287
28543
|
const modeled = claimFor(claim.statement, `knowledge-source:${source.id}`, confidence, provenance);
|
|
28288
|
-
|
|
28544
|
+
const planned = modeled ? planSubjectKey(modeled.subjectKey, modeled.propertyKey, claim.component ?? source.component, subjectKeys, `${source.id}:${claim.reference}`) : null;
|
|
28545
|
+
const subjectKey = planned?.resolution ?? null;
|
|
28546
|
+
diagnostics.push(...planned?.diagnostics ?? []);
|
|
28547
|
+
writeSet = modeled && subjectKey?.ok ? buildStrictWriteSet({
|
|
28548
|
+
claim: { ...modeled, subjectKey: subjectKey.subjectKey },
|
|
28549
|
+
statement: claim.statement
|
|
28550
|
+
}) : null;
|
|
28289
28551
|
if (!modeled)
|
|
28290
28552
|
diagnostics.push(`Intent claim needs authoring at ${source.id}:${claim.reference}: ${claim.statement}`);
|
|
28553
|
+
else if (subjectKey && !subjectKey.ok)
|
|
28554
|
+
diagnostics.push(`Intent claim at ${source.id}:${claim.reference} was not planned as a requirement: its ${subjectKey.reason}. Declare component on the claim or on knowledge source ${source.id} and re-plan, or author it with kb_model: ${claim.statement}`);
|
|
28291
28555
|
} catch (error) {
|
|
28292
28556
|
diagnostics.push(`Intent claim extraction failed at ${source.id}:${claim.reference}: ${error instanceof Error ? error.message : String(error)}`);
|
|
28293
28557
|
}
|
|
@@ -28306,7 +28570,7 @@ function buildIntentClaimCandidates(declared, existingIds, minConfidence) {
|
|
|
28306
28570
|
from,
|
|
28307
28571
|
to
|
|
28308
28572
|
})),
|
|
28309
|
-
applyPlan: strictPlan(writeSet).map((step) => step.type === "req" ? withClaimBody(step, claimBody(source, claim)) : step)
|
|
28573
|
+
applyPlan: strictPlan(writeSet).map((step) => step.type === "req" ? withClaimBody(withRationale(step, claim.rationale), claimBody(source, claim)) : step)
|
|
28310
28574
|
});
|
|
28311
28575
|
continue;
|
|
28312
28576
|
}
|
|
@@ -28347,6 +28611,7 @@ var init_intent_claims = __esm(() => {
|
|
|
28347
28611
|
init_entity_body_context();
|
|
28348
28612
|
init_strict_modeling();
|
|
28349
28613
|
init_candidate_helpers();
|
|
28614
|
+
init_requirement_claims();
|
|
28350
28615
|
AUTHORITY_CONFIDENCE = {
|
|
28351
28616
|
authoritative: 0.9,
|
|
28352
28617
|
supporting: 0.82
|
|
@@ -28554,6 +28819,7 @@ function knowledgeSources(values) {
|
|
|
28554
28819
|
seen.add(id);
|
|
28555
28820
|
const connector = value.connector?.trim();
|
|
28556
28821
|
const notes = value.notes?.trim();
|
|
28822
|
+
const component = value.component?.trim();
|
|
28557
28823
|
result.push({
|
|
28558
28824
|
id,
|
|
28559
28825
|
kind: value.kind,
|
|
@@ -28561,7 +28827,8 @@ function knowledgeSources(values) {
|
|
|
28561
28827
|
locator,
|
|
28562
28828
|
authority: value.authority,
|
|
28563
28829
|
...connector ? { connector } : {},
|
|
28564
|
-
...notes ? { notes } : {}
|
|
28830
|
+
...notes ? { notes } : {},
|
|
28831
|
+
...component ? { component } : {}
|
|
28565
28832
|
});
|
|
28566
28833
|
}
|
|
28567
28834
|
return result;
|
|
@@ -28583,11 +28850,15 @@ function intentClaims(values) {
|
|
|
28583
28850
|
continue;
|
|
28584
28851
|
seen.add(key);
|
|
28585
28852
|
const excerpt = value.excerpt?.trim();
|
|
28853
|
+
const component = value.component?.trim();
|
|
28854
|
+
const rationale = value.rationale?.trim().replace(/\s+/g, " ");
|
|
28586
28855
|
result.push({
|
|
28587
28856
|
statement,
|
|
28588
28857
|
sourceId,
|
|
28589
28858
|
reference,
|
|
28590
28859
|
...excerpt ? { excerpt } : {},
|
|
28860
|
+
...component ? { component } : {},
|
|
28861
|
+
...rationale ? { rationale } : {},
|
|
28591
28862
|
...kind !== "intent" ? { kind } : {}
|
|
28592
28863
|
});
|
|
28593
28864
|
}
|
|
@@ -30109,7 +30380,6 @@ var init_analysis_receipt = __esm(() => {
|
|
|
30109
30380
|
// ../cli/dist/operations/semantic-advisor/observation-plan.js
|
|
30110
30381
|
function observationPlan(payload, title, tags) {
|
|
30111
30382
|
const factId = `FACT-OBS-${shortHash(`${stringValue2(payload.id)}.${title}.${statementOf(payload)}`)}`;
|
|
30112
|
-
const target = tags.includes("review:ambiguity") ? "review:ambiguous-claim" : tags.includes("review:keyword-false-positive") ? "review:keyword-false-positive" : tags.includes("review:ontology-gap") ? "review:ontology-gap" : tags.includes("review:nonlogical") ? "review:nonlogical" : undefined;
|
|
30113
30383
|
return [
|
|
30114
30384
|
{
|
|
30115
30385
|
type: "fact",
|
|
@@ -30122,7 +30392,13 @@ function observationPlan(payload, title, tags) {
|
|
|
30122
30392
|
text_ref: statementOf(payload),
|
|
30123
30393
|
tags
|
|
30124
30394
|
},
|
|
30125
|
-
|
|
30395
|
+
document: {
|
|
30396
|
+
body: `${title}. The semantic advisor suggested this review observation because the prose below is not safely grounded by a typed fact; it stays open until a reviewer models, rewords or dismisses the claim.
|
|
30397
|
+
|
|
30398
|
+
> ${statementOf(payload).trim().replace(/\n/g, `
|
|
30399
|
+
> `)}`
|
|
30400
|
+
},
|
|
30401
|
+
relationships: []
|
|
30126
30402
|
}
|
|
30127
30403
|
];
|
|
30128
30404
|
}
|
|
@@ -30907,7 +31183,7 @@ var init_validation2 = __esm(() => {
|
|
|
30907
31183
|
});
|
|
30908
31184
|
|
|
30909
31185
|
// ../cli/dist/operations/bootstrap/generate.js
|
|
30910
|
-
import { createHash as
|
|
31186
|
+
import { createHash as createHash18 } from "node:crypto";
|
|
30911
31187
|
import path31 from "node:path";
|
|
30912
31188
|
function filterSourceOnlySignals(signals, entityTypes) {
|
|
30913
31189
|
return entityTypes && entityTypes.length > 0 ? signals.filter((signal) => entityTypes.includes(signal.kind)) : signals;
|
|
@@ -30926,7 +31202,7 @@ function firstUpsertId(candidate) {
|
|
|
30926
31202
|
return properties !== null && typeof properties === "object" && "id" in properties && typeof properties.id === "string" ? properties.id : "";
|
|
30927
31203
|
}
|
|
30928
31204
|
function sha2562(value) {
|
|
30929
|
-
return
|
|
31205
|
+
return createHash18("sha256").update(value).digest("hex");
|
|
30930
31206
|
}
|
|
30931
31207
|
function selectBootstrapCandidates(input, existingIds, entityTypes, maximum) {
|
|
30932
31208
|
const allowed = entityTypes?.length ? new Set(entityTypes) : null;
|
|
@@ -31141,13 +31417,14 @@ async function executePlanBootstrap(args, context) {
|
|
|
31141
31417
|
})
|
|
31142
31418
|
]);
|
|
31143
31419
|
const bound = await expectedSnapshots(context, discovery.evidence.map((evidence) => evidence.relativePath).filter((value) => Boolean(value)));
|
|
31144
|
-
const
|
|
31420
|
+
const subjectKeys = new SubjectKeyRegistry;
|
|
31421
|
+
const built = discovery.activation.allowCandidateGeneration ? buildBootstrapCandidates(discovery.evidence, new Set, minConfidence, includeGenericMarkdown, subjectKeys) : {
|
|
31145
31422
|
candidates: [],
|
|
31146
31423
|
sourceOnlySignals: [],
|
|
31147
31424
|
suppressed: [],
|
|
31148
31425
|
diagnostics: []
|
|
31149
31426
|
};
|
|
31150
|
-
const claimed = discovery.activation.allowCandidateGeneration ? buildIntentClaimCandidates(declared, existingIds, minConfidence) : {
|
|
31427
|
+
const claimed = discovery.activation.allowCandidateGeneration ? buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys) : {
|
|
31151
31428
|
candidates: [],
|
|
31152
31429
|
sourceOnlySignals: [],
|
|
31153
31430
|
suppressed: [],
|
|
@@ -31199,6 +31476,7 @@ var init_generate = __esm(() => {
|
|
|
31199
31476
|
init_discovery();
|
|
31200
31477
|
init_intent_claims();
|
|
31201
31478
|
init_presentation();
|
|
31479
|
+
init_requirement_claims();
|
|
31202
31480
|
init_validation2();
|
|
31203
31481
|
init_types();
|
|
31204
31482
|
});
|
|
@@ -31300,7 +31578,12 @@ var init_bootstrap = __esm(() => {
|
|
|
31300
31578
|
type: "string",
|
|
31301
31579
|
description: "Optional name of the MCP server or tool the agent used to read the source."
|
|
31302
31580
|
},
|
|
31303
|
-
notes: { type: "string" }
|
|
31581
|
+
notes: { type: "string" },
|
|
31582
|
+
component: {
|
|
31583
|
+
type: "string",
|
|
31584
|
+
minLength: 1,
|
|
31585
|
+
description: "Optional component this source's claims are about (for example recorder). It becomes the first segment of each generated subject_key (component.aspect); a claim's own component overrides it."
|
|
31586
|
+
}
|
|
31304
31587
|
}
|
|
31305
31588
|
}
|
|
31306
31589
|
},
|
|
@@ -31337,6 +31620,16 @@ var init_bootstrap = __esm(() => {
|
|
|
31337
31620
|
minLength: 1,
|
|
31338
31621
|
description: "Verbatim passage from the source the claim came from. Required for intent and observation claims (optional for open_question): Kibi persists it with the knowledge source title and reference in the created entity's '## Source' section, because the ticket or page may be gone by the next migration."
|
|
31339
31622
|
},
|
|
31623
|
+
component: {
|
|
31624
|
+
type: "string",
|
|
31625
|
+
minLength: 1,
|
|
31626
|
+
description: "Optional component the claim is about (for example recorder). Generated subject keys take the shape component.aspect with the aspect from the claim's subject. Without a component on the claim or its knowledge source, a claim whose subject is not a single word or already dotted becomes an authoring follow-up with a diagnostic instead of a malformed subject key."
|
|
31627
|
+
},
|
|
31628
|
+
rationale: {
|
|
31629
|
+
type: "string",
|
|
31630
|
+
minLength: 1,
|
|
31631
|
+
description: "Optional reason the requirement exists, as the source states it or the human answered when asked. It becomes the requirement's rationale and its body's '## Context' section. Never invent one."
|
|
31632
|
+
},
|
|
31340
31633
|
kind: {
|
|
31341
31634
|
type: "string",
|
|
31342
31635
|
enum: [...INTENT_CLAIM_KINDS],
|
|
@@ -31456,7 +31749,7 @@ var init_aggregated_checks = __esm(() => {
|
|
|
31456
31749
|
});
|
|
31457
31750
|
|
|
31458
31751
|
// ../cli/dist/traceability/impact-review.js
|
|
31459
|
-
import { createHash as
|
|
31752
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
31460
31753
|
function canonicalJson2(value) {
|
|
31461
31754
|
const active = new Set;
|
|
31462
31755
|
const encode = (item) => {
|
|
@@ -31490,10 +31783,10 @@ function canonicalJson2(value) {
|
|
|
31490
31783
|
return encode(value);
|
|
31491
31784
|
}
|
|
31492
31785
|
function fingerprint(value) {
|
|
31493
|
-
return `sha256:${
|
|
31786
|
+
return `sha256:${createHash19("sha256").update(canonicalJson2(value), "utf8").digest("hex")}`;
|
|
31494
31787
|
}
|
|
31495
31788
|
function fingerprintBytes(value) {
|
|
31496
|
-
return `sha256:${
|
|
31789
|
+
return `sha256:${createHash19("sha256").update(value).digest("hex")}`;
|
|
31497
31790
|
}
|
|
31498
31791
|
function isObject(value) {
|
|
31499
31792
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -32123,7 +32416,7 @@ var init_source_classification = __esm(() => {
|
|
|
32123
32416
|
});
|
|
32124
32417
|
|
|
32125
32418
|
// ../cli/dist/plugins/source-analysis-service.js
|
|
32126
|
-
import { createHash as
|
|
32419
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
32127
32420
|
import * as path33 from "node:path";
|
|
32128
32421
|
function detectSourceLanguage(filePath) {
|
|
32129
32422
|
return extensionLanguage(filePath);
|
|
@@ -32131,7 +32424,7 @@ function detectSourceLanguage(filePath) {
|
|
|
32131
32424
|
function createV2Request(filePath, content, explicitLanguageHint) {
|
|
32132
32425
|
const classification = classifySource(filePath, content, explicitLanguageHint);
|
|
32133
32426
|
const language = classification.language;
|
|
32134
|
-
const inputFingerprint =
|
|
32427
|
+
const inputFingerprint = createHash20("sha256").update(filePath).update("\x00").update(content).update("\x00").update(classification.kind).update("\x00").update(classification.language).update("\x00").update(explicitLanguageHint?.trim().toLowerCase() ?? "").digest("hex");
|
|
32135
32428
|
return {
|
|
32136
32429
|
classification,
|
|
32137
32430
|
input: {
|
|
@@ -32293,7 +32586,7 @@ class SourceAnalysisService {
|
|
|
32293
32586
|
providerId: entry.capability.id,
|
|
32294
32587
|
stamp: entry.stamp,
|
|
32295
32588
|
inputFingerprint: request.inputFingerprint,
|
|
32296
|
-
providerFingerprint: this.options.providerFingerprints?.[entry.pluginId] ??
|
|
32589
|
+
providerFingerprint: this.options.providerFingerprints?.[entry.pluginId] ?? createHash20("sha256").update(`${entry.pluginId}\x00${entry.pluginVersion}\x00${entry.stamp.capability}`).digest("hex"),
|
|
32297
32590
|
shadowComparisons: []
|
|
32298
32591
|
};
|
|
32299
32592
|
} catch (error) {
|
|
@@ -32413,7 +32706,7 @@ var init_source_analysis_service = __esm(() => {
|
|
|
32413
32706
|
});
|
|
32414
32707
|
|
|
32415
32708
|
// ../cli/dist/plugins/maintenance-source-analysis.js
|
|
32416
|
-
import { createHash as
|
|
32709
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
32417
32710
|
import { readFileSync as readFileSync16, realpathSync as realpathSync5 } from "node:fs";
|
|
32418
32711
|
import { createRequire as createRequire4 } from "node:module";
|
|
32419
32712
|
import { dirname as dirname7, isAbsolute as isAbsolute6, join as join13, relative as relative5, resolve as resolve7 } from "node:path";
|
|
@@ -32426,7 +32719,7 @@ function digestFile(root, file) {
|
|
|
32426
32719
|
const actualRel = relative5(realpathSync5(root), actual);
|
|
32427
32720
|
if (actualRel.startsWith("..") || isAbsolute6(actualRel))
|
|
32428
32721
|
throw new Error(`Approved asset escapes its package: ${file}`);
|
|
32429
|
-
return
|
|
32722
|
+
return createHash21("sha256").update(readFileSync16(actual)).digest("hex");
|
|
32430
32723
|
}
|
|
32431
32724
|
function verifyFiles(root, files) {
|
|
32432
32725
|
if (Object.keys(files).length === 0)
|
|
@@ -32495,7 +32788,7 @@ function verifyApprovedSourceAnalyzer(root, approval) {
|
|
|
32495
32788
|
if (metadata.version !== dependency.version)
|
|
32496
32789
|
throw new Error(`Unapproved source runtime version: ${dependency.packageName}`);
|
|
32497
32790
|
}
|
|
32498
|
-
return
|
|
32791
|
+
return createHash21("sha256").update(JSON.stringify(approval)).digest("hex");
|
|
32499
32792
|
}
|
|
32500
32793
|
function createMaintenanceSourceAnalysisService(workspaceRoot, projectConfig) {
|
|
32501
32794
|
const config = projectConfig ?? readProjectKibiConfig(workspaceRoot);
|
|
@@ -40467,7 +40760,7 @@ async function enrichSymbolCoordinatesWithTsMorph(entries, workspaceRoot) {
|
|
|
40467
40760
|
var init_symbols_ts = () => {};
|
|
40468
40761
|
|
|
40469
40762
|
// ../cli/dist/traceability/symbol-extract.js
|
|
40470
|
-
import { createHash as
|
|
40763
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
40471
40764
|
function createManifestLookupSentinelKey(manifestPath) {
|
|
40472
40765
|
return `${MANIFEST_SENTINEL_PREFIX}${manifestPath}`;
|
|
40473
40766
|
}
|
|
@@ -40479,7 +40772,7 @@ function getCandidateManifestPaths(filePath) {
|
|
|
40479
40772
|
return LOCAL_MANIFEST_NAMES.map((manifestName) => `${dir}/${manifestName}`);
|
|
40480
40773
|
}
|
|
40481
40774
|
function createHashFallbackId(filePath, name) {
|
|
40482
|
-
const h =
|
|
40775
|
+
const h = createHash23("sha256");
|
|
40483
40776
|
h.update(`${filePath}:${name}`);
|
|
40484
40777
|
return h.digest("hex").slice(0, 16);
|
|
40485
40778
|
}
|
|
@@ -40567,7 +40860,7 @@ function buildSymbolResult(stagedFile, name, kind, span, inlineReqLinks, manifes
|
|
|
40567
40860
|
};
|
|
40568
40861
|
}
|
|
40569
40862
|
function computeContentSha(content) {
|
|
40570
|
-
const h =
|
|
40863
|
+
const h = createHash23("sha256");
|
|
40571
40864
|
h.update(content);
|
|
40572
40865
|
return h.digest("hex");
|
|
40573
40866
|
}
|
|
@@ -51877,7 +52170,7 @@ var require_out4 = __commonJS(function(exports2, module2) {
|
|
|
51877
52170
|
|
|
51878
52171
|
// ../cli/dist/commands/sync/discovery.js
|
|
51879
52172
|
import { execFile } from "node:child_process";
|
|
51880
|
-
import { createHash as
|
|
52173
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
51881
52174
|
import * as fs5 from "node:fs";
|
|
51882
52175
|
import { existsSync as existsSync23, readFileSync as readFileSync24, readdirSync as readdirSync6, unlinkSync as unlinkSync4 } from "node:fs";
|
|
51883
52176
|
import * as path47 from "node:path";
|
|
@@ -51912,13 +52205,13 @@ function pendingSourcePaths(cwd, recoverMissing) {
|
|
|
51912
52205
|
receiptPath,
|
|
51913
52206
|
path: relative,
|
|
51914
52207
|
afterHash: receipt.afterHash,
|
|
51915
|
-
rawHash:
|
|
52208
|
+
rawHash: createHash24("sha256").update(raw).digest("hex")
|
|
51916
52209
|
});
|
|
51917
52210
|
continue;
|
|
51918
52211
|
}
|
|
51919
52212
|
throw new Error(`Pending source is missing: ${relative}. If the file was deleted on purpose, run 'kibi branch recover --apply' to rebuild the branch KB from the sources that remain.`);
|
|
51920
52213
|
}
|
|
51921
|
-
const actual =
|
|
52214
|
+
const actual = createHash24("sha256").update(readFileSync24(absolute)).digest("hex");
|
|
51922
52215
|
if (actual !== receipt.afterHash) {
|
|
51923
52216
|
throw new Error(`Pending source hash drift blocks sync for ${relative}; expected ${receipt.afterHash}, found ${actual}`);
|
|
51924
52217
|
}
|
|
@@ -51966,7 +52259,7 @@ function clearRecoveredPendingSourceReceipts(cwd, receipts) {
|
|
|
51966
52259
|
const raw = readTextOrEnoent(absolute);
|
|
51967
52260
|
if (raw === null)
|
|
51968
52261
|
continue;
|
|
51969
|
-
const rawHash =
|
|
52262
|
+
const rawHash = createHash24("sha256").update(raw).digest("hex");
|
|
51970
52263
|
if (rawHash !== receipt.rawHash) {
|
|
51971
52264
|
throw new Error(`Pending source receipt changed during recovery for ${receipt.path}; refusing to retire newer receipt`);
|
|
51972
52265
|
}
|
|
@@ -53754,7 +54047,7 @@ function scoreExactPredicates3(schema, text) {
|
|
|
53754
54047
|
}
|
|
53755
54048
|
|
|
53756
54049
|
// ../cli/dist/operations/modeling/predicate-utils.js
|
|
53757
|
-
import { createHash as
|
|
54050
|
+
import { createHash as createHash25 } from "node:crypto";
|
|
53758
54051
|
function normalizeText2(text) {
|
|
53759
54052
|
const normalized = String(text ?? "").trim();
|
|
53760
54053
|
if (!normalized) {
|
|
@@ -53778,7 +54071,7 @@ function slug2(value) {
|
|
|
53778
54071
|
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
53779
54072
|
}
|
|
53780
54073
|
function hashId(prefix, parts) {
|
|
53781
|
-
const digest =
|
|
54074
|
+
const digest = createHash25("sha256").update(parts.join("\x00")).digest("hex").slice(0, 12).toUpperCase();
|
|
53782
54075
|
return `${prefix}-${digest}`;
|
|
53783
54076
|
}
|
|
53784
54077
|
function inferSubject(text, subjectHint) {
|
|
@@ -54442,11 +54735,43 @@ function isGenericPlaceholder(value) {
|
|
|
54442
54735
|
const normalized = value.trim().toLowerCase();
|
|
54443
54736
|
return PLACEHOLDER_VALUES.has(normalized) || normalized === "unknown" || normalized.startsWith("requirement.") || normalized.endsWith("_policy") && ["executable", "cwd", "environment", "stdio", "termination"].some((kind) => normalized.startsWith(kind));
|
|
54444
54737
|
}
|
|
54445
|
-
function
|
|
54738
|
+
function bindingToken(value) {
|
|
54739
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
54740
|
+
}
|
|
54741
|
+
function claimNames(text, token) {
|
|
54742
|
+
if (!text || !token)
|
|
54743
|
+
return false;
|
|
54744
|
+
const words = token.split("_").filter(Boolean);
|
|
54745
|
+
if (words.length === 0)
|
|
54746
|
+
return false;
|
|
54747
|
+
return new RegExp(`\\b${words.join("[\\s_-]+")}\\b`, "i").test(text);
|
|
54748
|
+
}
|
|
54749
|
+
function matchesConstant(value, context) {
|
|
54750
|
+
const token = bindingToken(value);
|
|
54751
|
+
return context.constants?.some((constant) => bindingToken(constant) === token) ?? false;
|
|
54752
|
+
}
|
|
54753
|
+
function nameOrStopWordReason(value, context = {}) {
|
|
54754
|
+
const token = bindingToken(value);
|
|
54755
|
+
if (token === "true" || token === "false")
|
|
54756
|
+
return null;
|
|
54757
|
+
if (matchesConstant(value, context))
|
|
54758
|
+
return null;
|
|
54759
|
+
if (STOP_WORD_BINDINGS.has(token))
|
|
54760
|
+
return `"${token}" is a stop word`;
|
|
54761
|
+
const own = context.argumentName ? bindingToken(context.argumentName) : "";
|
|
54762
|
+
const repeatsName = own !== "" && token === own || (context.argumentNames ?? []).some((name) => bindingToken(name) === token);
|
|
54763
|
+
if (repeatsName && !claimNames(context.text, token))
|
|
54764
|
+
return `it repeats the argument name ${token} and the claim does not name it`;
|
|
54765
|
+
return null;
|
|
54766
|
+
}
|
|
54767
|
+
function classifyBinding(value, text, explicit, canonical = false, context = {}) {
|
|
54446
54768
|
const normalized = value.trim();
|
|
54447
|
-
if (
|
|
54769
|
+
if (nameOrStopWordReason(normalized, { ...context, text }) !== null)
|
|
54770
|
+
return "placeholder";
|
|
54771
|
+
const constant = matchesConstant(normalized, context);
|
|
54772
|
+
if (canonical && (constant || !isGenericPlaceholder(normalized)))
|
|
54448
54773
|
return "extracted";
|
|
54449
|
-
if (explicit && (!isGenericPlaceholder(normalized) || ["true", "false"].includes(normalized.toLowerCase())))
|
|
54774
|
+
if (explicit && (constant || !isGenericPlaceholder(normalized) || ["true", "false"].includes(normalized.toLowerCase())))
|
|
54450
54775
|
return "explicit";
|
|
54451
54776
|
if (!normalized || isGenericPlaceholder(normalized))
|
|
54452
54777
|
return "placeholder";
|
|
@@ -54460,7 +54785,7 @@ function aggregateBindingProvenance(values) {
|
|
|
54460
54785
|
function bindingCanBeApplied(value) {
|
|
54461
54786
|
return value === "explicit" || value === "extracted";
|
|
54462
54787
|
}
|
|
54463
|
-
var PLACEHOLDER_VALUES, DERIVED_CUE_ALIASES, PROVENANCE_ORDER;
|
|
54788
|
+
var PLACEHOLDER_VALUES, DERIVED_CUE_ALIASES, STOP_WORD_BINDINGS, PROVENANCE_ORDER;
|
|
54464
54789
|
var init_predicate_bindings = __esm(() => {
|
|
54465
54790
|
PLACEHOLDER_VALUES = new Set([
|
|
54466
54791
|
"unknown",
|
|
@@ -54532,6 +54857,62 @@ var init_predicate_bindings = __esm(() => {
|
|
|
54532
54857
|
actionable_error: ["actionable", "clear error", "report", "error"],
|
|
54533
54858
|
exception: ["exception", "except", "package-manager", "package manager"]
|
|
54534
54859
|
};
|
|
54860
|
+
STOP_WORD_BINDINGS = new Set([
|
|
54861
|
+
"a",
|
|
54862
|
+
"an",
|
|
54863
|
+
"the",
|
|
54864
|
+
"be",
|
|
54865
|
+
"is",
|
|
54866
|
+
"are",
|
|
54867
|
+
"was",
|
|
54868
|
+
"were",
|
|
54869
|
+
"been",
|
|
54870
|
+
"being",
|
|
54871
|
+
"am",
|
|
54872
|
+
"do",
|
|
54873
|
+
"does",
|
|
54874
|
+
"did",
|
|
54875
|
+
"done",
|
|
54876
|
+
"have",
|
|
54877
|
+
"has",
|
|
54878
|
+
"had",
|
|
54879
|
+
"it",
|
|
54880
|
+
"its",
|
|
54881
|
+
"this",
|
|
54882
|
+
"that",
|
|
54883
|
+
"these",
|
|
54884
|
+
"those",
|
|
54885
|
+
"they",
|
|
54886
|
+
"them",
|
|
54887
|
+
"there",
|
|
54888
|
+
"thing",
|
|
54889
|
+
"something",
|
|
54890
|
+
"anything",
|
|
54891
|
+
"some",
|
|
54892
|
+
"any",
|
|
54893
|
+
"of",
|
|
54894
|
+
"to",
|
|
54895
|
+
"in",
|
|
54896
|
+
"at",
|
|
54897
|
+
"by",
|
|
54898
|
+
"for",
|
|
54899
|
+
"with",
|
|
54900
|
+
"and",
|
|
54901
|
+
"or",
|
|
54902
|
+
"not",
|
|
54903
|
+
"null",
|
|
54904
|
+
"nil",
|
|
54905
|
+
"n_a",
|
|
54906
|
+
"na",
|
|
54907
|
+
"tbd",
|
|
54908
|
+
"todo",
|
|
54909
|
+
"x",
|
|
54910
|
+
"xxx",
|
|
54911
|
+
"foo",
|
|
54912
|
+
"bar",
|
|
54913
|
+
"example",
|
|
54914
|
+
"placeholder"
|
|
54915
|
+
]);
|
|
54535
54916
|
PROVENANCE_ORDER = [
|
|
54536
54917
|
"explicit",
|
|
54537
54918
|
"extracted",
|
|
@@ -55248,7 +55629,11 @@ function buildSuggestion(schema, text, subject, score, argumentBindings = {}, po
|
|
|
55248
55629
|
const undeclaredArguments = new Set(conformance.undeclared.map((value) => value.argumentName));
|
|
55249
55630
|
const bindingProvenanceByArgument = Object.fromEntries(schema.argument_names.map((name, index) => [
|
|
55250
55631
|
name,
|
|
55251
|
-
classifyBinding(predicateArgs[index] ?? "unknown", text, typeof argumentBindings[name] === "string" && argumentBindings[name].trim().length > 0 || diagnostics?.explicitSubject === true && index === 0, canonicalLauncherArgs?.[index] === predicateArgs[index] && !(index === 0 && predicateArgs[index] === "launcher" && diagnostics?.explicitSubject !== true && typeof argumentBindings[name] !== "string")
|
|
55632
|
+
classifyBinding(predicateArgs[index] ?? "unknown", text, typeof argumentBindings[name] === "string" && argumentBindings[name].trim().length > 0 || diagnostics?.explicitSubject === true && index === 0, canonicalLauncherArgs?.[index] === predicateArgs[index] && !(index === 0 && predicateArgs[index] === "launcher" && diagnostics?.explicitSubject !== true && typeof argumentBindings[name] !== "string"), index === 0 && diagnostics?.explicitSubject === true && typeof argumentBindings[name] !== "string" ? { constants: schema.argument_constants?.[name] } : {
|
|
55633
|
+
argumentName: name,
|
|
55634
|
+
argumentNames: schema.argument_names,
|
|
55635
|
+
constants: schema.argument_constants?.[name]
|
|
55636
|
+
})
|
|
55252
55637
|
]));
|
|
55253
55638
|
const bindingProvenance = aggregateBindingProvenance(Object.values(bindingProvenanceByArgument));
|
|
55254
55639
|
const unboundArguments = schema.argument_names.filter((name) => undeclaredArguments.has(name) || !bindingCanBeApplied(bindingProvenanceByArgument[name] ?? "placeholder"));
|
|
@@ -55338,8 +55723,21 @@ function buildRelationshipPlan(factId, requirementId, claimText, existingLogicCl
|
|
|
55338
55723
|
instructions: `Apply the predicate fact ${factId} first, update the requirement with the returned merged logicClaims manifest, then attach this relationship without overwriting other requirement metadata. The relationship target is the planned fact id ${factId}, never a candidates[].id (SUGGEST-...).`
|
|
55339
55724
|
};
|
|
55340
55725
|
}
|
|
55726
|
+
function gapObservationBody(text, args) {
|
|
55727
|
+
const origin = [
|
|
55728
|
+
args.requirementId ? `requirement ${args.requirementId}` : null,
|
|
55729
|
+
args.source ? `source ${args.source}` : null
|
|
55730
|
+
].filter((value) => value !== null);
|
|
55731
|
+
return [
|
|
55732
|
+
"No available predicate schema fits this claim, so kb_model mode predicates recorded it as an open ontology gap. The observation does not ground the claim; it stays visible for review until a reviewed predicate_schema covers this kind of statement.",
|
|
55733
|
+
...origin.length > 0 ? [`Claim from ${origin.join(", ")}:`] : ["Claim:"],
|
|
55734
|
+
`> ${text.trim().replace(/\n/g, `
|
|
55735
|
+
> `)}`
|
|
55736
|
+
].join(`
|
|
55737
|
+
|
|
55738
|
+
`);
|
|
55739
|
+
}
|
|
55341
55740
|
function buildGapApplyPlan(text, args) {
|
|
55342
|
-
const claimKey = semanticClaimKey(text);
|
|
55343
55741
|
const factId = hashId("FACT-ONTOLOGY-GAP", [
|
|
55344
55742
|
args.requirementId ?? "",
|
|
55345
55743
|
args.source ?? "",
|
|
@@ -55353,20 +55751,14 @@ function buildGapApplyPlan(text, args) {
|
|
|
55353
55751
|
title: "Ontology gap: predicate schema needed",
|
|
55354
55752
|
status: "active",
|
|
55355
55753
|
source: args.source ?? "mcp://kibi/suggest-predicates",
|
|
55356
|
-
text_ref: args.source,
|
|
55754
|
+
...args.source ? { text_ref: args.source } : {},
|
|
55357
55755
|
tags: ["review:ontology-gap", "needs_schema_extension"],
|
|
55358
55756
|
fact_kind: "observation",
|
|
55359
55757
|
value_string: text,
|
|
55360
|
-
claim_key: claimKey,
|
|
55361
55758
|
claim_text: text
|
|
55362
55759
|
},
|
|
55363
|
-
|
|
55364
|
-
|
|
55365
|
-
type: "relates_to",
|
|
55366
|
-
from: factId,
|
|
55367
|
-
to: "review:ontology-gap"
|
|
55368
|
-
}
|
|
55369
|
-
]
|
|
55760
|
+
document: { body: gapObservationBody(text, args) },
|
|
55761
|
+
relationships: []
|
|
55370
55762
|
}
|
|
55371
55763
|
];
|
|
55372
55764
|
}
|
|
@@ -55429,6 +55821,84 @@ var init_predicate_applyplan = __esm(() => {
|
|
|
55429
55821
|
init_predicate_utils();
|
|
55430
55822
|
});
|
|
55431
55823
|
|
|
55824
|
+
// ../cli/dist/operations/modeling/predicate-binding-hints.js
|
|
55825
|
+
function exampleArguments(example) {
|
|
55826
|
+
const open = example.indexOf("(");
|
|
55827
|
+
const close = example.lastIndexOf(")");
|
|
55828
|
+
if (open < 0 || close <= open)
|
|
55829
|
+
return [];
|
|
55830
|
+
const inner = example.slice(open + 1, close);
|
|
55831
|
+
const args = [];
|
|
55832
|
+
let depth = 0;
|
|
55833
|
+
let current = "";
|
|
55834
|
+
for (const char of inner) {
|
|
55835
|
+
if (char === "(" || char === "[")
|
|
55836
|
+
depth += 1;
|
|
55837
|
+
if (char === ")" || char === "]")
|
|
55838
|
+
depth -= 1;
|
|
55839
|
+
if (char === "," && depth === 0) {
|
|
55840
|
+
args.push(current.trim());
|
|
55841
|
+
current = "";
|
|
55842
|
+
continue;
|
|
55843
|
+
}
|
|
55844
|
+
current += char;
|
|
55845
|
+
}
|
|
55846
|
+
args.push(current.trim());
|
|
55847
|
+
return args.filter(Boolean);
|
|
55848
|
+
}
|
|
55849
|
+
function unboundReason(candidate, name, value, text) {
|
|
55850
|
+
const schema = candidate.schema;
|
|
55851
|
+
const provenance = candidate.binding_provenance_by_argument[name];
|
|
55852
|
+
const nameReason = nameOrStopWordReason(value, {
|
|
55853
|
+
argumentName: name,
|
|
55854
|
+
argumentNames: schema.argument_names,
|
|
55855
|
+
constants: schema.argument_constants?.[name],
|
|
55856
|
+
text
|
|
55857
|
+
});
|
|
55858
|
+
if (nameReason !== null)
|
|
55859
|
+
return `The value "${value}" is not a binding: ${nameReason}.`;
|
|
55860
|
+
if (!value.trim() || isGenericPlaceholder(value))
|
|
55861
|
+
return "The claim text names no value for this argument.";
|
|
55862
|
+
if (provenance === "inferred")
|
|
55863
|
+
return `The value "${value}" was inferred and does not appear in the claim text; confirm it or pass the exact value.`;
|
|
55864
|
+
if (schema.argument_constants?.[name])
|
|
55865
|
+
return `The value "${value}" is not one of this argument's declared constants.`;
|
|
55866
|
+
return `The value "${value}" needs review.`;
|
|
55867
|
+
}
|
|
55868
|
+
function buildBindingHints(candidate, text) {
|
|
55869
|
+
const schema = candidate.schema;
|
|
55870
|
+
const parsedExamples = schema.examples.map(exampleArguments);
|
|
55871
|
+
return candidate.unbound_arguments.map((name) => {
|
|
55872
|
+
const position = schema.argument_names.indexOf(name);
|
|
55873
|
+
const constants = schema.argument_constants?.[name];
|
|
55874
|
+
const exampleValues = parsedExamples.map((args) => args[position]).filter((value) => typeof value === "string");
|
|
55875
|
+
const examples = Array.from(new Set([...constants ?? [], ...exampleValues])).slice(0, MAX_EXAMPLES);
|
|
55876
|
+
const current = candidate.predicate_args[position] ?? "";
|
|
55877
|
+
const description = schema.argument_descriptions?.[position];
|
|
55878
|
+
return {
|
|
55879
|
+
argument: name,
|
|
55880
|
+
position,
|
|
55881
|
+
type: schema.argument_types[position] ?? "unknown",
|
|
55882
|
+
...description ? { description } : {},
|
|
55883
|
+
...constants ? { allowedValues: [...constants] } : {},
|
|
55884
|
+
examples,
|
|
55885
|
+
currentValue: current,
|
|
55886
|
+
provenance: candidate.binding_provenance_by_argument[name] ?? "placeholder",
|
|
55887
|
+
reason: unboundReason(candidate, name, current, text)
|
|
55888
|
+
};
|
|
55889
|
+
});
|
|
55890
|
+
}
|
|
55891
|
+
function describeBindingHints(hints) {
|
|
55892
|
+
return hints.map((hint) => {
|
|
55893
|
+
const values = hint.allowedValues ? `one of ${hint.allowedValues.join(", ")}` : hint.examples.length > 0 ? `e.g. ${hint.examples.join(", ")}` : "no example in the schema";
|
|
55894
|
+
return `${hint.argument} (${hint.type}, ${values})`;
|
|
55895
|
+
}).join("; ");
|
|
55896
|
+
}
|
|
55897
|
+
var MAX_EXAMPLES = 5;
|
|
55898
|
+
var init_predicate_binding_hints = __esm(() => {
|
|
55899
|
+
init_predicate_bindings();
|
|
55900
|
+
});
|
|
55901
|
+
|
|
55432
55902
|
// ../cli/dist/operations/modeling/suggest-predicates.js
|
|
55433
55903
|
function analyzeInputPropositions(text) {
|
|
55434
55904
|
return analyzeSemanticAdvisorInput({
|
|
@@ -55650,18 +56120,21 @@ async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
55650
56120
|
const existingGrounding = await existingClaimGrounding(prolog, args.requirementId, claimKey, warnings);
|
|
55651
56121
|
const alreadyGrounded = existingGrounding.length > 0;
|
|
55652
56122
|
const completeCandidate = recommendedCandidate && recommendedCandidate.binding_status === "complete" ? recommendedCandidate : undefined;
|
|
55653
|
-
const recommendedAction =
|
|
56123
|
+
const recommendedAction = !recommendedCandidate ? unavailableSchema ? "resolve_schema_reference" : "record_ontology_gap" : completeCandidate ? alreadyGrounded ? "replace_grounding" : "apply_requires_predicate" : "provide_argument_bindings";
|
|
55654
56124
|
const predicatePlan = completeCandidate ? buildPredicateApplyPlan(completeCandidate, args) : [];
|
|
55655
|
-
const applyPlan = alreadyGrounded ? [] :
|
|
56125
|
+
const applyPlan = completeCandidate ? alreadyGrounded ? [] : predicatePlan : !recommendedCandidate && !unavailableSchema ? buildGapApplyPlan(text, args) : [];
|
|
55656
56126
|
const plannedFactId = typeof predicatePlan[0]?.id === "string" ? predicatePlan[0].id : null;
|
|
55657
56127
|
const relationshipPlan = completeCandidate && !alreadyGrounded ? buildRelationshipPlan(plannedFactId ?? "", args.requirementId, text, args.existingLogicClaims) : null;
|
|
55658
|
-
const replacementPlan = alreadyGrounded && plannedFactId !== null && args.requirementId ? buildGroundingReplacementPlan(args.requirementId, plannedFactId, predicatePlan, existingGrounding) : null;
|
|
56128
|
+
const replacementPlan = alreadyGrounded && plannedFactId !== null && args.requirementId ? buildGroundingReplacementPlan(args.requirementId, plannedFactId, predicatePlan, existingGrounding, await storedRequirementProperties(prolog, args.requirementId, warnings)) : null;
|
|
55659
56129
|
const relationshipTarget = relationshipPlan !== null || replacementPlan !== null ? plannedFactId : null;
|
|
56130
|
+
const groundingSummary = existingGrounding.map((row) => `${row.relationship.type} -> ${row.factId}`).join(", ");
|
|
55660
56131
|
if (alreadyGrounded) {
|
|
55661
|
-
warnings.push(`${args.requirementId} already grounds this claim (${claimKey}) through ${
|
|
56132
|
+
warnings.push(`${args.requirementId} already grounds this claim (${claimKey}) through ${groundingSummary}. A modeled claim takes exactly one logical grounding relationship, so adding requires_predicate beside it fails the proposition-complete rule. ${replacementPlan ? "Keep the existing grounding, or follow replacementPlan to swap it for the predicate." : "Keep the existing grounding; no predicate replacement is available yet."}`);
|
|
55662
56133
|
}
|
|
55663
|
-
const
|
|
55664
|
-
const
|
|
56134
|
+
const bindingHints = recommendedAction === "provide_argument_bindings" && recommendedCandidate ? buildBindingHints(recommendedCandidate, text) : [];
|
|
56135
|
+
const recommendedPredicateSchema = !recommendedCandidate && !unavailableSchema ? buildPredicateSchemaDraft(text, subject) : null;
|
|
56136
|
+
const groundedPrefix = alreadyGrounded ? `${args.requirementId} already grounds this claim through ${groundingSummary}. ` : "";
|
|
56137
|
+
const textSummary = groundedPrefix + (replacementPlan ? `To use ${completeCandidate?.predicate_name} instead, follow replacementPlan and link requires_predicate to ${plannedFactId}; otherwise keep the existing grounding.` : completeCandidate ? `Suggested ${candidates.length} predicate candidate(s). Top applicable match: ${completeCandidate.predicate_name}. Apply the predicate fact ${plannedFactId}, then link requires_predicate to that fact id (not a candidate id).` : recommendedCandidate ? `Matched ${recommendedCandidate.predicate_name}, but exact reviewed values are still required for: ${recommendedCandidate.unbound_arguments.join(", ")}. Bind them from the claim text: ${describeBindingHints(bindingHints)}. A value that repeats an argument name or a stop word stays unbound. No apply plan was generated.` : unavailableSchema ? `Requested predicate schema ${args.schemaId} is unavailable or semantically inapplicable. No apply plan was generated.` : alreadyGrounded ? "No predicate candidate passed the semantic applicability gate; keep the existing grounding and record the ontology-gap observation in applyPlan so the missing schema stays visible." : "No predicate candidate passed the semantic applicability gate; record an ontology gap and review the generated schema draft instead of silently writing prose.");
|
|
55665
56138
|
const logicClaims = Array.from(new Set([...args.existingLogicClaims ?? [], claimKey]));
|
|
55666
56139
|
return {
|
|
55667
56140
|
content: [{ type: "text", text: textSummary }],
|
|
@@ -55680,12 +56153,40 @@ async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
55680
56153
|
relationshipTarget,
|
|
55681
56154
|
existingGrounding,
|
|
55682
56155
|
replacementPlan,
|
|
56156
|
+
bindingHints,
|
|
55683
56157
|
warnings
|
|
55684
56158
|
},
|
|
55685
56159
|
applyPlan
|
|
55686
56160
|
};
|
|
55687
56161
|
}
|
|
55688
|
-
function
|
|
56162
|
+
async function storedRequirementProperties(prolog, requirementId, warnings) {
|
|
56163
|
+
if (prolog === null)
|
|
56164
|
+
return null;
|
|
56165
|
+
try {
|
|
56166
|
+
const [stored] = await loadEntities(prolog, {
|
|
56167
|
+
id: requirementId,
|
|
56168
|
+
type: "req"
|
|
56169
|
+
});
|
|
56170
|
+
if (stored === undefined)
|
|
56171
|
+
return null;
|
|
56172
|
+
const restated = {};
|
|
56173
|
+
for (const field of RESTATED_REQUIREMENT_FIELDS)
|
|
56174
|
+
if (stored[field] !== undefined && stored[field] !== null)
|
|
56175
|
+
restated[field] = stored[field];
|
|
56176
|
+
return typeof restated.title === "string" && typeof restated.status === "string" ? restated : null;
|
|
56177
|
+
} catch (error) {
|
|
56178
|
+
warnings.push(`Requirement ${requirementId} could not be read (${error instanceof Error ? error.message : String(error)}); add its stored title and status to the last replacementPlan step before applying it.`);
|
|
56179
|
+
return null;
|
|
56180
|
+
}
|
|
56181
|
+
}
|
|
56182
|
+
function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, existing, stored) {
|
|
56183
|
+
const requirementUpsert = (relationships) => ({
|
|
56184
|
+
type: "req",
|
|
56185
|
+
id: requirementId,
|
|
56186
|
+
...stored === null ? {} : { properties: stored },
|
|
56187
|
+
relationships
|
|
56188
|
+
});
|
|
56189
|
+
const restate = stored === null ? `add the requirement's stored title and status as properties (they could not be read), keep this relationship only` : "the properties restate the stored title, status and metadata; kb_upsert keeps the stored proposition ledger";
|
|
55689
56190
|
return {
|
|
55690
56191
|
relationshipTarget: factId,
|
|
55691
56192
|
steps: [
|
|
@@ -55703,30 +56204,33 @@ function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, exi
|
|
|
55703
56204
|
},
|
|
55704
56205
|
{
|
|
55705
56206
|
operation: "kb_upsert",
|
|
55706
|
-
input:
|
|
55707
|
-
type: "
|
|
55708
|
-
|
|
55709
|
-
|
|
55710
|
-
{ type: "requires_predicate", from: requirementId, to: factId }
|
|
55711
|
-
]
|
|
55712
|
-
},
|
|
55713
|
-
reason: `Link requires_predicate to ${factId}; upsert the requirement with its stored title and status and this relationship only.`
|
|
56207
|
+
input: requirementUpsert([
|
|
56208
|
+
{ type: "requires_predicate", from: requirementId, to: factId }
|
|
56209
|
+
]),
|
|
56210
|
+
reason: `Link requires_predicate to ${factId}; ${restate}.`
|
|
55714
56211
|
}
|
|
55715
56212
|
],
|
|
55716
|
-
|
|
56213
|
+
rollback: {
|
|
56214
|
+
operation: "kb_upsert",
|
|
56215
|
+
input: requirementUpsert(existing.map((row) => row.relationship)),
|
|
56216
|
+
reason: "Only if the last step fails: restore the retracted grounding link so the claim is grounded again."
|
|
56217
|
+
},
|
|
56218
|
+
instructions: `Only replace the grounding when the predicate states the claim at least as precisely as ${existing.map((row) => row.factId).join(", ")}. Apply the steps unchanged, in order and back to back: linking requires_predicate before the retraction is rejected because the claim would have two groundings, and between the retraction and the link the claim is ungrounded, so kb_check reports logic-coverage for ${requirementId} until the last step lands. If the last step fails, apply rollback. Run kb_check after the last step.`
|
|
55717
56219
|
};
|
|
55718
56220
|
}
|
|
55719
56221
|
async function executeSuggestPredicates(args, context) {
|
|
55720
56222
|
return handleKbSuggestPredicates(context.prolog ?? null, args, context);
|
|
55721
56223
|
}
|
|
55722
|
-
var DEFAULT_MAX_CANDIDATES = 5, DEFAULT_MIN_SCORE2 = 0.35, NON_ASSERTIVE_PROPOSITION_ROLES, GROUNDING_RELATIONSHIP_TYPES;
|
|
56224
|
+
var DEFAULT_MAX_CANDIDATES = 5, DEFAULT_MIN_SCORE2 = 0.35, NON_ASSERTIVE_PROPOSITION_ROLES, GROUNDING_RELATIONSHIP_TYPES, RESTATED_REQUIREMENT_FIELDS;
|
|
55723
56225
|
var init_suggest_predicates = __esm(() => {
|
|
56226
|
+
init_discovery_entities();
|
|
55724
56227
|
init_serialization();
|
|
55725
56228
|
init_analyze_prose();
|
|
55726
56229
|
init_clauses();
|
|
55727
56230
|
init_plugin_orchestration();
|
|
55728
56231
|
init_predicate_applicability();
|
|
55729
56232
|
init_predicate_applyplan();
|
|
56233
|
+
init_predicate_binding_hints();
|
|
55730
56234
|
init_predicate_catalog();
|
|
55731
56235
|
init_predicate_inference();
|
|
55732
56236
|
init_predicate_loader();
|
|
@@ -55742,6 +56246,13 @@ var init_suggest_predicates = __esm(() => {
|
|
|
55742
56246
|
"requires_predicate",
|
|
55743
56247
|
"requires_rule"
|
|
55744
56248
|
];
|
|
56249
|
+
RESTATED_REQUIREMENT_FIELDS = [
|
|
56250
|
+
"title",
|
|
56251
|
+
"status",
|
|
56252
|
+
"priority",
|
|
56253
|
+
"owner",
|
|
56254
|
+
"tags"
|
|
56255
|
+
];
|
|
55745
56256
|
});
|
|
55746
56257
|
|
|
55747
56258
|
// ../cli/dist/public/operations/specs/modeling.js
|
|
@@ -59754,7 +60265,7 @@ var init_skills = __esm(() => {
|
|
|
59754
60265
|
});
|
|
59755
60266
|
|
|
59756
60267
|
// ../cli/dist/public/operations/specs/skills.js
|
|
59757
|
-
import { createHash as
|
|
60268
|
+
import { createHash as createHash26 } from "node:crypto";
|
|
59758
60269
|
function assertNonEmptyString(value, field) {
|
|
59759
60270
|
if (typeof value !== "string" || value.trim() === "") {
|
|
59760
60271
|
throw new Error(`${field} must be a non-empty string`);
|
|
@@ -59775,7 +60286,7 @@ async function executeSkillsLoad(input, _context) {
|
|
|
59775
60286
|
assertNonEmptyString(id, "id");
|
|
59776
60287
|
const bundle = loadBundledSkill(id);
|
|
59777
60288
|
const resources = bundle.manifest.resources ?? [];
|
|
59778
|
-
const contentHash =
|
|
60289
|
+
const contentHash = createHash26("sha256").update(bundle.body, "utf8").digest("hex");
|
|
59779
60290
|
const resourceList = resources.length === 0 ? "none" : resources.join(", ");
|
|
59780
60291
|
return {
|
|
59781
60292
|
content: [
|
|
@@ -61532,16 +62043,16 @@ var init_audit = __esm(() => {
|
|
|
61532
62043
|
});
|
|
61533
62044
|
|
|
61534
62045
|
// ../cli/dist/operations/mutation/source-authoring.js
|
|
61535
|
-
import { createHash as
|
|
62046
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
61536
62047
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
61537
62048
|
import fs6 from "node:fs";
|
|
61538
62049
|
import path50 from "node:path";
|
|
61539
62050
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
61540
|
-
function
|
|
61541
|
-
return
|
|
62051
|
+
function digest3(value) {
|
|
62052
|
+
return createHash27("sha256").update(value).digest("hex");
|
|
61542
62053
|
}
|
|
61543
62054
|
function pendingReceiptPath(workspaceRoot, relativePath) {
|
|
61544
|
-
return path50.join(workspaceRoot, ".kb", "recovery", "pending-sources", `${
|
|
62055
|
+
return path50.join(workspaceRoot, ".kb", "recovery", "pending-sources", `${digest3(relativePath)}.json`);
|
|
61545
62056
|
}
|
|
61546
62057
|
function writePendingSourceReceipt(workspaceRoot, relativePath, afterHash) {
|
|
61547
62058
|
const receiptPath = pendingReceiptPath(workspaceRoot, relativePath);
|
|
@@ -62048,8 +62559,8 @@ async function writeSourceForUpsert(input, entity, existing, context, sourceDocu
|
|
|
62048
62559
|
const receipt = {
|
|
62049
62560
|
path: relative,
|
|
62050
62561
|
mode: "write",
|
|
62051
|
-
beforeHash: before === undefined ? null :
|
|
62052
|
-
afterHash:
|
|
62562
|
+
beforeHash: before === undefined ? null : digest3(before),
|
|
62563
|
+
afterHash: digest3(after),
|
|
62053
62564
|
created: before === undefined
|
|
62054
62565
|
};
|
|
62055
62566
|
const rollback = async () => {
|
|
@@ -62062,7 +62573,7 @@ async function writeSourceForUpsert(input, entity, existing, context, sourceDocu
|
|
|
62062
62573
|
} catch {
|
|
62063
62574
|
current = undefined;
|
|
62064
62575
|
}
|
|
62065
|
-
if (current !== undefined &&
|
|
62576
|
+
if (current !== undefined && digest3(current) !== digest3(after)) {
|
|
62066
62577
|
writePendingSourceReceipt(context.workspaceRoot, relative, receipt.afterHash);
|
|
62067
62578
|
console.warn(`Skipped source rollback for ${relative}: file changed after the Kibi write; kept concurrent content and recorded recovery metadata.`);
|
|
62068
62579
|
return;
|
|
@@ -62132,7 +62643,7 @@ var init_source_authoring = __esm(() => {
|
|
|
62132
62643
|
});
|
|
62133
62644
|
|
|
62134
62645
|
// ../cli/dist/operations/mutation/plan-apply-journal.js
|
|
62135
|
-
import { createHash as
|
|
62646
|
+
import { createHash as createHash28, randomUUID as randomUUID3 } from "node:crypto";
|
|
62136
62647
|
import { closeSync as closeSync3, existsSync as existsSync26, fsyncSync as fsyncSync2, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync27, readdirSync as readdirSync8, renameSync as renameSync5, statSync as statSync10, unlinkSync as unlinkSync5, writeSync as writeSync2 } from "node:fs";
|
|
62137
62648
|
import path51 from "node:path";
|
|
62138
62649
|
function planApplyJournalId(planHash) {
|
|
@@ -62142,7 +62653,7 @@ function isPlanApplyJournalId(value) {
|
|
|
62142
62653
|
return JOURNAL_ID_PATTERN.test(value);
|
|
62143
62654
|
}
|
|
62144
62655
|
function contentHash(value) {
|
|
62145
|
-
return
|
|
62656
|
+
return createHash28("sha256").update(value).digest("hex");
|
|
62146
62657
|
}
|
|
62147
62658
|
function errorText(error) {
|
|
62148
62659
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -62919,7 +63430,7 @@ var init_workspace_mutation_lock = __esm(() => {
|
|
|
62919
63430
|
});
|
|
62920
63431
|
|
|
62921
63432
|
// ../cli/dist/operations/mutation/delete.js
|
|
62922
|
-
import { createHash as
|
|
63433
|
+
import { createHash as createHash29, randomUUID as randomUUID4 } from "node:crypto";
|
|
62923
63434
|
import { existsSync as existsSync27, readFileSync as readFileSync29, writeFileSync as writeFileSync9 } from "node:fs";
|
|
62924
63435
|
import path53 from "node:path";
|
|
62925
63436
|
function requireProlog3(context) {
|
|
@@ -62957,7 +63468,7 @@ function sourceIsAuthored(source) {
|
|
|
62957
63468
|
function fileHash(pathname) {
|
|
62958
63469
|
if (!existsSync27(pathname))
|
|
62959
63470
|
return null;
|
|
62960
|
-
return
|
|
63471
|
+
return createHash29("sha256").update(readFileSync29(pathname)).digest("hex");
|
|
62961
63472
|
}
|
|
62962
63473
|
async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted = () => {
|
|
62963
63474
|
return;
|
|
@@ -63151,8 +63662,8 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
|
|
|
63151
63662
|
];
|
|
63152
63663
|
});
|
|
63153
63664
|
sourceWrites.push(...Array.from(sourcePatches, ([relative, patch]) => {
|
|
63154
|
-
const beforeHash =
|
|
63155
|
-
const afterHash =
|
|
63665
|
+
const beforeHash = createHash29("sha256").update(patch.before).digest("hex");
|
|
63666
|
+
const afterHash = createHash29("sha256").update(patch.after).digest("hex");
|
|
63156
63667
|
writePendingSourceReceipt(context.workspaceRoot, relative, afterHash);
|
|
63157
63668
|
return {
|
|
63158
63669
|
path: relative,
|
|
@@ -63284,8 +63795,8 @@ async function executeDelete(input, context) {
|
|
|
63284
63795
|
}
|
|
63285
63796
|
const deletion = renderSourceDeletion(relativeSource, id, String(entity.type), contents);
|
|
63286
63797
|
evolvingSourceBodies.set(relativeSource, deletion.mode === "write" ? deletion.body : undefined);
|
|
63287
|
-
const beforeHash =
|
|
63288
|
-
const afterHash = deletion.body === undefined ? null :
|
|
63798
|
+
const beforeHash = createHash29("sha256").update(original).digest("hex");
|
|
63799
|
+
const afterHash = deletion.body === undefined ? null : createHash29("sha256").update(deletion.body).digest("hex");
|
|
63289
63800
|
sourceHashes[relativeSource] = beforeHash;
|
|
63290
63801
|
sourcePlansByPath.set(relativeSource, {
|
|
63291
63802
|
path: relativeSource,
|
|
@@ -63311,13 +63822,13 @@ async function executeDelete(input, context) {
|
|
|
63311
63822
|
const relativeShard = path53.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
|
|
63312
63823
|
const original = readFileSync29(shardPath, "utf8");
|
|
63313
63824
|
const body = renderShardWithout(original, selectors, shardPath);
|
|
63314
|
-
const beforeHash =
|
|
63825
|
+
const beforeHash = createHash29("sha256").update(original).digest("hex");
|
|
63315
63826
|
sourceHashes[relativeShard] = beforeHash;
|
|
63316
63827
|
sourcePlansByPath.set(relativeShard, {
|
|
63317
63828
|
path: relativeShard,
|
|
63318
63829
|
mode: "write",
|
|
63319
63830
|
beforeHash,
|
|
63320
|
-
afterHash:
|
|
63831
|
+
afterHash: createHash29("sha256").update(body).digest("hex"),
|
|
63321
63832
|
body
|
|
63322
63833
|
});
|
|
63323
63834
|
}
|
|
@@ -63331,7 +63842,7 @@ async function executeDelete(input, context) {
|
|
|
63331
63842
|
sourceWrites: sourcePlans,
|
|
63332
63843
|
supersessionRequired
|
|
63333
63844
|
};
|
|
63334
|
-
const planHash =
|
|
63845
|
+
const planHash = createHash29("sha256").update(JSON.stringify(planBody)).digest("hex");
|
|
63335
63846
|
const payload = {
|
|
63336
63847
|
deleted: 0,
|
|
63337
63848
|
skipped: authoredIds.length,
|
|
@@ -64265,7 +64776,7 @@ var init_symbols_coordinator2 = __esm(() => {
|
|
|
64265
64776
|
});
|
|
64266
64777
|
|
|
64267
64778
|
// ../cli/dist/operations/mutation/symbol-refresh.js
|
|
64268
|
-
import { createHash as
|
|
64779
|
+
import { createHash as createHash30, randomUUID as randomUUID5 } from "node:crypto";
|
|
64269
64780
|
import { existsSync as existsSync29, readFileSync as readFileSync33, renameSync as renameSync7, unlinkSync as unlinkSync8, writeFileSync as writeFileSync11 } from "node:fs";
|
|
64270
64781
|
import * as path58 from "node:path";
|
|
64271
64782
|
function record2(value) {
|
|
@@ -64292,7 +64803,7 @@ function sourceTextFor(sourceFile, workspaceRoot) {
|
|
|
64292
64803
|
}
|
|
64293
64804
|
}
|
|
64294
64805
|
function contentHash2(content) {
|
|
64295
|
-
return
|
|
64806
|
+
return createHash30("sha256").update(content).digest("hex");
|
|
64296
64807
|
}
|
|
64297
64808
|
function restoreOrUnlinkCoordinateArtifact(targetPath, before) {
|
|
64298
64809
|
if (before === null) {
|
|
@@ -64492,7 +65003,7 @@ async function scenarioCoverageWarnings(prolog, relationships, entityType, entit
|
|
|
64492
65003
|
var init_warnings = () => {};
|
|
64493
65004
|
|
|
64494
65005
|
// ../cli/dist/operations/mutation/upsert.js
|
|
64495
|
-
import { createHash as
|
|
65006
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
64496
65007
|
import { existsSync as existsSync30, readFileSync as readFileSync34, unlinkSync as unlinkSync9, writeFileSync as writeFileSync12 } from "node:fs";
|
|
64497
65008
|
import path59 from "node:path";
|
|
64498
65009
|
function requireProlog4(context) {
|
|
@@ -64513,10 +65024,10 @@ function parseChangeKind(value) {
|
|
|
64513
65024
|
function fileHash2(pathname) {
|
|
64514
65025
|
if (!existsSync30(pathname))
|
|
64515
65026
|
return null;
|
|
64516
|
-
return
|
|
65027
|
+
return createHash31("sha256").update(readFileSync34(pathname)).digest("hex");
|
|
64517
65028
|
}
|
|
64518
65029
|
function textHash(value) {
|
|
64519
|
-
return
|
|
65030
|
+
return createHash31("sha256").update(value).digest("hex");
|
|
64520
65031
|
}
|
|
64521
65032
|
function assertRelationshipShardContained(workspaceRoot, shardPath) {
|
|
64522
65033
|
const root = path59.resolve(workspaceRoot);
|
|
@@ -66810,7 +67321,7 @@ var init_staging = __esm(() => {
|
|
|
66810
67321
|
|
|
66811
67322
|
// ../cli/dist/commands/sync.js
|
|
66812
67323
|
import { execSync as execSync4 } from "node:child_process";
|
|
66813
|
-
import { createHash as
|
|
67324
|
+
import { createHash as createHash32 } from "node:crypto";
|
|
66814
67325
|
import { existsSync as existsSync34, mkdirSync as mkdirSync12, readFileSync as readFileSync37, readdirSync as readdirSync9, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
|
|
66815
67326
|
import * as path64 from "node:path";
|
|
66816
67327
|
function relationshipKey2(relationship) {
|
|
@@ -66883,14 +67394,14 @@ function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissin
|
|
|
66883
67394
|
receiptPath,
|
|
66884
67395
|
path: relative,
|
|
66885
67396
|
afterHash: receipt.afterHash,
|
|
66886
|
-
rawHash:
|
|
67397
|
+
rawHash: createHash32("sha256").update(readFileSync37(receiptPath)).digest("hex")
|
|
66887
67398
|
});
|
|
66888
67399
|
}
|
|
66889
67400
|
continue;
|
|
66890
67401
|
}
|
|
66891
67402
|
throw new SyncError(`Pending source is missing: ${relative}.${PENDING_SOURCE_RECOVERY_HINT}`);
|
|
66892
67403
|
}
|
|
66893
|
-
const actual =
|
|
67404
|
+
const actual = createHash32("sha256").update(readFileSync37(absolute)).digest("hex");
|
|
66894
67405
|
if (actual !== receipt.afterHash) {
|
|
66895
67406
|
throw new SyncError(`Pending source hash drift blocks sync for ${relative}`);
|
|
66896
67407
|
}
|
|
@@ -67751,14 +68262,14 @@ var init_sync = __esm(() => {
|
|
|
67751
68262
|
});
|
|
67752
68263
|
|
|
67753
68264
|
// ../cli/dist/commands/branch.js
|
|
67754
|
-
import { createHash as
|
|
68265
|
+
import { createHash as createHash33 } from "node:crypto";
|
|
67755
68266
|
import * as fs8 from "node:fs";
|
|
67756
68267
|
import * as path65 from "node:path";
|
|
67757
68268
|
function isSupportedLegacyBranchMigration(from, to) {
|
|
67758
68269
|
return from === to;
|
|
67759
68270
|
}
|
|
67760
68271
|
function hashLegacyStore(sourcePath) {
|
|
67761
|
-
const hash =
|
|
68272
|
+
const hash = createHash33("sha256");
|
|
67762
68273
|
const visit = (directory, relative = "") => {
|
|
67763
68274
|
for (const entry of fs8.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name))) {
|
|
67764
68275
|
const absolute = path65.join(directory, entry.name);
|
|
@@ -67778,7 +68289,7 @@ function hashLegacyStore(sourcePath) {
|
|
|
67778
68289
|
}
|
|
67779
68290
|
function branchMigrationApprovalHash(from, to, sourcePath, targetPath) {
|
|
67780
68291
|
const sourceHash = hashLegacyStore(sourcePath);
|
|
67781
|
-
return
|
|
68292
|
+
return createHash33("sha256").update(JSON.stringify({
|
|
67782
68293
|
version: 2,
|
|
67783
68294
|
from,
|
|
67784
68295
|
to,
|
|
@@ -68071,7 +68582,7 @@ var init_branch = __esm(() => {
|
|
|
68071
68582
|
});
|
|
68072
68583
|
|
|
68073
68584
|
// ../cli/dist/operations/migration/inventory-rederive.js
|
|
68074
|
-
import { createHash as
|
|
68585
|
+
import { createHash as createHash34 } from "node:crypto";
|
|
68075
68586
|
import path66 from "node:path";
|
|
68076
68587
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
68077
68588
|
function isRecord17(value) {
|
|
@@ -68288,7 +68799,7 @@ function planOne(workspaceRoot, relativePath, entity, extracted, shards, facts)
|
|
|
68288
68799
|
summary: summarize2(changes, inventory),
|
|
68289
68800
|
changes,
|
|
68290
68801
|
contract,
|
|
68291
|
-
contractHash:
|
|
68802
|
+
contractHash: createHash34("sha256").update(canonicalJson3(contract)).digest("hex")
|
|
68292
68803
|
};
|
|
68293
68804
|
}
|
|
68294
68805
|
function readShardRelationships(workspaceRoot) {
|
|
@@ -68861,7 +69372,7 @@ ${KIBI_BIN_RESOLVER}
|
|
|
68861
69372
|
});
|
|
68862
69373
|
|
|
68863
69374
|
// ../cli/dist/commands/legacy-storage-migration.js
|
|
68864
|
-
import { createHash as
|
|
69375
|
+
import { createHash as createHash35 } from "node:crypto";
|
|
68865
69376
|
import { existsSync as existsSync37, mkdirSync as mkdirSync15, readFileSync as readFileSync40, readdirSync as readdirSync11, renameSync as renameSync12, rmSync as rmSync5, statSync as statSync12, writeFileSync as writeFileSync18 } from "node:fs";
|
|
68866
69377
|
import * as path70 from "node:path";
|
|
68867
69378
|
function stripGlobToRoot(pattern) {
|
|
@@ -69047,7 +69558,7 @@ function rewritePendingSourceReceiptPaths(cwd, moves) {
|
|
|
69047
69558
|
const absolute = path70.resolve(cwd, destination);
|
|
69048
69559
|
if (!existsSync37(absolute))
|
|
69049
69560
|
continue;
|
|
69050
|
-
const afterHash = typeof receipt.afterHash === "string" && /^[a-f0-9]{64}$/i.test(receipt.afterHash) ? receipt.afterHash :
|
|
69561
|
+
const afterHash = typeof receipt.afterHash === "string" && /^[a-f0-9]{64}$/i.test(receipt.afterHash) ? receipt.afterHash : createHash35("sha256").update(readFileSync40(absolute)).digest("hex");
|
|
69051
69562
|
writeFileSync18(receiptPath, `${JSON.stringify({ ...receipt, path: destination, afterHash }, null, 2)}
|
|
69052
69563
|
`, "utf8");
|
|
69053
69564
|
rewritten += 1;
|
|
@@ -69784,7 +70295,7 @@ var init_ignore_policy = __esm(() => {
|
|
|
69784
70295
|
|
|
69785
70296
|
// ../cli/dist/public/operations/node-ports.js
|
|
69786
70297
|
import { execFile as execFile2, execFileSync as execFileSync8 } from "node:child_process";
|
|
69787
|
-
import { createHash as
|
|
70298
|
+
import { createHash as createHash36 } from "node:crypto";
|
|
69788
70299
|
import * as fsSync from "node:fs";
|
|
69789
70300
|
import * as fs9 from "node:fs/promises";
|
|
69790
70301
|
import path72 from "node:path";
|
|
@@ -69814,7 +70325,7 @@ async function workspaceSnapshot(workspaceRoot) {
|
|
|
69814
70325
|
"-z"
|
|
69815
70326
|
], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 });
|
|
69816
70327
|
const paths = listed.toString("utf8").split("\x00").filter(Boolean).filter(includedSnapshotPath).map((raw) => ({ raw, key: raw.normalize("NFC") })).sort((left, right) => left.key < right.key ? -1 : left.key > right.key ? 1 : 0);
|
|
69817
|
-
const digest =
|
|
70328
|
+
const digest = createHash36("sha256");
|
|
69818
70329
|
digest.update("kibi.workspace-snapshot.v2\x00");
|
|
69819
70330
|
for (const { raw, key: relativePath } of paths) {
|
|
69820
70331
|
digest.update(relativePath);
|
|
@@ -70205,7 +70716,7 @@ var init_cli_runtime = __esm(() => {
|
|
|
70205
70716
|
});
|
|
70206
70717
|
|
|
70207
70718
|
// ../cli/dist/public/operations/legacy-migration-plan.js
|
|
70208
|
-
import { createHash as
|
|
70719
|
+
import { createHash as createHash37 } from "node:crypto";
|
|
70209
70720
|
function isRecord20(value) {
|
|
70210
70721
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
70211
70722
|
}
|
|
@@ -70240,7 +70751,7 @@ function stableStringify(value) {
|
|
|
70240
70751
|
return JSON.stringify(stableValue3(value));
|
|
70241
70752
|
}
|
|
70242
70753
|
function hash(value) {
|
|
70243
|
-
return
|
|
70754
|
+
return createHash37("sha256").update(stableStringify(value)).digest("hex");
|
|
70244
70755
|
}
|
|
70245
70756
|
function migrationRepairBatches(plan) {
|
|
70246
70757
|
const seen = new Set;
|
|
@@ -70562,7 +71073,7 @@ var init_legacy_migration_plan = __esm(() => {
|
|
|
70562
71073
|
});
|
|
70563
71074
|
|
|
70564
71075
|
// ../cli/dist/public/operations/repair-plan.js
|
|
70565
|
-
import { createHash as
|
|
71076
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
70566
71077
|
function isRecord21(value) {
|
|
70567
71078
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
70568
71079
|
}
|
|
@@ -70705,7 +71216,7 @@ function buildRepairPlan(payload, input, codeSnapshot) {
|
|
|
70705
71216
|
},
|
|
70706
71217
|
batches
|
|
70707
71218
|
};
|
|
70708
|
-
const planId = `repair-plan-${
|
|
71219
|
+
const planId = `repair-plan-${createHash38("sha256").update(stableStringify2(planCore)).digest("hex").slice(0, 24)}`;
|
|
70709
71220
|
return {
|
|
70710
71221
|
version: REPAIR_PLAN_VERSION,
|
|
70711
71222
|
planId,
|
|
@@ -73807,7 +74318,7 @@ var init_migrate = __esm(() => {
|
|
|
73807
74318
|
});
|
|
73808
74319
|
|
|
73809
74320
|
// ../cli/dist/operations/planning/compile-intent.js
|
|
73810
|
-
import { createHash as
|
|
74321
|
+
import { createHash as createHash39 } from "node:crypto";
|
|
73811
74322
|
import path77 from "node:path";
|
|
73812
74323
|
function compilePlanHash(plan) {
|
|
73813
74324
|
const { planHash: _ignored, ...body } = plan;
|
|
@@ -73817,7 +74328,7 @@ function text7(value) {
|
|
|
73817
74328
|
return typeof value === "string" ? value.trim() : "";
|
|
73818
74329
|
}
|
|
73819
74330
|
function hash2(value) {
|
|
73820
|
-
return
|
|
74331
|
+
return createHash39("sha256").update(canonicalize(value)).digest("hex");
|
|
73821
74332
|
}
|
|
73822
74333
|
function shortHash2(value, length = 8) {
|
|
73823
74334
|
return hash2(value).slice(0, length);
|
|
@@ -73964,7 +74475,7 @@ async function sourceHashes(context, locations) {
|
|
|
73964
74475
|
for (const relative of sourceFilesFor(locations)) {
|
|
73965
74476
|
try {
|
|
73966
74477
|
const contents = context.fs ? await context.fs.readFile(path77.join(context.workspaceRoot, relative)) : null;
|
|
73967
|
-
hashes[relative] = contents === null ? null :
|
|
74478
|
+
hashes[relative] = contents === null ? null : createHash39("sha256").update(contents).digest("hex");
|
|
73968
74479
|
} catch {
|
|
73969
74480
|
hashes[relative] = null;
|
|
73970
74481
|
}
|
|
@@ -74549,7 +75060,7 @@ var init_compile_intent = __esm(() => {
|
|
|
74549
75060
|
});
|
|
74550
75061
|
|
|
74551
75062
|
// ../cli/dist/operations/planning/apply-plan.js
|
|
74552
|
-
import { createHash as
|
|
75063
|
+
import { createHash as createHash40, randomUUID as randomUUID6 } from "node:crypto";
|
|
74553
75064
|
import path78 from "node:path";
|
|
74554
75065
|
function text8(value) {
|
|
74555
75066
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -74557,8 +75068,8 @@ function text8(value) {
|
|
|
74557
75068
|
function isRecord23(value) {
|
|
74558
75069
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
74559
75070
|
}
|
|
74560
|
-
function
|
|
74561
|
-
return
|
|
75071
|
+
function digest4(value) {
|
|
75072
|
+
return createHash40("sha256").update(value).digest("hex");
|
|
74562
75073
|
}
|
|
74563
75074
|
function relationships(step) {
|
|
74564
75075
|
if (!Array.isArray(step.relationships))
|
|
@@ -74722,7 +75233,7 @@ function validateEntityDeletionPlan(args) {
|
|
|
74722
75233
|
throw new Error("Entity deletion apply failed: approvedPlanHash does not match planHash");
|
|
74723
75234
|
}
|
|
74724
75235
|
const { planHash: _ignored, ...body } = args.plan;
|
|
74725
|
-
if (
|
|
75236
|
+
if (createHash40("sha256").update(JSON.stringify(body)).digest("hex") !== args.plan.planHash) {
|
|
74726
75237
|
throw new Error("Entity deletion apply failed: planHash does not match the canonical plan body");
|
|
74727
75238
|
}
|
|
74728
75239
|
if (!Array.isArray(args.plan.entityIds) || args.plan.entityIds.length === 0) {
|
|
@@ -74801,7 +75312,7 @@ async function validateSources(context, sourceHashes) {
|
|
|
74801
75312
|
throw new Error("Apply plan failed: source hashes require a filesystem-capable runtime");
|
|
74802
75313
|
let actual;
|
|
74803
75314
|
try {
|
|
74804
|
-
actual =
|
|
75315
|
+
actual = digest4(await context.fs.readFile(path78.join(context.workspaceRoot, relative)));
|
|
74805
75316
|
} catch {
|
|
74806
75317
|
actual = null;
|
|
74807
75318
|
}
|
|
@@ -74830,12 +75341,12 @@ async function resolveSourceWriteTarget(workspaceRoot, fsPort, write) {
|
|
|
74830
75341
|
const existing = await fsPort.readFile(absolute).catch(() => {
|
|
74831
75342
|
return;
|
|
74832
75343
|
});
|
|
74833
|
-
const beforeHash = existing === undefined ? null :
|
|
75344
|
+
const beforeHash = existing === undefined ? null : digest4(existing);
|
|
74834
75345
|
if (beforeHash !== write.beforeHash) {
|
|
74835
75346
|
throw new Error(`Apply plan failed: source hash changed for ${write.path}`);
|
|
74836
75347
|
}
|
|
74837
75348
|
const mode = write.mode ?? "write";
|
|
74838
|
-
if (mode === "write" && (write.body === undefined || write.afterHash === null ||
|
|
75349
|
+
if (mode === "write" && (write.body === undefined || write.afterHash === null || digest4(write.body) !== write.afterHash)) {
|
|
74839
75350
|
throw new Error(`Apply plan failed: afterHash does not match staged body for ${write.path}`);
|
|
74840
75351
|
}
|
|
74841
75352
|
if (mode === "delete" && write.afterHash !== null) {
|
|
@@ -74879,7 +75390,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
74879
75390
|
for (const entry of prior.entries) {
|
|
74880
75391
|
try {
|
|
74881
75392
|
const current = await context.fs.readFile(path78.resolve(context.workspaceRoot, entry.path));
|
|
74882
|
-
if (entry.afterHash === null ||
|
|
75393
|
+
if (entry.afterHash === null || digest4(current) !== entry.afterHash) {
|
|
74883
75394
|
allAfter = false;
|
|
74884
75395
|
}
|
|
74885
75396
|
} catch {
|
|
@@ -74907,7 +75418,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
74907
75418
|
} catch {
|
|
74908
75419
|
current = undefined;
|
|
74909
75420
|
}
|
|
74910
|
-
const currentHash = current === undefined ? null :
|
|
75421
|
+
const currentHash = current === undefined ? null : digest4(current);
|
|
74911
75422
|
if (currentHash !== entry.beforeHash && currentHash !== entry.afterHash) {
|
|
74912
75423
|
throw new Error(`Apply plan recovery refused: ${entry.path} changed outside its journal`);
|
|
74913
75424
|
}
|
|
@@ -75103,15 +75614,7 @@ async function executeSourceRecovery(args, context, onCommitted = () => {
|
|
|
75103
75614
|
}
|
|
75104
75615
|
};
|
|
75105
75616
|
}
|
|
75106
|
-
async function
|
|
75107
|
-
return;
|
|
75108
|
-
}, carry = {}) {
|
|
75109
|
-
const actions = recovery ? [...remainingActions ?? args.plan.actions] : validateBootstrapPlanShape(args);
|
|
75110
|
-
preflightBootstrapActions(actions, context);
|
|
75111
|
-
const prolog = context.prolog ?? await context.ensureProlog?.();
|
|
75112
|
-
if (!prolog)
|
|
75113
|
-
throw new Error("Bootstrap apply requires a Prolog runtime");
|
|
75114
|
-
const operationContext = { ...context, prolog, sourceFirst: true };
|
|
75617
|
+
async function assertBootstrapPlanCurrent(args, operationContext) {
|
|
75115
75618
|
const statusResult = await executeStatus({}, operationContext);
|
|
75116
75619
|
const status = statusResult.structuredContent;
|
|
75117
75620
|
if (!status)
|
|
@@ -75122,15 +75625,56 @@ async function executeBootstrapPlan(args, context, recovery = false, remainingAc
|
|
|
75122
75625
|
workspaceSnapshot: workspace.snapshot.hash,
|
|
75123
75626
|
sourceHashes: args.plan.expected.sourceHashes
|
|
75124
75627
|
}) : status.snapshotId;
|
|
75125
|
-
if (
|
|
75126
|
-
|
|
75127
|
-
|
|
75128
|
-
|
|
75129
|
-
|
|
75130
|
-
|
|
75131
|
-
|
|
75132
|
-
|
|
75628
|
+
if (args.plan.expected.branch !== "unknown" && status.branch !== args.plan.expected.branch)
|
|
75629
|
+
throw new Error("Bootstrap apply failed: branch changed since planning");
|
|
75630
|
+
if (boundLiveKbSnapshot !== args.plan.expected.kbSnapshotId)
|
|
75631
|
+
throw new Error("Bootstrap apply failed: KB snapshot changed since planning");
|
|
75632
|
+
if (args.plan.expected.workspaceSnapshot !== "unknown" && (!workspace.available || workspace.snapshot.hash !== args.plan.expected.workspaceSnapshot))
|
|
75633
|
+
throw new Error("Bootstrap apply failed: workspace snapshot changed since planning");
|
|
75634
|
+
await validateSources(operationContext, args.plan.expected.sourceHashes);
|
|
75635
|
+
return status;
|
|
75636
|
+
}
|
|
75637
|
+
async function preflightApplyPlan(args, context) {
|
|
75638
|
+
if (!("plan" in args))
|
|
75639
|
+
return;
|
|
75640
|
+
if (!isRecord23(args.plan))
|
|
75641
|
+
throw new Error("Apply plan failed: plan must be an object");
|
|
75642
|
+
if (typeof args.approvedPlanHash !== "string" || !/^[a-f0-9]{64}$/i.test(args.approvedPlanHash))
|
|
75643
|
+
throw new Error("Apply plan failed: approvedPlanHash must be the SHA-256 planHash returned with the plan");
|
|
75644
|
+
if (isBootstrapApplyArgs(args)) {
|
|
75645
|
+
preflightBootstrapActions(validateBootstrapPlanShape(args), context);
|
|
75646
|
+
const prolog = context.prolog ?? await context.ensureProlog?.();
|
|
75647
|
+
if (!prolog)
|
|
75648
|
+
throw new Error("Bootstrap apply requires a Prolog runtime");
|
|
75649
|
+
await assertBootstrapPlanCurrent(args, {
|
|
75650
|
+
...context,
|
|
75651
|
+
prolog,
|
|
75652
|
+
sourceFirst: true
|
|
75653
|
+
});
|
|
75654
|
+
return;
|
|
75133
75655
|
}
|
|
75656
|
+
if (isMigrationApplyArgs(args)) {
|
|
75657
|
+
validateMigrationPlanShape(args);
|
|
75658
|
+
return;
|
|
75659
|
+
}
|
|
75660
|
+
if (isEntityDeletionApplyArgs(args)) {
|
|
75661
|
+
validateEntityDeletionPlan(args);
|
|
75662
|
+
return;
|
|
75663
|
+
}
|
|
75664
|
+
validateCompilePlanShape(args);
|
|
75665
|
+
}
|
|
75666
|
+
async function executeBootstrapPlan(args, context, recovery = false, remainingActions, priorResults = [], onCommitted = () => {
|
|
75667
|
+
return;
|
|
75668
|
+
}, carry = {}) {
|
|
75669
|
+
const actions = recovery ? [...remainingActions ?? args.plan.actions] : validateBootstrapPlanShape(args);
|
|
75670
|
+
preflightBootstrapActions(actions, context);
|
|
75671
|
+
const prolog = context.prolog ?? await context.ensureProlog?.();
|
|
75672
|
+
if (!prolog)
|
|
75673
|
+
throw new Error("Bootstrap apply requires a Prolog runtime");
|
|
75674
|
+
const operationContext = { ...context, prolog, sourceFirst: true };
|
|
75675
|
+
const status = recovery ? (await executeStatus({}, operationContext)).structuredContent : await assertBootstrapPlanCurrent(args, operationContext);
|
|
75676
|
+
if (!status)
|
|
75677
|
+
throw new Error("Bootstrap apply failed: status returned no payload");
|
|
75134
75678
|
const journalId = `bootstrap-${args.plan.planHash.slice(0, 16)}`;
|
|
75135
75679
|
const journalPath = path78.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
|
|
75136
75680
|
if (!recovery && context.fs) {
|
|
@@ -76454,7 +76998,8 @@ __export(exports_planning, {
|
|
|
76454
76998
|
applyPlanSpec: () => applyPlanSpec,
|
|
76455
76999
|
compileIntentSpec: () => compileIntentSpec,
|
|
76456
77000
|
executeApplyPlan: () => executeApplyPlan,
|
|
76457
|
-
executeCompileIntent: () => executeCompileIntent
|
|
77001
|
+
executeCompileIntent: () => executeCompileIntent,
|
|
77002
|
+
preflightApplyPlan: () => preflightApplyPlan
|
|
76458
77003
|
});
|
|
76459
77004
|
var compileIntentSpec, applyPlanSpec;
|
|
76460
77005
|
var init_planning = __esm(() => {
|
|
@@ -77765,7 +78310,7 @@ init_generate();
|
|
|
77765
78310
|
init_presentation();
|
|
77766
78311
|
init_ir();
|
|
77767
78312
|
// src/skill-operations.ts
|
|
77768
|
-
import { createHash as
|
|
78313
|
+
import { createHash as createHash41 } from "node:crypto";
|
|
77769
78314
|
|
|
77770
78315
|
// src/skill-system/loader.ts
|
|
77771
78316
|
import { existsSync as existsSync44, readFileSync as readFileSync47, readdirSync as readdirSync13, realpathSync as realpathSync10 } from "node:fs";
|
|
@@ -78037,7 +78582,7 @@ async function executeSkillsLoad2(input, _context) {
|
|
|
78037
78582
|
assertNonEmptyString2(id, "id");
|
|
78038
78583
|
const bundle = loadBundledSkill2(id);
|
|
78039
78584
|
const resources = bundle.manifest.resources ?? [];
|
|
78040
|
-
const contentHash =
|
|
78585
|
+
const contentHash = createHash41("sha256").update(bundle.body, "utf8").digest("hex");
|
|
78041
78586
|
const resourceList = resources.length === 0 ? "none" : resources.join(", ");
|
|
78042
78587
|
return {
|
|
78043
78588
|
content: [
|
|
@@ -78511,6 +79056,7 @@ export {
|
|
|
78511
79056
|
paginateResults,
|
|
78512
79057
|
parseEnvContent,
|
|
78513
79058
|
planBootstrapSpec,
|
|
79059
|
+
preflightApplyPlan,
|
|
78514
79060
|
prepareImpactReviewSpec,
|
|
78515
79061
|
presentBootstrap,
|
|
78516
79062
|
queryLimitExceededOf,
|