kibi-runtime 2.8.0 → 2.10.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
|
@@ -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
|
}
|
|
@@ -27449,6 +27454,46 @@ function claimFor(statement, source, confidence, provenance) {
|
|
|
27449
27454
|
function snakeSegment(value) {
|
|
27450
27455
|
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
27451
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
|
+
}
|
|
27452
27497
|
function resolveBootstrapSubjectKey(subject, propertyKey, component) {
|
|
27453
27498
|
const stripped = subject.trim().replace(/^(?:the|a|an)\s+/i, "");
|
|
27454
27499
|
let key;
|
|
@@ -27462,25 +27507,226 @@ function resolveBootstrapSubjectKey(subject, propertyKey, component) {
|
|
|
27462
27507
|
const flat = key.replace(/\./g, "_");
|
|
27463
27508
|
const comp = component === undefined ? "" : snakeSegment(component);
|
|
27464
27509
|
const property = snakeSegment(propertyKey);
|
|
27465
|
-
let candidate;
|
|
27466
27510
|
if (comp) {
|
|
27467
27511
|
const aspect = flat === comp ? property : flat.startsWith(`${comp}_`) ? flat.slice(comp.length + 1) : flat;
|
|
27468
|
-
|
|
27469
|
-
} else if (/^[a-z][a-z0-9]*$/.test(flat) && property) {
|
|
27470
|
-
candidate = `${flat}.${property}`;
|
|
27471
|
-
} else {
|
|
27472
|
-
return {
|
|
27473
|
-
ok: false,
|
|
27474
|
-
reason: `subject key "${flat}" names no component, so it would violate component.aspect[.sub]`
|
|
27475
|
-
};
|
|
27512
|
+
return withShortAspect(comp, aspect);
|
|
27476
27513
|
}
|
|
27477
|
-
|
|
27514
|
+
if (/^[a-z][a-z0-9]*$/.test(flat) && property)
|
|
27515
|
+
return withShortAspect(flat, property);
|
|
27516
|
+
return {
|
|
27478
27517
|
ok: false,
|
|
27479
|
-
reason: `subject key "${
|
|
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
|
+
function stepProperties2(step) {
|
|
27570
|
+
return step.properties !== null && typeof step.properties === "object" ? step.properties : {};
|
|
27571
|
+
}
|
|
27572
|
+
function subjectStepKey(step) {
|
|
27573
|
+
const properties = stepProperties2(step);
|
|
27574
|
+
return step.type === "fact" && properties.fact_kind === "subject" && typeof properties.subject_key === "string" && typeof step.id === "string" ? properties.subject_key : null;
|
|
27575
|
+
}
|
|
27576
|
+
function retarget(relationships, renamed) {
|
|
27577
|
+
return relationships.map((relationship) => {
|
|
27578
|
+
const to = renamed.get(relationship.to);
|
|
27579
|
+
return to === undefined ? relationship : { ...relationship, to };
|
|
27580
|
+
});
|
|
27581
|
+
}
|
|
27582
|
+
function retargetStep(step, renamed) {
|
|
27583
|
+
if (!Array.isArray(step.relationships))
|
|
27584
|
+
return step;
|
|
27585
|
+
const relationships = step.relationships;
|
|
27586
|
+
return { ...step, relationships: retarget(relationships, renamed) };
|
|
27587
|
+
}
|
|
27588
|
+
function shareSubjectFacts(candidates) {
|
|
27589
|
+
const owners = new Map;
|
|
27590
|
+
const renamed = new Map;
|
|
27591
|
+
candidates.forEach((candidate, candidateIndex) => {
|
|
27592
|
+
for (const step of candidate.applyPlan) {
|
|
27593
|
+
const key = subjectStepKey(step);
|
|
27594
|
+
if (key === null)
|
|
27595
|
+
continue;
|
|
27596
|
+
const factId = String(step.id);
|
|
27597
|
+
const source = String(stepProperties2(step).text_ref ?? candidate.sourcePath);
|
|
27598
|
+
const owner = owners.get(key);
|
|
27599
|
+
if (owner === undefined) {
|
|
27600
|
+
owners.set(key, { factId, candidateIndex, sources: [source] });
|
|
27601
|
+
continue;
|
|
27602
|
+
}
|
|
27603
|
+
if (owner.factId === factId)
|
|
27604
|
+
continue;
|
|
27605
|
+
renamed.set(factId, owner.factId);
|
|
27606
|
+
if (!owner.sources.includes(source))
|
|
27607
|
+
owner.sources.push(source);
|
|
27608
|
+
}
|
|
27609
|
+
});
|
|
27610
|
+
if (renamed.size === 0)
|
|
27611
|
+
return { candidates: [...candidates], diagnostics: [] };
|
|
27612
|
+
const shared = [...owners.entries()].filter(([, owner]) => owner.sources.length > 1);
|
|
27613
|
+
const sharedFacts = new Map(shared.map(([key, owner]) => [owner.factId, { key, owner }]));
|
|
27614
|
+
const result = candidates.map((candidate) => ({
|
|
27615
|
+
...candidate,
|
|
27616
|
+
relationships: retarget(candidate.relationships, renamed),
|
|
27617
|
+
applyPlan: candidate.applyPlan.filter((step) => !renamed.has(String(step.id))).map((step) => {
|
|
27618
|
+
const sharing = sharedFacts.get(String(step.id));
|
|
27619
|
+
const retargeted = retargetStep(step, renamed);
|
|
27620
|
+
if (sharing === undefined || subjectStepKey(step) === null)
|
|
27621
|
+
return retargeted;
|
|
27622
|
+
const properties = stepProperties2(step);
|
|
27623
|
+
const tags = Array.isArray(properties.tags) ? properties.tags.map(String) : [];
|
|
27624
|
+
return {
|
|
27625
|
+
...retargeted,
|
|
27626
|
+
properties: {
|
|
27627
|
+
...properties,
|
|
27628
|
+
tags: [
|
|
27629
|
+
...new Set([
|
|
27630
|
+
...tags,
|
|
27631
|
+
...sharing.owner.sources.map((source) => `provenance:${normalizeSourceKey(source)}`)
|
|
27632
|
+
])
|
|
27633
|
+
]
|
|
27634
|
+
},
|
|
27635
|
+
document: {
|
|
27636
|
+
body: `Subject ${sharing.key}, shared by the requirements bootstrap planned from ${sharing.owner.sources.join(", ")}. Each of them links to this fact through constrains.
|
|
27637
|
+
`
|
|
27638
|
+
}
|
|
27639
|
+
};
|
|
27640
|
+
})
|
|
27641
|
+
}));
|
|
27642
|
+
return {
|
|
27643
|
+
candidates: result,
|
|
27644
|
+
diagnostics: shared.map(([key, owner]) => `subject-key-shared: claims at ${owner.sources.join(", ")} name the same subject ${key}, so the plan writes one subject fact ${owner.factId} and links every requirement to it through constrains.`)
|
|
27480
27645
|
};
|
|
27481
27646
|
}
|
|
27647
|
+
var MAX_ASPECT_WORDS = 4, MAX_ASPECT_CHARS = 40, ASPECT_BOUNDARY_WORDS, ASPECT_STOP_WORDS;
|
|
27482
27648
|
var init_requirement_claims = __esm(() => {
|
|
27483
27649
|
init_strict_modeling();
|
|
27650
|
+
ASPECT_BOUNDARY_WORDS = new Set([
|
|
27651
|
+
"when",
|
|
27652
|
+
"whenever",
|
|
27653
|
+
"while",
|
|
27654
|
+
"if",
|
|
27655
|
+
"unless",
|
|
27656
|
+
"without",
|
|
27657
|
+
"after",
|
|
27658
|
+
"before",
|
|
27659
|
+
"until",
|
|
27660
|
+
"because",
|
|
27661
|
+
"once",
|
|
27662
|
+
"as",
|
|
27663
|
+
"by",
|
|
27664
|
+
"via",
|
|
27665
|
+
"during",
|
|
27666
|
+
"except",
|
|
27667
|
+
"so",
|
|
27668
|
+
"that",
|
|
27669
|
+
"which",
|
|
27670
|
+
"who",
|
|
27671
|
+
"where",
|
|
27672
|
+
"since",
|
|
27673
|
+
"for",
|
|
27674
|
+
"and",
|
|
27675
|
+
"or"
|
|
27676
|
+
]);
|
|
27677
|
+
ASPECT_STOP_WORDS = new Set([
|
|
27678
|
+
"a",
|
|
27679
|
+
"an",
|
|
27680
|
+
"the",
|
|
27681
|
+
"be",
|
|
27682
|
+
"is",
|
|
27683
|
+
"are",
|
|
27684
|
+
"was",
|
|
27685
|
+
"were",
|
|
27686
|
+
"been",
|
|
27687
|
+
"being",
|
|
27688
|
+
"to",
|
|
27689
|
+
"of",
|
|
27690
|
+
"in",
|
|
27691
|
+
"on",
|
|
27692
|
+
"at",
|
|
27693
|
+
"with",
|
|
27694
|
+
"from",
|
|
27695
|
+
"into",
|
|
27696
|
+
"its",
|
|
27697
|
+
"it",
|
|
27698
|
+
"their",
|
|
27699
|
+
"they",
|
|
27700
|
+
"them",
|
|
27701
|
+
"this",
|
|
27702
|
+
"these",
|
|
27703
|
+
"those",
|
|
27704
|
+
"can",
|
|
27705
|
+
"could",
|
|
27706
|
+
"will",
|
|
27707
|
+
"would",
|
|
27708
|
+
"may",
|
|
27709
|
+
"might",
|
|
27710
|
+
"must",
|
|
27711
|
+
"shall",
|
|
27712
|
+
"should",
|
|
27713
|
+
"do",
|
|
27714
|
+
"does",
|
|
27715
|
+
"has",
|
|
27716
|
+
"have",
|
|
27717
|
+
"had",
|
|
27718
|
+
"any",
|
|
27719
|
+
"all",
|
|
27720
|
+
"each",
|
|
27721
|
+
"every",
|
|
27722
|
+
"some",
|
|
27723
|
+
"only",
|
|
27724
|
+
"also",
|
|
27725
|
+
"then",
|
|
27726
|
+
"than",
|
|
27727
|
+
"not",
|
|
27728
|
+
"no"
|
|
27729
|
+
]);
|
|
27484
27730
|
});
|
|
27485
27731
|
|
|
27486
27732
|
// ../cli/dist/operations/bootstrap/markdown-candidates.js
|
|
@@ -27550,7 +27796,7 @@ function markdownComponentHint(relativePath) {
|
|
|
27550
27796
|
}
|
|
27551
27797
|
return;
|
|
27552
27798
|
}
|
|
27553
|
-
function requirementCandidate(item, statement, line, heading, headingLine, existingIds, minConfidence) {
|
|
27799
|
+
function requirementCandidate(item, statement, line, heading, headingLine, existingIds, minConfidence, subjectKeys, diagnostics) {
|
|
27554
27800
|
const relativePath = item.relativePath ?? item.label;
|
|
27555
27801
|
const base = /\bshall\b/i.test(statement) ? 0.86 : /\bmust\b/i.test(statement) ? 0.84 : 0.78;
|
|
27556
27802
|
const confidence = Math.min(0.95, base + (heading && /requirements?|constraints?|polic(?:y|ies)|rules?/i.test(heading) ? 0.08 : 0));
|
|
@@ -27559,7 +27805,8 @@ function requirementCandidate(item, statement, line, heading, headingLine, exist
|
|
|
27559
27805
|
const claim = claimFor(statement, relativePath, confidence, `${relativePath}#L${line}`);
|
|
27560
27806
|
if (!claim)
|
|
27561
27807
|
return null;
|
|
27562
|
-
const
|
|
27808
|
+
const planned = planSubjectKey(claim.subjectKey, claim.propertyKey, markdownComponentHint(relativePath), subjectKeys, `${relativePath}#L${line}`);
|
|
27809
|
+
const subjectKey = planned.resolution;
|
|
27563
27810
|
if (!subjectKey.ok)
|
|
27564
27811
|
throw new Error(`${subjectKey.reason}; author it with kb_model and a component.aspect subjectKey`);
|
|
27565
27812
|
const writeSet = buildStrictWriteSet({
|
|
@@ -27568,6 +27815,7 @@ function requirementCandidate(item, statement, line, heading, headingLine, exist
|
|
|
27568
27815
|
});
|
|
27569
27816
|
if (!writeSet.isStrict)
|
|
27570
27817
|
return null;
|
|
27818
|
+
diagnostics.push(...planned.diagnostics);
|
|
27571
27819
|
return {
|
|
27572
27820
|
candidateId: `norm:${writeSet.req.id.toLowerCase()}`,
|
|
27573
27821
|
entityType: "req",
|
|
@@ -27588,7 +27836,7 @@ function requirementCandidate(item, statement, line, heading, headingLine, exist
|
|
|
27588
27836
|
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)
|
|
27589
27837
|
};
|
|
27590
27838
|
}
|
|
27591
|
-
function markdownCandidates(item, existingIds, minConfidence) {
|
|
27839
|
+
function markdownCandidates(item, existingIds, minConfidence, subjectKeys) {
|
|
27592
27840
|
const candidates = [];
|
|
27593
27841
|
const sourceOnlySignals = [];
|
|
27594
27842
|
const diagnostics = [];
|
|
@@ -27617,7 +27865,7 @@ function markdownCandidates(item, existingIds, minConfidence) {
|
|
|
27617
27865
|
if (!statement || !/\b(must|shall|should)\b/i.test(statement))
|
|
27618
27866
|
continue;
|
|
27619
27867
|
try {
|
|
27620
|
-
const candidate = requirementCandidate(item, statement, index + 1, heading, headingLine, existingIds, minConfidence);
|
|
27868
|
+
const candidate = requirementCandidate(item, statement, index + 1, heading, headingLine, existingIds, minConfidence, subjectKeys, diagnostics);
|
|
27621
27869
|
if (candidate) {
|
|
27622
27870
|
if (!candidate.applyPlan.some((payload) => payload.type === "req" && existingIds.has(String(payload.id))))
|
|
27623
27871
|
candidates.push(candidate);
|
|
@@ -27748,7 +27996,7 @@ function providerCandidate(item, existingIds, minConfidence) {
|
|
|
27748
27996
|
}
|
|
27749
27997
|
];
|
|
27750
27998
|
}
|
|
27751
|
-
function buildBootstrapCandidates(evidence, existingIds, minConfidence, includeGenericMarkdown) {
|
|
27999
|
+
function buildBootstrapCandidates(evidence, existingIds, minConfidence, includeGenericMarkdown, subjectKeys) {
|
|
27752
28000
|
const candidates = [];
|
|
27753
28001
|
const sourceOnlySignals = [];
|
|
27754
28002
|
const diagnostics = [];
|
|
@@ -27771,7 +28019,7 @@ function buildBootstrapCandidates(evidence, existingIds, minConfidence, includeG
|
|
|
27771
28019
|
}
|
|
27772
28020
|
}
|
|
27773
28021
|
if (item.kind === "generic_markdown" && includeGenericMarkdown) {
|
|
27774
|
-
const built = markdownCandidates(item, existingIds, minConfidence);
|
|
28022
|
+
const built = markdownCandidates(item, existingIds, minConfidence, subjectKeys);
|
|
27775
28023
|
candidates.push(...built.candidates);
|
|
27776
28024
|
sourceOnlySignals.push(...built.sourceOnlySignals);
|
|
27777
28025
|
diagnostics.push(...built.diagnostics);
|
|
@@ -28019,13 +28267,13 @@ var init_discovery_evidence = __esm(() => {
|
|
|
28019
28267
|
});
|
|
28020
28268
|
|
|
28021
28269
|
// ../cli/dist/operations/bootstrap/types.js
|
|
28022
|
-
import { createHash as
|
|
28270
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
28023
28271
|
function bootstrapPlanHash(plan) {
|
|
28024
28272
|
const { planHash: _ignored, ...body } = plan;
|
|
28025
|
-
return
|
|
28273
|
+
return createHash16("sha256").update(canonicalize(body)).digest("hex");
|
|
28026
28274
|
}
|
|
28027
28275
|
function bootstrapEmptyKbSnapshotId(input) {
|
|
28028
|
-
return `empty-source-state-${
|
|
28276
|
+
return `empty-source-state-${createHash16("sha256").update(canonicalize({
|
|
28029
28277
|
version: "kibi.empty-source-state.v1",
|
|
28030
28278
|
branch: input.branch,
|
|
28031
28279
|
workspaceSnapshot: input.workspaceSnapshot,
|
|
@@ -28162,7 +28410,7 @@ var init_discovery = __esm(() => {
|
|
|
28162
28410
|
});
|
|
28163
28411
|
|
|
28164
28412
|
// ../cli/dist/operations/bootstrap/intent-claims.js
|
|
28165
|
-
import { createHash as
|
|
28413
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
28166
28414
|
function citation(source, claim) {
|
|
28167
28415
|
return [
|
|
28168
28416
|
`intent_claim:${source.id}:${claim.reference}`,
|
|
@@ -28171,8 +28419,8 @@ function citation(source, claim) {
|
|
|
28171
28419
|
...source.connector ? [`connector:${source.connector}`] : []
|
|
28172
28420
|
];
|
|
28173
28421
|
}
|
|
28174
|
-
function
|
|
28175
|
-
return
|
|
28422
|
+
function digest2(...parts) {
|
|
28423
|
+
return createHash17("sha256").update(parts.join("\x00")).digest("hex").slice(0, 16).toUpperCase();
|
|
28176
28424
|
}
|
|
28177
28425
|
function claimBody(source, claim) {
|
|
28178
28426
|
return renderRequirementBody({
|
|
@@ -28195,7 +28443,7 @@ function withRationale(step, rationale) {
|
|
|
28195
28443
|
return { ...step, properties: { ...properties, rationale } };
|
|
28196
28444
|
}
|
|
28197
28445
|
function reviewClaimCandidate(source, claim, kind, confidence) {
|
|
28198
|
-
const id = `FACT-BOOTSTRAP-${kind === "open_question" ? "QUESTION" : "OBSERVATION"}-${
|
|
28446
|
+
const id = `FACT-BOOTSTRAP-${kind === "open_question" ? "QUESTION" : "OBSERVATION"}-${digest2(source.id, claim.reference, claim.statement)}`;
|
|
28199
28447
|
const entity = {
|
|
28200
28448
|
type: "fact",
|
|
28201
28449
|
id,
|
|
@@ -28240,7 +28488,7 @@ function conflictCandidates(declared, sources, existingIds, minConfidence) {
|
|
|
28240
28488
|
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.`);
|
|
28241
28489
|
continue;
|
|
28242
28490
|
}
|
|
28243
|
-
const id = `FACT-BOOTSTRAP-CONFLICT-${
|
|
28491
|
+
const id = `FACT-BOOTSTRAP-CONFLICT-${digest2(...[...refs].sort(), conflict.note)}`;
|
|
28244
28492
|
const candidateId = `conflict:${id.toLowerCase()}`;
|
|
28245
28493
|
if (confidence < minConfidence) {
|
|
28246
28494
|
suppressed.push({
|
|
@@ -28315,7 +28563,7 @@ ${evidenceLines.join(`
|
|
|
28315
28563
|
}
|
|
28316
28564
|
return { candidates, sourceOnlySignals: [], suppressed, diagnostics };
|
|
28317
28565
|
}
|
|
28318
|
-
function buildIntentClaimCandidates(declared, existingIds, minConfidence) {
|
|
28566
|
+
function buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys) {
|
|
28319
28567
|
const sources = new Map((declared.knowledgeSources ?? []).map((source) => [source.id, source]));
|
|
28320
28568
|
const candidates = [];
|
|
28321
28569
|
const sourceOnlySignals = [];
|
|
@@ -28371,7 +28619,9 @@ function buildIntentClaimCandidates(declared, existingIds, minConfidence) {
|
|
|
28371
28619
|
let writeSet = null;
|
|
28372
28620
|
try {
|
|
28373
28621
|
const modeled = claimFor(claim.statement, `knowledge-source:${source.id}`, confidence, provenance);
|
|
28374
|
-
const
|
|
28622
|
+
const planned = modeled ? planSubjectKey(modeled.subjectKey, modeled.propertyKey, claim.component ?? source.component, subjectKeys, `${source.id}:${claim.reference}`) : null;
|
|
28623
|
+
const subjectKey = planned?.resolution ?? null;
|
|
28624
|
+
diagnostics.push(...planned?.diagnostics ?? []);
|
|
28375
28625
|
writeSet = modeled && subjectKey?.ok ? buildStrictWriteSet({
|
|
28376
28626
|
claim: { ...modeled, subjectKey: subjectKey.subjectKey },
|
|
28377
28627
|
statement: claim.statement
|
|
@@ -30208,7 +30458,6 @@ var init_analysis_receipt = __esm(() => {
|
|
|
30208
30458
|
// ../cli/dist/operations/semantic-advisor/observation-plan.js
|
|
30209
30459
|
function observationPlan(payload, title, tags) {
|
|
30210
30460
|
const factId = `FACT-OBS-${shortHash(`${stringValue2(payload.id)}.${title}.${statementOf(payload)}`)}`;
|
|
30211
|
-
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;
|
|
30212
30461
|
return [
|
|
30213
30462
|
{
|
|
30214
30463
|
type: "fact",
|
|
@@ -30221,7 +30470,13 @@ function observationPlan(payload, title, tags) {
|
|
|
30221
30470
|
text_ref: statementOf(payload),
|
|
30222
30471
|
tags
|
|
30223
30472
|
},
|
|
30224
|
-
|
|
30473
|
+
document: {
|
|
30474
|
+
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.
|
|
30475
|
+
|
|
30476
|
+
> ${statementOf(payload).trim().replace(/\n/g, `
|
|
30477
|
+
> `)}`
|
|
30478
|
+
},
|
|
30479
|
+
relationships: []
|
|
30225
30480
|
}
|
|
30226
30481
|
];
|
|
30227
30482
|
}
|
|
@@ -31006,7 +31261,7 @@ var init_validation2 = __esm(() => {
|
|
|
31006
31261
|
});
|
|
31007
31262
|
|
|
31008
31263
|
// ../cli/dist/operations/bootstrap/generate.js
|
|
31009
|
-
import { createHash as
|
|
31264
|
+
import { createHash as createHash18 } from "node:crypto";
|
|
31010
31265
|
import path31 from "node:path";
|
|
31011
31266
|
function filterSourceOnlySignals(signals, entityTypes) {
|
|
31012
31267
|
return entityTypes && entityTypes.length > 0 ? signals.filter((signal) => entityTypes.includes(signal.kind)) : signals;
|
|
@@ -31025,7 +31280,7 @@ function firstUpsertId(candidate) {
|
|
|
31025
31280
|
return properties !== null && typeof properties === "object" && "id" in properties && typeof properties.id === "string" ? properties.id : "";
|
|
31026
31281
|
}
|
|
31027
31282
|
function sha2562(value) {
|
|
31028
|
-
return
|
|
31283
|
+
return createHash18("sha256").update(value).digest("hex");
|
|
31029
31284
|
}
|
|
31030
31285
|
function selectBootstrapCandidates(input, existingIds, entityTypes, maximum) {
|
|
31031
31286
|
const allowed = entityTypes?.length ? new Set(entityTypes) : null;
|
|
@@ -31240,13 +31495,14 @@ async function executePlanBootstrap(args, context) {
|
|
|
31240
31495
|
})
|
|
31241
31496
|
]);
|
|
31242
31497
|
const bound = await expectedSnapshots(context, discovery.evidence.map((evidence) => evidence.relativePath).filter((value) => Boolean(value)));
|
|
31243
|
-
const
|
|
31498
|
+
const subjectKeys = new SubjectKeyRegistry;
|
|
31499
|
+
const built = discovery.activation.allowCandidateGeneration ? buildBootstrapCandidates(discovery.evidence, new Set, minConfidence, includeGenericMarkdown, subjectKeys) : {
|
|
31244
31500
|
candidates: [],
|
|
31245
31501
|
sourceOnlySignals: [],
|
|
31246
31502
|
suppressed: [],
|
|
31247
31503
|
diagnostics: []
|
|
31248
31504
|
};
|
|
31249
|
-
const claimed = discovery.activation.allowCandidateGeneration ? buildIntentClaimCandidates(declared, existingIds, minConfidence) : {
|
|
31505
|
+
const claimed = discovery.activation.allowCandidateGeneration ? buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys) : {
|
|
31250
31506
|
candidates: [],
|
|
31251
31507
|
sourceOnlySignals: [],
|
|
31252
31508
|
suppressed: [],
|
|
@@ -31254,6 +31510,7 @@ async function executePlanBootstrap(args, context) {
|
|
|
31254
31510
|
};
|
|
31255
31511
|
const filteredSignals = filterSourceOnlySignals([...built.sourceOnlySignals, ...claimed.sourceOnlySignals], args.entityTypes);
|
|
31256
31512
|
const selected = selectBootstrapCandidates([...built.candidates, ...claimed.candidates].filter((candidate) => candidate.confidence >= minConfidence), existingIds, args.entityTypes, maxCandidates);
|
|
31513
|
+
const shared = shareSubjectFacts(selected.candidates);
|
|
31257
31514
|
const ignored = discovery.ignoredSources.map((sourcePath) => ({
|
|
31258
31515
|
candidateId: "",
|
|
31259
31516
|
reason: "ignored_source",
|
|
@@ -31267,7 +31524,7 @@ async function executePlanBootstrap(args, context) {
|
|
|
31267
31524
|
discoverySummary: discovery.summary,
|
|
31268
31525
|
migrationWarning: discovery.migrationWarning,
|
|
31269
31526
|
...args.bootstrapContext ? { bootstrapContext: args.bootstrapContext } : {},
|
|
31270
|
-
candidates:
|
|
31527
|
+
candidates: shared.candidates,
|
|
31271
31528
|
sourceOnlySignals: [
|
|
31272
31529
|
...filteredSignals,
|
|
31273
31530
|
...filterSourceOnlySignals(selected.sourceOnlySignals, args.entityTypes)
|
|
@@ -31286,7 +31543,8 @@ async function executePlanBootstrap(args, context) {
|
|
|
31286
31543
|
] : [],
|
|
31287
31544
|
...claimed.diagnostics,
|
|
31288
31545
|
...built.diagnostics,
|
|
31289
|
-
...selected.diagnostics
|
|
31546
|
+
...selected.diagnostics,
|
|
31547
|
+
...shared.diagnostics
|
|
31290
31548
|
]
|
|
31291
31549
|
});
|
|
31292
31550
|
}
|
|
@@ -31298,6 +31556,7 @@ var init_generate = __esm(() => {
|
|
|
31298
31556
|
init_discovery();
|
|
31299
31557
|
init_intent_claims();
|
|
31300
31558
|
init_presentation();
|
|
31559
|
+
init_requirement_claims();
|
|
31301
31560
|
init_validation2();
|
|
31302
31561
|
init_types();
|
|
31303
31562
|
});
|
|
@@ -31570,7 +31829,7 @@ var init_aggregated_checks = __esm(() => {
|
|
|
31570
31829
|
});
|
|
31571
31830
|
|
|
31572
31831
|
// ../cli/dist/traceability/impact-review.js
|
|
31573
|
-
import { createHash as
|
|
31832
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
31574
31833
|
function canonicalJson2(value) {
|
|
31575
31834
|
const active = new Set;
|
|
31576
31835
|
const encode = (item) => {
|
|
@@ -31604,10 +31863,10 @@ function canonicalJson2(value) {
|
|
|
31604
31863
|
return encode(value);
|
|
31605
31864
|
}
|
|
31606
31865
|
function fingerprint(value) {
|
|
31607
|
-
return `sha256:${
|
|
31866
|
+
return `sha256:${createHash19("sha256").update(canonicalJson2(value), "utf8").digest("hex")}`;
|
|
31608
31867
|
}
|
|
31609
31868
|
function fingerprintBytes(value) {
|
|
31610
|
-
return `sha256:${
|
|
31869
|
+
return `sha256:${createHash19("sha256").update(value).digest("hex")}`;
|
|
31611
31870
|
}
|
|
31612
31871
|
function isObject(value) {
|
|
31613
31872
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -32237,7 +32496,7 @@ var init_source_classification = __esm(() => {
|
|
|
32237
32496
|
});
|
|
32238
32497
|
|
|
32239
32498
|
// ../cli/dist/plugins/source-analysis-service.js
|
|
32240
|
-
import { createHash as
|
|
32499
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
32241
32500
|
import * as path33 from "node:path";
|
|
32242
32501
|
function detectSourceLanguage(filePath) {
|
|
32243
32502
|
return extensionLanguage(filePath);
|
|
@@ -32245,7 +32504,7 @@ function detectSourceLanguage(filePath) {
|
|
|
32245
32504
|
function createV2Request(filePath, content, explicitLanguageHint) {
|
|
32246
32505
|
const classification = classifySource(filePath, content, explicitLanguageHint);
|
|
32247
32506
|
const language = classification.language;
|
|
32248
|
-
const inputFingerprint =
|
|
32507
|
+
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");
|
|
32249
32508
|
return {
|
|
32250
32509
|
classification,
|
|
32251
32510
|
input: {
|
|
@@ -32407,7 +32666,7 @@ class SourceAnalysisService {
|
|
|
32407
32666
|
providerId: entry.capability.id,
|
|
32408
32667
|
stamp: entry.stamp,
|
|
32409
32668
|
inputFingerprint: request.inputFingerprint,
|
|
32410
|
-
providerFingerprint: this.options.providerFingerprints?.[entry.pluginId] ??
|
|
32669
|
+
providerFingerprint: this.options.providerFingerprints?.[entry.pluginId] ?? createHash20("sha256").update(`${entry.pluginId}\x00${entry.pluginVersion}\x00${entry.stamp.capability}`).digest("hex"),
|
|
32411
32670
|
shadowComparisons: []
|
|
32412
32671
|
};
|
|
32413
32672
|
} catch (error) {
|
|
@@ -32527,7 +32786,7 @@ var init_source_analysis_service = __esm(() => {
|
|
|
32527
32786
|
});
|
|
32528
32787
|
|
|
32529
32788
|
// ../cli/dist/plugins/maintenance-source-analysis.js
|
|
32530
|
-
import { createHash as
|
|
32789
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
32531
32790
|
import { readFileSync as readFileSync16, realpathSync as realpathSync5 } from "node:fs";
|
|
32532
32791
|
import { createRequire as createRequire4 } from "node:module";
|
|
32533
32792
|
import { dirname as dirname7, isAbsolute as isAbsolute6, join as join13, relative as relative5, resolve as resolve7 } from "node:path";
|
|
@@ -32540,7 +32799,7 @@ function digestFile(root, file) {
|
|
|
32540
32799
|
const actualRel = relative5(realpathSync5(root), actual);
|
|
32541
32800
|
if (actualRel.startsWith("..") || isAbsolute6(actualRel))
|
|
32542
32801
|
throw new Error(`Approved asset escapes its package: ${file}`);
|
|
32543
|
-
return
|
|
32802
|
+
return createHash21("sha256").update(readFileSync16(actual)).digest("hex");
|
|
32544
32803
|
}
|
|
32545
32804
|
function verifyFiles(root, files) {
|
|
32546
32805
|
if (Object.keys(files).length === 0)
|
|
@@ -32609,7 +32868,7 @@ function verifyApprovedSourceAnalyzer(root, approval) {
|
|
|
32609
32868
|
if (metadata.version !== dependency.version)
|
|
32610
32869
|
throw new Error(`Unapproved source runtime version: ${dependency.packageName}`);
|
|
32611
32870
|
}
|
|
32612
|
-
return
|
|
32871
|
+
return createHash21("sha256").update(JSON.stringify(approval)).digest("hex");
|
|
32613
32872
|
}
|
|
32614
32873
|
function createMaintenanceSourceAnalysisService(workspaceRoot, projectConfig) {
|
|
32615
32874
|
const config = projectConfig ?? readProjectKibiConfig(workspaceRoot);
|
|
@@ -40581,7 +40840,7 @@ async function enrichSymbolCoordinatesWithTsMorph(entries, workspaceRoot) {
|
|
|
40581
40840
|
var init_symbols_ts = () => {};
|
|
40582
40841
|
|
|
40583
40842
|
// ../cli/dist/traceability/symbol-extract.js
|
|
40584
|
-
import { createHash as
|
|
40843
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
40585
40844
|
function createManifestLookupSentinelKey(manifestPath) {
|
|
40586
40845
|
return `${MANIFEST_SENTINEL_PREFIX}${manifestPath}`;
|
|
40587
40846
|
}
|
|
@@ -40593,7 +40852,7 @@ function getCandidateManifestPaths(filePath) {
|
|
|
40593
40852
|
return LOCAL_MANIFEST_NAMES.map((manifestName) => `${dir}/${manifestName}`);
|
|
40594
40853
|
}
|
|
40595
40854
|
function createHashFallbackId(filePath, name) {
|
|
40596
|
-
const h =
|
|
40855
|
+
const h = createHash23("sha256");
|
|
40597
40856
|
h.update(`${filePath}:${name}`);
|
|
40598
40857
|
return h.digest("hex").slice(0, 16);
|
|
40599
40858
|
}
|
|
@@ -40681,7 +40940,7 @@ function buildSymbolResult(stagedFile, name, kind, span, inlineReqLinks, manifes
|
|
|
40681
40940
|
};
|
|
40682
40941
|
}
|
|
40683
40942
|
function computeContentSha(content) {
|
|
40684
|
-
const h =
|
|
40943
|
+
const h = createHash23("sha256");
|
|
40685
40944
|
h.update(content);
|
|
40686
40945
|
return h.digest("hex");
|
|
40687
40946
|
}
|
|
@@ -44180,9 +44439,88 @@ var init_origin_review = __esm(() => {
|
|
|
44180
44439
|
RATIONALE_HEADING = /^#{1,6}[ \t]+(?:rationale|why|context)\b/im;
|
|
44181
44440
|
});
|
|
44182
44441
|
|
|
44442
|
+
// ../cli/dist/operations/modeling/predicate-closed-vocabularies.js
|
|
44443
|
+
function closedArguments(byArgument) {
|
|
44444
|
+
const constants = {};
|
|
44445
|
+
const aliases = {};
|
|
44446
|
+
for (const [name, vocabulary] of Object.entries(byArgument)) {
|
|
44447
|
+
constants[name] = [...vocabulary.constants];
|
|
44448
|
+
if (Object.keys(vocabulary.aliases).length > 0)
|
|
44449
|
+
aliases[name] = { ...vocabulary.aliases };
|
|
44450
|
+
}
|
|
44451
|
+
return Object.keys(aliases).length > 0 ? { argument_constants: constants, argument_aliases: aliases } : { argument_constants: constants };
|
|
44452
|
+
}
|
|
44453
|
+
var TRIGGER_VOCABULARY, DECISION_VOCABULARY, REFRESH_POLICY_VOCABULARY, ENVIRONMENT_DECISION_VOCABULARY, OPERATOR_VOCABULARY, RETENTION_UNIT_VOCABULARY, CODING_STANDARD_ACTION_VOCABULARY, LIFECYCLE_ACTION_VOCABULARY;
|
|
44454
|
+
var init_predicate_closed_vocabularies = __esm(() => {
|
|
44455
|
+
TRIGGER_VOCABULARY = {
|
|
44456
|
+
constants: ["escape", "cancel", "submit", "navigation", "click", "timeout"],
|
|
44457
|
+
aliases: {
|
|
44458
|
+
esc: "escape",
|
|
44459
|
+
escape_key: "escape",
|
|
44460
|
+
cancellation: "cancel",
|
|
44461
|
+
submission: "submit",
|
|
44462
|
+
navigate: "navigation",
|
|
44463
|
+
navigates: "navigation",
|
|
44464
|
+
navigating: "navigation",
|
|
44465
|
+
navigation_away: "navigation",
|
|
44466
|
+
clicks: "click",
|
|
44467
|
+
time_out: "timeout",
|
|
44468
|
+
timed_out: "timeout"
|
|
44469
|
+
}
|
|
44470
|
+
};
|
|
44471
|
+
DECISION_VOCABULARY = {
|
|
44472
|
+
constants: ["allow", "deny"],
|
|
44473
|
+
aliases: {
|
|
44474
|
+
assert: "allow",
|
|
44475
|
+
allowed: "allow",
|
|
44476
|
+
permit: "allow",
|
|
44477
|
+
permitted: "allow",
|
|
44478
|
+
denied: "deny",
|
|
44479
|
+
forbid: "deny",
|
|
44480
|
+
forbidden: "deny"
|
|
44481
|
+
}
|
|
44482
|
+
};
|
|
44483
|
+
REFRESH_POLICY_VOCABULARY = {
|
|
44484
|
+
constants: ["automatic", "manual", "on_demand"],
|
|
44485
|
+
aliases: {
|
|
44486
|
+
auto: "automatic",
|
|
44487
|
+
automatically: "automatic",
|
|
44488
|
+
manually: "manual",
|
|
44489
|
+
"on-demand": "on_demand"
|
|
44490
|
+
}
|
|
44491
|
+
};
|
|
44492
|
+
ENVIRONMENT_DECISION_VOCABULARY = {
|
|
44493
|
+
constants: ["allowed", "forbidden", "read-only"],
|
|
44494
|
+
aliases: {
|
|
44495
|
+
allow: "allowed",
|
|
44496
|
+
deny: "forbidden",
|
|
44497
|
+
denied: "forbidden",
|
|
44498
|
+
read_only: "read-only",
|
|
44499
|
+
readonly: "read-only"
|
|
44500
|
+
}
|
|
44501
|
+
};
|
|
44502
|
+
OPERATOR_VOCABULARY = {
|
|
44503
|
+
constants: ["lt", "lte", "eq", "neq", "gte", "gt"],
|
|
44504
|
+
aliases: { le: "lte", ge: "gte", ne: "neq" }
|
|
44505
|
+
};
|
|
44506
|
+
RETENTION_UNIT_VOCABULARY = {
|
|
44507
|
+
constants: ["days", "months", "years"],
|
|
44508
|
+
aliases: { day: "days", month: "months", year: "years" }
|
|
44509
|
+
};
|
|
44510
|
+
CODING_STANDARD_ACTION_VOCABULARY = {
|
|
44511
|
+
constants: ["use", "avoid"],
|
|
44512
|
+
aliases: {}
|
|
44513
|
+
};
|
|
44514
|
+
LIFECYCLE_ACTION_VOCABULARY = {
|
|
44515
|
+
constants: ["archived", "deleted", "expired"],
|
|
44516
|
+
aliases: { archive: "archived", delete: "deleted", expire: "expired" }
|
|
44517
|
+
};
|
|
44518
|
+
});
|
|
44519
|
+
|
|
44183
44520
|
// ../cli/dist/operations/modeling/predicate-catalog-1.js
|
|
44184
44521
|
var PREDICATE_CATALOG_1;
|
|
44185
44522
|
var init_predicate_catalog_1 = __esm(() => {
|
|
44523
|
+
init_predicate_closed_vocabularies();
|
|
44186
44524
|
PREDICATE_CATALOG_1 = [
|
|
44187
44525
|
{
|
|
44188
44526
|
id: "FACT-SCHEMA-STATE",
|
|
@@ -44202,6 +44540,7 @@ var init_predicate_catalog_1 = __esm(() => {
|
|
|
44202
44540
|
description: "A subject transitions between states because of a trigger.",
|
|
44203
44541
|
argument_names: ["subject", "from_state", "to_state", "trigger"],
|
|
44204
44542
|
argument_types: ["entity", "state", "state", "trigger"],
|
|
44543
|
+
...closedArguments({ trigger: TRIGGER_VOCABULARY }),
|
|
44205
44544
|
keywords: [
|
|
44206
44545
|
"transition",
|
|
44207
44546
|
"enter",
|
|
@@ -44377,6 +44716,7 @@ var init_predicate_catalog_1 = __esm(() => {
|
|
|
44377
44716
|
description: "An entity must be archived, deleted, expired, or lifecycle-transitioned after a duration.",
|
|
44378
44717
|
argument_names: ["subject", "action", "duration", "unit"],
|
|
44379
44718
|
argument_types: ["entity", "action", "number", "unit"],
|
|
44719
|
+
...closedArguments({ action: LIFECYCLE_ACTION_VOCABULARY }),
|
|
44380
44720
|
keywords: ["archive", "archived", "delete", "deleted", "expire", "after"],
|
|
44381
44721
|
examples: ["lifecycle_rule(expired_sessions, archived, 30, days)"],
|
|
44382
44722
|
tags: ["lifecycle", "retention"]
|
|
@@ -44387,6 +44727,7 @@ var init_predicate_catalog_1 = __esm(() => {
|
|
|
44387
44727
|
// ../cli/dist/operations/modeling/predicate-catalog-2.js
|
|
44388
44728
|
var PREDICATE_CATALOG_2;
|
|
44389
44729
|
var init_predicate_catalog_2 = __esm(() => {
|
|
44730
|
+
init_predicate_closed_vocabularies();
|
|
44390
44731
|
PREDICATE_CATALOG_2 = [
|
|
44391
44732
|
{
|
|
44392
44733
|
id: "FACT-SCHEMA-CONFLICT-RESOLUTION-RULE",
|
|
@@ -44454,6 +44795,7 @@ var init_predicate_catalog_2 = __esm(() => {
|
|
|
44454
44795
|
description: "A named action is allowed or forbidden in a deployment environment.",
|
|
44455
44796
|
argument_names: ["action", "decision", "environment"],
|
|
44456
44797
|
argument_types: ["action", "decision", "environment"],
|
|
44798
|
+
...closedArguments({ decision: ENVIRONMENT_DECISION_VOCABULARY }),
|
|
44457
44799
|
keywords: ["production", "staging", "forbidden", "destructive"],
|
|
44458
44800
|
examples: [
|
|
44459
44801
|
"environment_safety_rule(destructive_operations, forbidden, production)"
|
|
@@ -44478,6 +44820,7 @@ var init_predicate_catalog_2 = __esm(() => {
|
|
|
44478
44820
|
description: "Developer-facing code must use or avoid a framework API, pattern, or documentation practice.",
|
|
44479
44821
|
argument_names: ["subject", "action", "target"],
|
|
44480
44822
|
argument_types: ["entity", "action", "api"],
|
|
44823
|
+
...closedArguments({ action: CODING_STANDARD_ACTION_VOCABULARY }),
|
|
44481
44824
|
keywords: ["computed", "signals", "must use", "must not use"],
|
|
44482
44825
|
examples: ["coding_standard_rule(derived_state, use, computed_signals)"],
|
|
44483
44826
|
tags: ["coding-standard", "agent-guidance"]
|
|
@@ -44604,6 +44947,7 @@ var init_predicate_catalog_2 = __esm(() => {
|
|
|
44604
44947
|
// ../cli/dist/operations/modeling/predicate-catalog-3.js
|
|
44605
44948
|
var PREDICATE_CATALOG_3;
|
|
44606
44949
|
var init_predicate_catalog_3 = __esm(() => {
|
|
44950
|
+
init_predicate_closed_vocabularies();
|
|
44607
44951
|
PREDICATE_CATALOG_3 = [
|
|
44608
44952
|
{
|
|
44609
44953
|
id: "FACT-SCHEMA-ORDERED-STRATEGY-RULE",
|
|
@@ -44625,6 +44969,7 @@ var init_predicate_catalog_3 = __esm(() => {
|
|
|
44625
44969
|
description: "A subject refreshes a target automatically or by a named policy.",
|
|
44626
44970
|
argument_names: ["subject", "target", "policy"],
|
|
44627
44971
|
argument_types: ["entity", "target", "policy"],
|
|
44972
|
+
...closedArguments({ policy: REFRESH_POLICY_VOCABULARY }),
|
|
44628
44973
|
keywords: ["automatically refresh", "manual page reload", "refresh"],
|
|
44629
44974
|
examples: ["refresh_policy_rule(dashboard, processing_videos, automatic)"],
|
|
44630
44975
|
tags: ["refresh", "ui"]
|
|
@@ -44636,6 +44981,7 @@ var init_predicate_catalog_3 = __esm(() => {
|
|
|
44636
44981
|
description: "A scoped actor is allowed or denied an action because of assignment, ownership, or membership.",
|
|
44637
44982
|
argument_names: ["actor_scope", "action", "decision"],
|
|
44638
44983
|
argument_types: ["actor_scope", "action", "decision"],
|
|
44984
|
+
...closedArguments({ decision: DECISION_VOCABULARY }),
|
|
44639
44985
|
keywords: ["unassigned", "assigned", "denied", "scoped"],
|
|
44640
44986
|
examples: [
|
|
44641
44987
|
"scoped_authorization_rule(unassigned_instructors, signed_url_generation, deny)"
|
|
@@ -44736,6 +45082,7 @@ var init_predicate_catalog_3 = __esm(() => {
|
|
|
44736
45082
|
description: "A trigger commits, saves, or persists a subject within a scope.",
|
|
44737
45083
|
argument_names: ["subject", "trigger", "scope"],
|
|
44738
45084
|
argument_types: ["entity", "trigger", "scope"],
|
|
45085
|
+
...closedArguments({ trigger: TRIGGER_VOCABULARY }),
|
|
44739
45086
|
keywords: [
|
|
44740
45087
|
"save",
|
|
44741
45088
|
"saves",
|
|
@@ -44758,6 +45105,7 @@ var init_predicate_catalog_3 = __esm(() => {
|
|
|
44758
45105
|
description: "A trigger discards or cancels changes for a subject within a scope.",
|
|
44759
45106
|
argument_names: ["subject", "trigger", "scope"],
|
|
44760
45107
|
argument_types: ["entity", "trigger", "scope"],
|
|
45108
|
+
...closedArguments({ trigger: TRIGGER_VOCABULARY }),
|
|
44761
45109
|
keywords: ["discard", "cancel", "escape", "revert", "without save"],
|
|
44762
45110
|
examples: ["discard_action(editor.annotation, escape, active_annotation)"],
|
|
44763
45111
|
tags: ["persistence", "workflow"]
|
|
@@ -44780,6 +45128,7 @@ var init_predicate_catalog_3 = __esm(() => {
|
|
|
44780
45128
|
description: "A subject is retained for a bounded duration.",
|
|
44781
45129
|
argument_names: ["subject", "duration", "unit"],
|
|
44782
45130
|
argument_types: ["entity", "number", "unit"],
|
|
45131
|
+
...closedArguments({ unit: RETENTION_UNIT_VOCABULARY }),
|
|
44783
45132
|
keywords: ["retain", "retained", "retention", "days", "months", "years"],
|
|
44784
45133
|
examples: ["retention_policy(customer.data, 7, years)"],
|
|
44785
45134
|
tags: ["data", "policy"]
|
|
@@ -44791,6 +45140,7 @@ var init_predicate_catalog_3 = __esm(() => {
|
|
|
44791
45140
|
description: "A subject constrains a resource by operator, threshold, and unit.",
|
|
44792
45141
|
argument_names: ["subject", "resource", "operator", "threshold", "unit"],
|
|
44793
45142
|
argument_types: ["entity", "resource", "operator", "number", "unit"],
|
|
45143
|
+
...closedArguments({ operator: OPERATOR_VOCABULARY }),
|
|
44794
45144
|
keywords: [
|
|
44795
45145
|
"limit",
|
|
44796
45146
|
"maximum",
|
|
@@ -44817,6 +45167,7 @@ var init_predicate_catalog_3 = __esm(() => {
|
|
|
44817
45167
|
// ../cli/dist/operations/modeling/predicate-catalog-4.js
|
|
44818
45168
|
var PREDICATE_CATALOG_4;
|
|
44819
45169
|
var init_predicate_catalog_4 = __esm(() => {
|
|
45170
|
+
init_predicate_closed_vocabularies();
|
|
44820
45171
|
PREDICATE_CATALOG_4 = [
|
|
44821
45172
|
{
|
|
44822
45173
|
id: "FACT-SCHEMA-DEPENDENCY-RESOLUTION-POLICY",
|
|
@@ -45019,6 +45370,7 @@ var init_predicate_catalog_4 = __esm(() => {
|
|
|
45019
45370
|
description: "An actor is allowed or denied an action against a resource.",
|
|
45020
45371
|
argument_names: ["actor", "action", "resource", "decision"],
|
|
45021
45372
|
argument_types: ["actor", "action", "resource", "decision"],
|
|
45373
|
+
...closedArguments({ decision: DECISION_VOCABULARY }),
|
|
45022
45374
|
keywords: [
|
|
45023
45375
|
"may",
|
|
45024
45376
|
"can",
|
|
@@ -51991,7 +52343,7 @@ var require_out4 = __commonJS(function(exports2, module2) {
|
|
|
51991
52343
|
|
|
51992
52344
|
// ../cli/dist/commands/sync/discovery.js
|
|
51993
52345
|
import { execFile } from "node:child_process";
|
|
51994
|
-
import { createHash as
|
|
52346
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
51995
52347
|
import * as fs5 from "node:fs";
|
|
51996
52348
|
import { existsSync as existsSync23, readFileSync as readFileSync24, readdirSync as readdirSync6, unlinkSync as unlinkSync4 } from "node:fs";
|
|
51997
52349
|
import * as path47 from "node:path";
|
|
@@ -52026,13 +52378,13 @@ function pendingSourcePaths(cwd, recoverMissing) {
|
|
|
52026
52378
|
receiptPath,
|
|
52027
52379
|
path: relative,
|
|
52028
52380
|
afterHash: receipt.afterHash,
|
|
52029
|
-
rawHash:
|
|
52381
|
+
rawHash: createHash24("sha256").update(raw).digest("hex")
|
|
52030
52382
|
});
|
|
52031
52383
|
continue;
|
|
52032
52384
|
}
|
|
52033
52385
|
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.`);
|
|
52034
52386
|
}
|
|
52035
|
-
const actual =
|
|
52387
|
+
const actual = createHash24("sha256").update(readFileSync24(absolute)).digest("hex");
|
|
52036
52388
|
if (actual !== receipt.afterHash) {
|
|
52037
52389
|
throw new Error(`Pending source hash drift blocks sync for ${relative}; expected ${receipt.afterHash}, found ${actual}`);
|
|
52038
52390
|
}
|
|
@@ -52080,7 +52432,7 @@ function clearRecoveredPendingSourceReceipts(cwd, receipts) {
|
|
|
52080
52432
|
const raw = readTextOrEnoent(absolute);
|
|
52081
52433
|
if (raw === null)
|
|
52082
52434
|
continue;
|
|
52083
|
-
const rawHash =
|
|
52435
|
+
const rawHash = createHash24("sha256").update(raw).digest("hex");
|
|
52084
52436
|
if (rawHash !== receipt.rawHash) {
|
|
52085
52437
|
throw new Error(`Pending source receipt changed during recovery for ${receipt.path}; refusing to retire newer receipt`);
|
|
52086
52438
|
}
|
|
@@ -53868,7 +54220,7 @@ function scoreExactPredicates3(schema, text) {
|
|
|
53868
54220
|
}
|
|
53869
54221
|
|
|
53870
54222
|
// ../cli/dist/operations/modeling/predicate-utils.js
|
|
53871
|
-
import { createHash as
|
|
54223
|
+
import { createHash as createHash25 } from "node:crypto";
|
|
53872
54224
|
function normalizeText2(text) {
|
|
53873
54225
|
const normalized = String(text ?? "").trim();
|
|
53874
54226
|
if (!normalized) {
|
|
@@ -53892,13 +54244,18 @@ function slug2(value) {
|
|
|
53892
54244
|
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
53893
54245
|
}
|
|
53894
54246
|
function hashId(prefix, parts) {
|
|
53895
|
-
const digest =
|
|
54247
|
+
const digest = createHash25("sha256").update(parts.join("\x00")).digest("hex").slice(0, 12).toUpperCase();
|
|
53896
54248
|
return `${prefix}-${digest}`;
|
|
53897
54249
|
}
|
|
53898
|
-
function inferSubject(text, subjectHint) {
|
|
54250
|
+
function inferSubject(text, subjectHint, requirement) {
|
|
53899
54251
|
const explicit = normalizeOptionalString2(subjectHint);
|
|
53900
54252
|
if (explicit)
|
|
53901
54253
|
return explicit;
|
|
54254
|
+
const grounded = normalizeOptionalString2(requirement?.subjectKey);
|
|
54255
|
+
if (grounded)
|
|
54256
|
+
return grounded;
|
|
54257
|
+
if (normalizeOptionalString2(requirement?.requirementId))
|
|
54258
|
+
return "requirement.subject";
|
|
53902
54259
|
const lower = text.toLowerCase();
|
|
53903
54260
|
if (lower.includes("annotation"))
|
|
53904
54261
|
return "editor.annotation";
|
|
@@ -53922,6 +54279,10 @@ function inferTrigger(text) {
|
|
|
53922
54279
|
return "cancel";
|
|
53923
54280
|
if (lower.includes("submit"))
|
|
53924
54281
|
return "submit";
|
|
54282
|
+
if (/\bclick/.test(lower))
|
|
54283
|
+
return "click";
|
|
54284
|
+
if (/\b(?:times?|timed)[\s-]?out\b/.test(lower))
|
|
54285
|
+
return "timeout";
|
|
53925
54286
|
return "unspecified_trigger";
|
|
53926
54287
|
}
|
|
53927
54288
|
function inferScope(text) {
|
|
@@ -54556,11 +54917,43 @@ function isGenericPlaceholder(value) {
|
|
|
54556
54917
|
const normalized = value.trim().toLowerCase();
|
|
54557
54918
|
return PLACEHOLDER_VALUES.has(normalized) || normalized === "unknown" || normalized.startsWith("requirement.") || normalized.endsWith("_policy") && ["executable", "cwd", "environment", "stdio", "termination"].some((kind) => normalized.startsWith(kind));
|
|
54558
54919
|
}
|
|
54559
|
-
function
|
|
54920
|
+
function bindingToken(value) {
|
|
54921
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
54922
|
+
}
|
|
54923
|
+
function claimNames(text, token) {
|
|
54924
|
+
if (!text || !token)
|
|
54925
|
+
return false;
|
|
54926
|
+
const words = token.split("_").filter(Boolean);
|
|
54927
|
+
if (words.length === 0)
|
|
54928
|
+
return false;
|
|
54929
|
+
return new RegExp(`\\b${words.join("[\\s_-]+")}\\b`, "i").test(text);
|
|
54930
|
+
}
|
|
54931
|
+
function matchesConstant(value, context) {
|
|
54932
|
+
const token = bindingToken(value);
|
|
54933
|
+
return context.constants?.some((constant) => bindingToken(constant) === token) ?? false;
|
|
54934
|
+
}
|
|
54935
|
+
function nameOrStopWordReason(value, context = {}) {
|
|
54936
|
+
const token = bindingToken(value);
|
|
54937
|
+
if (token === "true" || token === "false")
|
|
54938
|
+
return null;
|
|
54939
|
+
if (matchesConstant(value, context))
|
|
54940
|
+
return null;
|
|
54941
|
+
if (STOP_WORD_BINDINGS.has(token))
|
|
54942
|
+
return `"${token}" is a stop word`;
|
|
54943
|
+
const own = context.argumentName ? bindingToken(context.argumentName) : "";
|
|
54944
|
+
const repeatsName = own !== "" && token === own || (context.argumentNames ?? []).some((name) => bindingToken(name) === token);
|
|
54945
|
+
if (repeatsName && !claimNames(context.text, token))
|
|
54946
|
+
return `it repeats the argument name ${token} and the claim does not name it`;
|
|
54947
|
+
return null;
|
|
54948
|
+
}
|
|
54949
|
+
function classifyBinding(value, text, explicit, canonical = false, context = {}) {
|
|
54560
54950
|
const normalized = value.trim();
|
|
54561
|
-
if (
|
|
54951
|
+
if (nameOrStopWordReason(normalized, { ...context, text }) !== null)
|
|
54952
|
+
return "placeholder";
|
|
54953
|
+
const constant = matchesConstant(normalized, context);
|
|
54954
|
+
if (canonical && (constant || !isGenericPlaceholder(normalized)))
|
|
54562
54955
|
return "extracted";
|
|
54563
|
-
if (explicit && (!isGenericPlaceholder(normalized) || ["true", "false"].includes(normalized.toLowerCase())))
|
|
54956
|
+
if (explicit && (constant || !isGenericPlaceholder(normalized) || ["true", "false"].includes(normalized.toLowerCase())))
|
|
54564
54957
|
return "explicit";
|
|
54565
54958
|
if (!normalized || isGenericPlaceholder(normalized))
|
|
54566
54959
|
return "placeholder";
|
|
@@ -54572,9 +54965,9 @@ function aggregateBindingProvenance(values) {
|
|
|
54572
54965
|
return values.reduce((worst, value) => PROVENANCE_ORDER.indexOf(value) > PROVENANCE_ORDER.indexOf(worst) ? value : worst, "explicit");
|
|
54573
54966
|
}
|
|
54574
54967
|
function bindingCanBeApplied(value) {
|
|
54575
|
-
return value === "explicit" || value === "extracted";
|
|
54968
|
+
return value === "explicit" || value === "requirement" || value === "extracted";
|
|
54576
54969
|
}
|
|
54577
|
-
var PLACEHOLDER_VALUES, DERIVED_CUE_ALIASES, PROVENANCE_ORDER;
|
|
54970
|
+
var PLACEHOLDER_VALUES, DERIVED_CUE_ALIASES, STOP_WORD_BINDINGS, PROVENANCE_ORDER;
|
|
54578
54971
|
var init_predicate_bindings = __esm(() => {
|
|
54579
54972
|
PLACEHOLDER_VALUES = new Set([
|
|
54580
54973
|
"unknown",
|
|
@@ -54644,10 +55037,80 @@ var init_predicate_bindings = __esm(() => {
|
|
|
54644
55037
|
"missing module"
|
|
54645
55038
|
],
|
|
54646
55039
|
actionable_error: ["actionable", "clear error", "report", "error"],
|
|
54647
|
-
exception: ["exception", "except", "package-manager", "package manager"]
|
|
55040
|
+
exception: ["exception", "except", "package-manager", "package manager"],
|
|
55041
|
+
deny: [
|
|
55042
|
+
"denied",
|
|
55043
|
+
"must not",
|
|
55044
|
+
"must never",
|
|
55045
|
+
"forbidden",
|
|
55046
|
+
"prohibited",
|
|
55047
|
+
"not allowed",
|
|
55048
|
+
"not be allowed"
|
|
55049
|
+
],
|
|
55050
|
+
allow: ["is allowed", "are allowed", "permitted"],
|
|
55051
|
+
on_demand: ["on demand", "on request"],
|
|
55052
|
+
timeout: ["times out", "timed out", "time out"],
|
|
55053
|
+
submit: ["submission", "submits", "submitted"]
|
|
54648
55054
|
};
|
|
55055
|
+
STOP_WORD_BINDINGS = new Set([
|
|
55056
|
+
"a",
|
|
55057
|
+
"an",
|
|
55058
|
+
"the",
|
|
55059
|
+
"be",
|
|
55060
|
+
"is",
|
|
55061
|
+
"are",
|
|
55062
|
+
"was",
|
|
55063
|
+
"were",
|
|
55064
|
+
"been",
|
|
55065
|
+
"being",
|
|
55066
|
+
"am",
|
|
55067
|
+
"do",
|
|
55068
|
+
"does",
|
|
55069
|
+
"did",
|
|
55070
|
+
"done",
|
|
55071
|
+
"have",
|
|
55072
|
+
"has",
|
|
55073
|
+
"had",
|
|
55074
|
+
"it",
|
|
55075
|
+
"its",
|
|
55076
|
+
"this",
|
|
55077
|
+
"that",
|
|
55078
|
+
"these",
|
|
55079
|
+
"those",
|
|
55080
|
+
"they",
|
|
55081
|
+
"them",
|
|
55082
|
+
"there",
|
|
55083
|
+
"thing",
|
|
55084
|
+
"something",
|
|
55085
|
+
"anything",
|
|
55086
|
+
"some",
|
|
55087
|
+
"any",
|
|
55088
|
+
"of",
|
|
55089
|
+
"to",
|
|
55090
|
+
"in",
|
|
55091
|
+
"at",
|
|
55092
|
+
"by",
|
|
55093
|
+
"for",
|
|
55094
|
+
"with",
|
|
55095
|
+
"and",
|
|
55096
|
+
"or",
|
|
55097
|
+
"not",
|
|
55098
|
+
"null",
|
|
55099
|
+
"nil",
|
|
55100
|
+
"n_a",
|
|
55101
|
+
"na",
|
|
55102
|
+
"tbd",
|
|
55103
|
+
"todo",
|
|
55104
|
+
"x",
|
|
55105
|
+
"xxx",
|
|
55106
|
+
"foo",
|
|
55107
|
+
"bar",
|
|
55108
|
+
"example",
|
|
55109
|
+
"placeholder"
|
|
55110
|
+
]);
|
|
54649
55111
|
PROVENANCE_ORDER = [
|
|
54650
55112
|
"explicit",
|
|
55113
|
+
"requirement",
|
|
54651
55114
|
"extracted",
|
|
54652
55115
|
"inferred",
|
|
54653
55116
|
"placeholder"
|
|
@@ -55349,8 +55812,12 @@ var init_predicate_loader = __esm(() => {
|
|
|
55349
55812
|
function buildSuggestion(schema, text, subject, score, argumentBindings = {}, polarityHint, diagnostics) {
|
|
55350
55813
|
const inferredArgs = inferArgs(schema, text, subject);
|
|
55351
55814
|
const canonicalLauncherArgs = exactLauncherPredicateArgs(schema.predicate_name, text);
|
|
55815
|
+
const hasExactBinding = (name) => typeof argumentBindings[name] === "string" && argumentBindings[name].trim().length > 0;
|
|
55816
|
+
const requirementSubjectArgument = diagnostics?.requirementSubject && diagnostics.explicitSubject !== true && !hasExactBinding("subject") ? schema.argument_names.indexOf("subject") : -1;
|
|
55352
55817
|
const boundArgs = schema.argument_names.map((name, index) => {
|
|
55353
55818
|
const exactBinding = argumentBindings[name];
|
|
55819
|
+
if (index === requirementSubjectArgument)
|
|
55820
|
+
return diagnostics?.requirementSubject ?? "unknown";
|
|
55354
55821
|
return typeof exactBinding === "string" && exactBinding.trim().length > 0 ? exactBinding.trim() : inferredArgs[index] ?? "unknown";
|
|
55355
55822
|
});
|
|
55356
55823
|
const vocabulary = {
|
|
@@ -55362,7 +55829,11 @@ function buildSuggestion(schema, text, subject, score, argumentBindings = {}, po
|
|
|
55362
55829
|
const undeclaredArguments = new Set(conformance.undeclared.map((value) => value.argumentName));
|
|
55363
55830
|
const bindingProvenanceByArgument = Object.fromEntries(schema.argument_names.map((name, index) => [
|
|
55364
55831
|
name,
|
|
55365
|
-
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")
|
|
55832
|
+
index === requirementSubjectArgument && !undeclaredArguments.has(name) ? "requirement" : 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] } : {
|
|
55833
|
+
argumentName: name,
|
|
55834
|
+
argumentNames: schema.argument_names,
|
|
55835
|
+
constants: schema.argument_constants?.[name]
|
|
55836
|
+
})
|
|
55366
55837
|
]));
|
|
55367
55838
|
const bindingProvenance = aggregateBindingProvenance(Object.values(bindingProvenanceByArgument));
|
|
55368
55839
|
const unboundArguments = schema.argument_names.filter((name) => undeclaredArguments.has(name) || !bindingCanBeApplied(bindingProvenanceByArgument[name] ?? "placeholder"));
|
|
@@ -55452,8 +55923,21 @@ function buildRelationshipPlan(factId, requirementId, claimText, existingLogicCl
|
|
|
55452
55923
|
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-...).`
|
|
55453
55924
|
};
|
|
55454
55925
|
}
|
|
55926
|
+
function gapObservationBody(text, args) {
|
|
55927
|
+
const origin = [
|
|
55928
|
+
args.requirementId ? `requirement ${args.requirementId}` : null,
|
|
55929
|
+
args.source ? `source ${args.source}` : null
|
|
55930
|
+
].filter((value) => value !== null);
|
|
55931
|
+
return [
|
|
55932
|
+
"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.",
|
|
55933
|
+
...origin.length > 0 ? [`Claim from ${origin.join(", ")}:`] : ["Claim:"],
|
|
55934
|
+
`> ${text.trim().replace(/\n/g, `
|
|
55935
|
+
> `)}`
|
|
55936
|
+
].join(`
|
|
55937
|
+
|
|
55938
|
+
`);
|
|
55939
|
+
}
|
|
55455
55940
|
function buildGapApplyPlan(text, args) {
|
|
55456
|
-
const claimKey = semanticClaimKey(text);
|
|
55457
55941
|
const factId = hashId("FACT-ONTOLOGY-GAP", [
|
|
55458
55942
|
args.requirementId ?? "",
|
|
55459
55943
|
args.source ?? "",
|
|
@@ -55467,20 +55951,14 @@ function buildGapApplyPlan(text, args) {
|
|
|
55467
55951
|
title: "Ontology gap: predicate schema needed",
|
|
55468
55952
|
status: "active",
|
|
55469
55953
|
source: args.source ?? "mcp://kibi/suggest-predicates",
|
|
55470
|
-
text_ref: args.source,
|
|
55954
|
+
...args.source ? { text_ref: args.source } : {},
|
|
55471
55955
|
tags: ["review:ontology-gap", "needs_schema_extension"],
|
|
55472
55956
|
fact_kind: "observation",
|
|
55473
55957
|
value_string: text,
|
|
55474
|
-
claim_key: claimKey,
|
|
55475
55958
|
claim_text: text
|
|
55476
55959
|
},
|
|
55477
|
-
|
|
55478
|
-
|
|
55479
|
-
type: "relates_to",
|
|
55480
|
-
from: factId,
|
|
55481
|
-
to: "review:ontology-gap"
|
|
55482
|
-
}
|
|
55483
|
-
]
|
|
55960
|
+
document: { body: gapObservationBody(text, args) },
|
|
55961
|
+
relationships: []
|
|
55484
55962
|
}
|
|
55485
55963
|
];
|
|
55486
55964
|
}
|
|
@@ -55543,6 +56021,88 @@ var init_predicate_applyplan = __esm(() => {
|
|
|
55543
56021
|
init_predicate_utils();
|
|
55544
56022
|
});
|
|
55545
56023
|
|
|
56024
|
+
// ../cli/dist/operations/modeling/predicate-binding-hints.js
|
|
56025
|
+
function exampleArguments(example) {
|
|
56026
|
+
const open = example.indexOf("(");
|
|
56027
|
+
const close = example.lastIndexOf(")");
|
|
56028
|
+
if (open < 0 || close <= open)
|
|
56029
|
+
return [];
|
|
56030
|
+
const inner = example.slice(open + 1, close);
|
|
56031
|
+
const args = [];
|
|
56032
|
+
let depth = 0;
|
|
56033
|
+
let current = "";
|
|
56034
|
+
for (const char of inner) {
|
|
56035
|
+
if (char === "(" || char === "[")
|
|
56036
|
+
depth += 1;
|
|
56037
|
+
if (char === ")" || char === "]")
|
|
56038
|
+
depth -= 1;
|
|
56039
|
+
if (char === "," && depth === 0) {
|
|
56040
|
+
args.push(current.trim());
|
|
56041
|
+
current = "";
|
|
56042
|
+
continue;
|
|
56043
|
+
}
|
|
56044
|
+
current += char;
|
|
56045
|
+
}
|
|
56046
|
+
args.push(current.trim());
|
|
56047
|
+
return args.filter(Boolean);
|
|
56048
|
+
}
|
|
56049
|
+
function unboundReason(candidate, name, value, text) {
|
|
56050
|
+
const schema = candidate.schema;
|
|
56051
|
+
const provenance = candidate.binding_provenance_by_argument[name];
|
|
56052
|
+
const nameReason = nameOrStopWordReason(value, {
|
|
56053
|
+
argumentName: name,
|
|
56054
|
+
argumentNames: schema.argument_names,
|
|
56055
|
+
constants: schema.argument_constants?.[name],
|
|
56056
|
+
text
|
|
56057
|
+
});
|
|
56058
|
+
if (nameReason !== null)
|
|
56059
|
+
return `The value "${value}" is not a binding: ${nameReason}.`;
|
|
56060
|
+
if (!value.trim() || isGenericPlaceholder(value))
|
|
56061
|
+
return "The claim text names no value for this argument.";
|
|
56062
|
+
if (provenance === "inferred")
|
|
56063
|
+
return `The value "${value}" was inferred and does not appear in the claim text; confirm it or pass the exact value.`;
|
|
56064
|
+
if (schema.argument_constants?.[name])
|
|
56065
|
+
return `The value "${value}" is not one of this argument's declared constants.`;
|
|
56066
|
+
return `The value "${value}" needs review.`;
|
|
56067
|
+
}
|
|
56068
|
+
function buildBindingHints(candidate, text, requirementSubjects = []) {
|
|
56069
|
+
const schema = candidate.schema;
|
|
56070
|
+
const parsedExamples = schema.examples.map(exampleArguments);
|
|
56071
|
+
return candidate.unbound_arguments.map((name) => {
|
|
56072
|
+
const position = schema.argument_names.indexOf(name);
|
|
56073
|
+
const constants = schema.argument_constants?.[name];
|
|
56074
|
+
const exampleValues = parsedExamples.map((args) => args[position]).filter((value) => typeof value === "string");
|
|
56075
|
+
const examples = Array.from(new Set([
|
|
56076
|
+
...name === "subject" ? requirementSubjects : [],
|
|
56077
|
+
...constants ?? [],
|
|
56078
|
+
...exampleValues
|
|
56079
|
+
])).slice(0, MAX_EXAMPLES);
|
|
56080
|
+
const current = candidate.predicate_args[position] ?? "";
|
|
56081
|
+
const description = schema.argument_descriptions?.[position];
|
|
56082
|
+
return {
|
|
56083
|
+
argument: name,
|
|
56084
|
+
position,
|
|
56085
|
+
type: schema.argument_types[position] ?? "unknown",
|
|
56086
|
+
...description ? { description } : {},
|
|
56087
|
+
...constants ? { allowedValues: [...constants] } : {},
|
|
56088
|
+
examples,
|
|
56089
|
+
currentValue: current,
|
|
56090
|
+
provenance: candidate.binding_provenance_by_argument[name] ?? "placeholder",
|
|
56091
|
+
reason: unboundReason(candidate, name, current, text)
|
|
56092
|
+
};
|
|
56093
|
+
});
|
|
56094
|
+
}
|
|
56095
|
+
function describeBindingHints(hints) {
|
|
56096
|
+
return hints.map((hint) => {
|
|
56097
|
+
const values = hint.allowedValues ? `one of ${hint.allowedValues.join(", ")}` : hint.examples.length > 0 ? `e.g. ${hint.examples.join(", ")}` : "no example in the schema";
|
|
56098
|
+
return `${hint.argument} (${hint.type}, ${values})`;
|
|
56099
|
+
}).join("; ");
|
|
56100
|
+
}
|
|
56101
|
+
var MAX_EXAMPLES = 5;
|
|
56102
|
+
var init_predicate_binding_hints = __esm(() => {
|
|
56103
|
+
init_predicate_bindings();
|
|
56104
|
+
});
|
|
56105
|
+
|
|
55546
56106
|
// ../cli/dist/operations/modeling/suggest-predicates.js
|
|
55547
56107
|
function analyzeInputPropositions(text) {
|
|
55548
56108
|
return analyzeSemanticAdvisorInput({
|
|
@@ -55696,9 +56256,31 @@ async function existingClaimGrounding(prolog, requirementId, claimKey, warnings)
|
|
|
55696
56256
|
}
|
|
55697
56257
|
return found;
|
|
55698
56258
|
}
|
|
56259
|
+
function hasSubjectHint(value) {
|
|
56260
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
56261
|
+
}
|
|
56262
|
+
async function constrainedSubjectKeys(prolog, requirementId, warnings) {
|
|
56263
|
+
if (prolog === null || !requirementId?.trim())
|
|
56264
|
+
return [];
|
|
56265
|
+
try {
|
|
56266
|
+
const result = await prolog.query(`findall(Key, (kb_relationship(constrains, '${escapeAtom(requirementId.trim())}', _SubjectFact), kb:fact_subject_key(_SubjectFact, Key)), Keys)`);
|
|
56267
|
+
if (!result.success)
|
|
56268
|
+
return [];
|
|
56269
|
+
return Array.from(new Set(parsePrologList(result.bindings.Keys ?? "[]").map(unquoted).filter((key) => key.length > 0))).sort();
|
|
56270
|
+
} catch (error) {
|
|
56271
|
+
warnings.push(`The subject facts ${requirementId} constrains could not be read (${error instanceof Error ? error.message : String(error)}); pass subjectHint with the requirement's subject_key.`);
|
|
56272
|
+
return [];
|
|
56273
|
+
}
|
|
56274
|
+
}
|
|
55699
56275
|
async function handleKbSuggestPredicates(prolog, args, context) {
|
|
55700
56276
|
const text = normalizeText2(args.text);
|
|
55701
|
-
const
|
|
56277
|
+
const warnings = [];
|
|
56278
|
+
const requirementSubjects = hasSubjectHint(args.subjectHint) ? [] : await constrainedSubjectKeys(prolog, args.requirementId, warnings);
|
|
56279
|
+
const requirementSubject = requirementSubjects.length === 1 ? requirementSubjects[0] : undefined;
|
|
56280
|
+
const subject = inferSubject(text, args.subjectHint, {
|
|
56281
|
+
requirementId: args.requirementId,
|
|
56282
|
+
subjectKey: requirementSubject
|
|
56283
|
+
});
|
|
55702
56284
|
const propositions = analyzeInputPropositions(text);
|
|
55703
56285
|
const assertivePropositionCount = propositions.filter((proposition) => !NON_ASSERTIVE_PROPOSITION_ROLES.has(proposition.role)).length;
|
|
55704
56286
|
if (propositions.length > 0 && assertivePropositionCount === 0) {
|
|
@@ -55709,7 +56291,6 @@ async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
55709
56291
|
}
|
|
55710
56292
|
const maxCandidates = clampInteger(args.maxCandidates, DEFAULT_MAX_CANDIDATES, 1, 20);
|
|
55711
56293
|
const minScore = clampScore(args.minScore ?? DEFAULT_MIN_SCORE2);
|
|
55712
|
-
const warnings = [];
|
|
55713
56294
|
const existingSchemas = await loadExistingPredicateSchemas(prolog, args.includeExistingSchemas ?? true, warnings);
|
|
55714
56295
|
const composedCatalog = await composeOntologyCatalogForOperation(context, "kb_suggest_predicates");
|
|
55715
56296
|
const packSchemas = composedCatalog ? ontologyPackSchemasToCandidates(composedCatalog.schemas) : [];
|
|
@@ -55740,7 +56321,8 @@ async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
55740
56321
|
rejectionReasons: applicability.reasons,
|
|
55741
56322
|
applicabilityScore: applicability.applicabilityScore,
|
|
55742
56323
|
scoreComponents: ranked.components,
|
|
55743
|
-
explicitSubject: Boolean(args.subjectHint?.trim())
|
|
56324
|
+
explicitSubject: Boolean(args.subjectHint?.trim()),
|
|
56325
|
+
...requirementSubject ? { requirementSubject } : {}
|
|
55744
56326
|
});
|
|
55745
56327
|
});
|
|
55746
56328
|
const evaluatedCandidates = withMarginRejection(initialCandidates).sort((left, right) => {
|
|
@@ -55769,15 +56351,16 @@ async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
55769
56351
|
const applyPlan = completeCandidate ? alreadyGrounded ? [] : predicatePlan : !recommendedCandidate && !unavailableSchema ? buildGapApplyPlan(text, args) : [];
|
|
55770
56352
|
const plannedFactId = typeof predicatePlan[0]?.id === "string" ? predicatePlan[0].id : null;
|
|
55771
56353
|
const relationshipPlan = completeCandidate && !alreadyGrounded ? buildRelationshipPlan(plannedFactId ?? "", args.requirementId, text, args.existingLogicClaims) : null;
|
|
55772
|
-
const replacementPlan = alreadyGrounded && plannedFactId !== null && args.requirementId ? buildGroundingReplacementPlan(args.requirementId, plannedFactId, predicatePlan, existingGrounding) : null;
|
|
56354
|
+
const replacementPlan = alreadyGrounded && plannedFactId !== null && args.requirementId ? buildGroundingReplacementPlan(args.requirementId, plannedFactId, predicatePlan, existingGrounding, await storedRequirementProperties(prolog, args.requirementId, warnings)) : null;
|
|
55773
56355
|
const relationshipTarget = relationshipPlan !== null || replacementPlan !== null ? plannedFactId : null;
|
|
55774
56356
|
const groundingSummary = existingGrounding.map((row) => `${row.relationship.type} -> ${row.factId}`).join(", ");
|
|
55775
56357
|
if (alreadyGrounded) {
|
|
55776
56358
|
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."}`);
|
|
55777
56359
|
}
|
|
56360
|
+
const bindingHints = recommendedAction === "provide_argument_bindings" && recommendedCandidate ? buildBindingHints(recommendedCandidate, text, requirementSubjects) : [];
|
|
55778
56361
|
const recommendedPredicateSchema = !recommendedCandidate && !unavailableSchema ? buildPredicateSchemaDraft(text, subject) : null;
|
|
55779
56362
|
const groundedPrefix = alreadyGrounded ? `${args.requirementId} already grounds this claim through ${groundingSummary}. ` : "";
|
|
55780
|
-
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(", ")}. 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.");
|
|
56363
|
+
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.");
|
|
55781
56364
|
const logicClaims = Array.from(new Set([...args.existingLogicClaims ?? [], claimKey]));
|
|
55782
56365
|
return {
|
|
55783
56366
|
content: [{ type: "text", text: textSummary }],
|
|
@@ -55796,12 +56379,40 @@ async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
55796
56379
|
relationshipTarget,
|
|
55797
56380
|
existingGrounding,
|
|
55798
56381
|
replacementPlan,
|
|
56382
|
+
bindingHints,
|
|
55799
56383
|
warnings
|
|
55800
56384
|
},
|
|
55801
56385
|
applyPlan
|
|
55802
56386
|
};
|
|
55803
56387
|
}
|
|
55804
|
-
function
|
|
56388
|
+
async function storedRequirementProperties(prolog, requirementId, warnings) {
|
|
56389
|
+
if (prolog === null)
|
|
56390
|
+
return null;
|
|
56391
|
+
try {
|
|
56392
|
+
const [stored] = await loadEntities(prolog, {
|
|
56393
|
+
id: requirementId,
|
|
56394
|
+
type: "req"
|
|
56395
|
+
});
|
|
56396
|
+
if (stored === undefined)
|
|
56397
|
+
return null;
|
|
56398
|
+
const restated = {};
|
|
56399
|
+
for (const field of RESTATED_REQUIREMENT_FIELDS)
|
|
56400
|
+
if (stored[field] !== undefined && stored[field] !== null)
|
|
56401
|
+
restated[field] = stored[field];
|
|
56402
|
+
return typeof restated.title === "string" && typeof restated.status === "string" ? restated : null;
|
|
56403
|
+
} catch (error) {
|
|
56404
|
+
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.`);
|
|
56405
|
+
return null;
|
|
56406
|
+
}
|
|
56407
|
+
}
|
|
56408
|
+
function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, existing, stored) {
|
|
56409
|
+
const requirementUpsert = (relationships) => ({
|
|
56410
|
+
type: "req",
|
|
56411
|
+
id: requirementId,
|
|
56412
|
+
...stored === null ? {} : { properties: stored },
|
|
56413
|
+
relationships
|
|
56414
|
+
});
|
|
56415
|
+
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";
|
|
55805
56416
|
return {
|
|
55806
56417
|
relationshipTarget: factId,
|
|
55807
56418
|
steps: [
|
|
@@ -55819,30 +56430,33 @@ function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, exi
|
|
|
55819
56430
|
},
|
|
55820
56431
|
{
|
|
55821
56432
|
operation: "kb_upsert",
|
|
55822
|
-
input:
|
|
55823
|
-
type: "
|
|
55824
|
-
|
|
55825
|
-
|
|
55826
|
-
{ type: "requires_predicate", from: requirementId, to: factId }
|
|
55827
|
-
]
|
|
55828
|
-
},
|
|
55829
|
-
reason: `Link requires_predicate to ${factId}; upsert the requirement with its stored title and status and this relationship only.`
|
|
56433
|
+
input: requirementUpsert([
|
|
56434
|
+
{ type: "requires_predicate", from: requirementId, to: factId }
|
|
56435
|
+
]),
|
|
56436
|
+
reason: `Link requires_predicate to ${factId}; ${restate}.`
|
|
55830
56437
|
}
|
|
55831
56438
|
],
|
|
55832
|
-
|
|
56439
|
+
rollback: {
|
|
56440
|
+
operation: "kb_upsert",
|
|
56441
|
+
input: requirementUpsert(existing.map((row) => row.relationship)),
|
|
56442
|
+
reason: "Only if the last step fails: restore the retracted grounding link so the claim is grounded again."
|
|
56443
|
+
},
|
|
56444
|
+
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.`
|
|
55833
56445
|
};
|
|
55834
56446
|
}
|
|
55835
56447
|
async function executeSuggestPredicates(args, context) {
|
|
55836
56448
|
return handleKbSuggestPredicates(context.prolog ?? null, args, context);
|
|
55837
56449
|
}
|
|
55838
|
-
var DEFAULT_MAX_CANDIDATES = 5, DEFAULT_MIN_SCORE2 = 0.35, NON_ASSERTIVE_PROPOSITION_ROLES, GROUNDING_RELATIONSHIP_TYPES;
|
|
56450
|
+
var DEFAULT_MAX_CANDIDATES = 5, DEFAULT_MIN_SCORE2 = 0.35, NON_ASSERTIVE_PROPOSITION_ROLES, GROUNDING_RELATIONSHIP_TYPES, RESTATED_REQUIREMENT_FIELDS;
|
|
55839
56451
|
var init_suggest_predicates = __esm(() => {
|
|
56452
|
+
init_discovery_entities();
|
|
55840
56453
|
init_serialization();
|
|
55841
56454
|
init_analyze_prose();
|
|
55842
56455
|
init_clauses();
|
|
55843
56456
|
init_plugin_orchestration();
|
|
55844
56457
|
init_predicate_applicability();
|
|
55845
56458
|
init_predicate_applyplan();
|
|
56459
|
+
init_predicate_binding_hints();
|
|
55846
56460
|
init_predicate_catalog();
|
|
55847
56461
|
init_predicate_inference();
|
|
55848
56462
|
init_predicate_loader();
|
|
@@ -55858,6 +56472,13 @@ var init_suggest_predicates = __esm(() => {
|
|
|
55858
56472
|
"requires_predicate",
|
|
55859
56473
|
"requires_rule"
|
|
55860
56474
|
];
|
|
56475
|
+
RESTATED_REQUIREMENT_FIELDS = [
|
|
56476
|
+
"title",
|
|
56477
|
+
"status",
|
|
56478
|
+
"priority",
|
|
56479
|
+
"owner",
|
|
56480
|
+
"tags"
|
|
56481
|
+
];
|
|
55861
56482
|
});
|
|
55862
56483
|
|
|
55863
56484
|
// ../cli/dist/public/operations/specs/modeling.js
|
|
@@ -59870,7 +60491,7 @@ var init_skills = __esm(() => {
|
|
|
59870
60491
|
});
|
|
59871
60492
|
|
|
59872
60493
|
// ../cli/dist/public/operations/specs/skills.js
|
|
59873
|
-
import { createHash as
|
|
60494
|
+
import { createHash as createHash26 } from "node:crypto";
|
|
59874
60495
|
function assertNonEmptyString(value, field) {
|
|
59875
60496
|
if (typeof value !== "string" || value.trim() === "") {
|
|
59876
60497
|
throw new Error(`${field} must be a non-empty string`);
|
|
@@ -59891,7 +60512,7 @@ async function executeSkillsLoad(input, _context) {
|
|
|
59891
60512
|
assertNonEmptyString(id, "id");
|
|
59892
60513
|
const bundle = loadBundledSkill(id);
|
|
59893
60514
|
const resources = bundle.manifest.resources ?? [];
|
|
59894
|
-
const contentHash =
|
|
60515
|
+
const contentHash = createHash26("sha256").update(bundle.body, "utf8").digest("hex");
|
|
59895
60516
|
const resourceList = resources.length === 0 ? "none" : resources.join(", ");
|
|
59896
60517
|
return {
|
|
59897
60518
|
content: [
|
|
@@ -61648,16 +62269,16 @@ var init_audit = __esm(() => {
|
|
|
61648
62269
|
});
|
|
61649
62270
|
|
|
61650
62271
|
// ../cli/dist/operations/mutation/source-authoring.js
|
|
61651
|
-
import { createHash as
|
|
62272
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
61652
62273
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
61653
62274
|
import fs6 from "node:fs";
|
|
61654
62275
|
import path50 from "node:path";
|
|
61655
62276
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
61656
|
-
function
|
|
61657
|
-
return
|
|
62277
|
+
function digest3(value) {
|
|
62278
|
+
return createHash27("sha256").update(value).digest("hex");
|
|
61658
62279
|
}
|
|
61659
62280
|
function pendingReceiptPath(workspaceRoot, relativePath) {
|
|
61660
|
-
return path50.join(workspaceRoot, ".kb", "recovery", "pending-sources", `${
|
|
62281
|
+
return path50.join(workspaceRoot, ".kb", "recovery", "pending-sources", `${digest3(relativePath)}.json`);
|
|
61661
62282
|
}
|
|
61662
62283
|
function writePendingSourceReceipt(workspaceRoot, relativePath, afterHash) {
|
|
61663
62284
|
const receiptPath = pendingReceiptPath(workspaceRoot, relativePath);
|
|
@@ -62164,8 +62785,8 @@ async function writeSourceForUpsert(input, entity, existing, context, sourceDocu
|
|
|
62164
62785
|
const receipt = {
|
|
62165
62786
|
path: relative,
|
|
62166
62787
|
mode: "write",
|
|
62167
|
-
beforeHash: before === undefined ? null :
|
|
62168
|
-
afterHash:
|
|
62788
|
+
beforeHash: before === undefined ? null : digest3(before),
|
|
62789
|
+
afterHash: digest3(after),
|
|
62169
62790
|
created: before === undefined
|
|
62170
62791
|
};
|
|
62171
62792
|
const rollback = async () => {
|
|
@@ -62178,7 +62799,7 @@ async function writeSourceForUpsert(input, entity, existing, context, sourceDocu
|
|
|
62178
62799
|
} catch {
|
|
62179
62800
|
current = undefined;
|
|
62180
62801
|
}
|
|
62181
|
-
if (current !== undefined &&
|
|
62802
|
+
if (current !== undefined && digest3(current) !== digest3(after)) {
|
|
62182
62803
|
writePendingSourceReceipt(context.workspaceRoot, relative, receipt.afterHash);
|
|
62183
62804
|
console.warn(`Skipped source rollback for ${relative}: file changed after the Kibi write; kept concurrent content and recorded recovery metadata.`);
|
|
62184
62805
|
return;
|
|
@@ -62248,7 +62869,7 @@ var init_source_authoring = __esm(() => {
|
|
|
62248
62869
|
});
|
|
62249
62870
|
|
|
62250
62871
|
// ../cli/dist/operations/mutation/plan-apply-journal.js
|
|
62251
|
-
import { createHash as
|
|
62872
|
+
import { createHash as createHash28, randomUUID as randomUUID3 } from "node:crypto";
|
|
62252
62873
|
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";
|
|
62253
62874
|
import path51 from "node:path";
|
|
62254
62875
|
function planApplyJournalId(planHash) {
|
|
@@ -62258,7 +62879,7 @@ function isPlanApplyJournalId(value) {
|
|
|
62258
62879
|
return JOURNAL_ID_PATTERN.test(value);
|
|
62259
62880
|
}
|
|
62260
62881
|
function contentHash(value) {
|
|
62261
|
-
return
|
|
62882
|
+
return createHash28("sha256").update(value).digest("hex");
|
|
62262
62883
|
}
|
|
62263
62884
|
function errorText(error) {
|
|
62264
62885
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -63035,7 +63656,7 @@ var init_workspace_mutation_lock = __esm(() => {
|
|
|
63035
63656
|
});
|
|
63036
63657
|
|
|
63037
63658
|
// ../cli/dist/operations/mutation/delete.js
|
|
63038
|
-
import { createHash as
|
|
63659
|
+
import { createHash as createHash29, randomUUID as randomUUID4 } from "node:crypto";
|
|
63039
63660
|
import { existsSync as existsSync27, readFileSync as readFileSync29, writeFileSync as writeFileSync9 } from "node:fs";
|
|
63040
63661
|
import path53 from "node:path";
|
|
63041
63662
|
function requireProlog3(context) {
|
|
@@ -63073,7 +63694,7 @@ function sourceIsAuthored(source) {
|
|
|
63073
63694
|
function fileHash(pathname) {
|
|
63074
63695
|
if (!existsSync27(pathname))
|
|
63075
63696
|
return null;
|
|
63076
|
-
return
|
|
63697
|
+
return createHash29("sha256").update(readFileSync29(pathname)).digest("hex");
|
|
63077
63698
|
}
|
|
63078
63699
|
async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted = () => {
|
|
63079
63700
|
return;
|
|
@@ -63267,8 +63888,8 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
|
|
|
63267
63888
|
];
|
|
63268
63889
|
});
|
|
63269
63890
|
sourceWrites.push(...Array.from(sourcePatches, ([relative, patch]) => {
|
|
63270
|
-
const beforeHash =
|
|
63271
|
-
const afterHash =
|
|
63891
|
+
const beforeHash = createHash29("sha256").update(patch.before).digest("hex");
|
|
63892
|
+
const afterHash = createHash29("sha256").update(patch.after).digest("hex");
|
|
63272
63893
|
writePendingSourceReceipt(context.workspaceRoot, relative, afterHash);
|
|
63273
63894
|
return {
|
|
63274
63895
|
path: relative,
|
|
@@ -63400,8 +64021,8 @@ async function executeDelete(input, context) {
|
|
|
63400
64021
|
}
|
|
63401
64022
|
const deletion = renderSourceDeletion(relativeSource, id, String(entity.type), contents);
|
|
63402
64023
|
evolvingSourceBodies.set(relativeSource, deletion.mode === "write" ? deletion.body : undefined);
|
|
63403
|
-
const beforeHash =
|
|
63404
|
-
const afterHash = deletion.body === undefined ? null :
|
|
64024
|
+
const beforeHash = createHash29("sha256").update(original).digest("hex");
|
|
64025
|
+
const afterHash = deletion.body === undefined ? null : createHash29("sha256").update(deletion.body).digest("hex");
|
|
63405
64026
|
sourceHashes[relativeSource] = beforeHash;
|
|
63406
64027
|
sourcePlansByPath.set(relativeSource, {
|
|
63407
64028
|
path: relativeSource,
|
|
@@ -63427,13 +64048,13 @@ async function executeDelete(input, context) {
|
|
|
63427
64048
|
const relativeShard = path53.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
|
|
63428
64049
|
const original = readFileSync29(shardPath, "utf8");
|
|
63429
64050
|
const body = renderShardWithout(original, selectors, shardPath);
|
|
63430
|
-
const beforeHash =
|
|
64051
|
+
const beforeHash = createHash29("sha256").update(original).digest("hex");
|
|
63431
64052
|
sourceHashes[relativeShard] = beforeHash;
|
|
63432
64053
|
sourcePlansByPath.set(relativeShard, {
|
|
63433
64054
|
path: relativeShard,
|
|
63434
64055
|
mode: "write",
|
|
63435
64056
|
beforeHash,
|
|
63436
|
-
afterHash:
|
|
64057
|
+
afterHash: createHash29("sha256").update(body).digest("hex"),
|
|
63437
64058
|
body
|
|
63438
64059
|
});
|
|
63439
64060
|
}
|
|
@@ -63447,7 +64068,7 @@ async function executeDelete(input, context) {
|
|
|
63447
64068
|
sourceWrites: sourcePlans,
|
|
63448
64069
|
supersessionRequired
|
|
63449
64070
|
};
|
|
63450
|
-
const planHash =
|
|
64071
|
+
const planHash = createHash29("sha256").update(JSON.stringify(planBody)).digest("hex");
|
|
63451
64072
|
const payload = {
|
|
63452
64073
|
deleted: 0,
|
|
63453
64074
|
skipped: authoredIds.length,
|
|
@@ -64381,7 +65002,7 @@ var init_symbols_coordinator2 = __esm(() => {
|
|
|
64381
65002
|
});
|
|
64382
65003
|
|
|
64383
65004
|
// ../cli/dist/operations/mutation/symbol-refresh.js
|
|
64384
|
-
import { createHash as
|
|
65005
|
+
import { createHash as createHash30, randomUUID as randomUUID5 } from "node:crypto";
|
|
64385
65006
|
import { existsSync as existsSync29, readFileSync as readFileSync33, renameSync as renameSync7, unlinkSync as unlinkSync8, writeFileSync as writeFileSync11 } from "node:fs";
|
|
64386
65007
|
import * as path58 from "node:path";
|
|
64387
65008
|
function record2(value) {
|
|
@@ -64408,7 +65029,7 @@ function sourceTextFor(sourceFile, workspaceRoot) {
|
|
|
64408
65029
|
}
|
|
64409
65030
|
}
|
|
64410
65031
|
function contentHash2(content) {
|
|
64411
|
-
return
|
|
65032
|
+
return createHash30("sha256").update(content).digest("hex");
|
|
64412
65033
|
}
|
|
64413
65034
|
function restoreOrUnlinkCoordinateArtifact(targetPath, before) {
|
|
64414
65035
|
if (before === null) {
|
|
@@ -64608,7 +65229,7 @@ async function scenarioCoverageWarnings(prolog, relationships, entityType, entit
|
|
|
64608
65229
|
var init_warnings = () => {};
|
|
64609
65230
|
|
|
64610
65231
|
// ../cli/dist/operations/mutation/upsert.js
|
|
64611
|
-
import { createHash as
|
|
65232
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
64612
65233
|
import { existsSync as existsSync30, readFileSync as readFileSync34, unlinkSync as unlinkSync9, writeFileSync as writeFileSync12 } from "node:fs";
|
|
64613
65234
|
import path59 from "node:path";
|
|
64614
65235
|
function requireProlog4(context) {
|
|
@@ -64629,10 +65250,10 @@ function parseChangeKind(value) {
|
|
|
64629
65250
|
function fileHash2(pathname) {
|
|
64630
65251
|
if (!existsSync30(pathname))
|
|
64631
65252
|
return null;
|
|
64632
|
-
return
|
|
65253
|
+
return createHash31("sha256").update(readFileSync34(pathname)).digest("hex");
|
|
64633
65254
|
}
|
|
64634
65255
|
function textHash(value) {
|
|
64635
|
-
return
|
|
65256
|
+
return createHash31("sha256").update(value).digest("hex");
|
|
64636
65257
|
}
|
|
64637
65258
|
function assertRelationshipShardContained(workspaceRoot, shardPath) {
|
|
64638
65259
|
const root = path59.resolve(workspaceRoot);
|
|
@@ -66926,7 +67547,7 @@ var init_staging = __esm(() => {
|
|
|
66926
67547
|
|
|
66927
67548
|
// ../cli/dist/commands/sync.js
|
|
66928
67549
|
import { execSync as execSync4 } from "node:child_process";
|
|
66929
|
-
import { createHash as
|
|
67550
|
+
import { createHash as createHash32 } from "node:crypto";
|
|
66930
67551
|
import { existsSync as existsSync34, mkdirSync as mkdirSync12, readFileSync as readFileSync37, readdirSync as readdirSync9, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
|
|
66931
67552
|
import * as path64 from "node:path";
|
|
66932
67553
|
function relationshipKey2(relationship) {
|
|
@@ -66999,14 +67620,14 @@ function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissin
|
|
|
66999
67620
|
receiptPath,
|
|
67000
67621
|
path: relative,
|
|
67001
67622
|
afterHash: receipt.afterHash,
|
|
67002
|
-
rawHash:
|
|
67623
|
+
rawHash: createHash32("sha256").update(readFileSync37(receiptPath)).digest("hex")
|
|
67003
67624
|
});
|
|
67004
67625
|
}
|
|
67005
67626
|
continue;
|
|
67006
67627
|
}
|
|
67007
67628
|
throw new SyncError(`Pending source is missing: ${relative}.${PENDING_SOURCE_RECOVERY_HINT}`);
|
|
67008
67629
|
}
|
|
67009
|
-
const actual =
|
|
67630
|
+
const actual = createHash32("sha256").update(readFileSync37(absolute)).digest("hex");
|
|
67010
67631
|
if (actual !== receipt.afterHash) {
|
|
67011
67632
|
throw new SyncError(`Pending source hash drift blocks sync for ${relative}`);
|
|
67012
67633
|
}
|
|
@@ -67867,14 +68488,14 @@ var init_sync = __esm(() => {
|
|
|
67867
68488
|
});
|
|
67868
68489
|
|
|
67869
68490
|
// ../cli/dist/commands/branch.js
|
|
67870
|
-
import { createHash as
|
|
68491
|
+
import { createHash as createHash33 } from "node:crypto";
|
|
67871
68492
|
import * as fs8 from "node:fs";
|
|
67872
68493
|
import * as path65 from "node:path";
|
|
67873
68494
|
function isSupportedLegacyBranchMigration(from, to) {
|
|
67874
68495
|
return from === to;
|
|
67875
68496
|
}
|
|
67876
68497
|
function hashLegacyStore(sourcePath) {
|
|
67877
|
-
const hash =
|
|
68498
|
+
const hash = createHash33("sha256");
|
|
67878
68499
|
const visit = (directory, relative = "") => {
|
|
67879
68500
|
for (const entry of fs8.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name))) {
|
|
67880
68501
|
const absolute = path65.join(directory, entry.name);
|
|
@@ -67894,7 +68515,7 @@ function hashLegacyStore(sourcePath) {
|
|
|
67894
68515
|
}
|
|
67895
68516
|
function branchMigrationApprovalHash(from, to, sourcePath, targetPath) {
|
|
67896
68517
|
const sourceHash = hashLegacyStore(sourcePath);
|
|
67897
|
-
return
|
|
68518
|
+
return createHash33("sha256").update(JSON.stringify({
|
|
67898
68519
|
version: 2,
|
|
67899
68520
|
from,
|
|
67900
68521
|
to,
|
|
@@ -68187,7 +68808,7 @@ var init_branch = __esm(() => {
|
|
|
68187
68808
|
});
|
|
68188
68809
|
|
|
68189
68810
|
// ../cli/dist/operations/migration/inventory-rederive.js
|
|
68190
|
-
import { createHash as
|
|
68811
|
+
import { createHash as createHash34 } from "node:crypto";
|
|
68191
68812
|
import path66 from "node:path";
|
|
68192
68813
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
68193
68814
|
function isRecord17(value) {
|
|
@@ -68404,7 +69025,7 @@ function planOne(workspaceRoot, relativePath, entity, extracted, shards, facts)
|
|
|
68404
69025
|
summary: summarize2(changes, inventory),
|
|
68405
69026
|
changes,
|
|
68406
69027
|
contract,
|
|
68407
|
-
contractHash:
|
|
69028
|
+
contractHash: createHash34("sha256").update(canonicalJson3(contract)).digest("hex")
|
|
68408
69029
|
};
|
|
68409
69030
|
}
|
|
68410
69031
|
function readShardRelationships(workspaceRoot) {
|
|
@@ -68977,7 +69598,7 @@ ${KIBI_BIN_RESOLVER}
|
|
|
68977
69598
|
});
|
|
68978
69599
|
|
|
68979
69600
|
// ../cli/dist/commands/legacy-storage-migration.js
|
|
68980
|
-
import { createHash as
|
|
69601
|
+
import { createHash as createHash35 } from "node:crypto";
|
|
68981
69602
|
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";
|
|
68982
69603
|
import * as path70 from "node:path";
|
|
68983
69604
|
function stripGlobToRoot(pattern) {
|
|
@@ -69163,7 +69784,7 @@ function rewritePendingSourceReceiptPaths(cwd, moves) {
|
|
|
69163
69784
|
const absolute = path70.resolve(cwd, destination);
|
|
69164
69785
|
if (!existsSync37(absolute))
|
|
69165
69786
|
continue;
|
|
69166
|
-
const afterHash = typeof receipt.afterHash === "string" && /^[a-f0-9]{64}$/i.test(receipt.afterHash) ? receipt.afterHash :
|
|
69787
|
+
const afterHash = typeof receipt.afterHash === "string" && /^[a-f0-9]{64}$/i.test(receipt.afterHash) ? receipt.afterHash : createHash35("sha256").update(readFileSync40(absolute)).digest("hex");
|
|
69167
69788
|
writeFileSync18(receiptPath, `${JSON.stringify({ ...receipt, path: destination, afterHash }, null, 2)}
|
|
69168
69789
|
`, "utf8");
|
|
69169
69790
|
rewritten += 1;
|
|
@@ -69900,7 +70521,7 @@ var init_ignore_policy = __esm(() => {
|
|
|
69900
70521
|
|
|
69901
70522
|
// ../cli/dist/public/operations/node-ports.js
|
|
69902
70523
|
import { execFile as execFile2, execFileSync as execFileSync8 } from "node:child_process";
|
|
69903
|
-
import { createHash as
|
|
70524
|
+
import { createHash as createHash36 } from "node:crypto";
|
|
69904
70525
|
import * as fsSync from "node:fs";
|
|
69905
70526
|
import * as fs9 from "node:fs/promises";
|
|
69906
70527
|
import path72 from "node:path";
|
|
@@ -69930,7 +70551,7 @@ async function workspaceSnapshot(workspaceRoot) {
|
|
|
69930
70551
|
"-z"
|
|
69931
70552
|
], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 });
|
|
69932
70553
|
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);
|
|
69933
|
-
const digest =
|
|
70554
|
+
const digest = createHash36("sha256");
|
|
69934
70555
|
digest.update("kibi.workspace-snapshot.v2\x00");
|
|
69935
70556
|
for (const { raw, key: relativePath } of paths) {
|
|
69936
70557
|
digest.update(relativePath);
|
|
@@ -70321,7 +70942,7 @@ var init_cli_runtime = __esm(() => {
|
|
|
70321
70942
|
});
|
|
70322
70943
|
|
|
70323
70944
|
// ../cli/dist/public/operations/legacy-migration-plan.js
|
|
70324
|
-
import { createHash as
|
|
70945
|
+
import { createHash as createHash37 } from "node:crypto";
|
|
70325
70946
|
function isRecord20(value) {
|
|
70326
70947
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
70327
70948
|
}
|
|
@@ -70356,7 +70977,7 @@ function stableStringify(value) {
|
|
|
70356
70977
|
return JSON.stringify(stableValue3(value));
|
|
70357
70978
|
}
|
|
70358
70979
|
function hash(value) {
|
|
70359
|
-
return
|
|
70980
|
+
return createHash37("sha256").update(stableStringify(value)).digest("hex");
|
|
70360
70981
|
}
|
|
70361
70982
|
function migrationRepairBatches(plan) {
|
|
70362
70983
|
const seen = new Set;
|
|
@@ -70678,7 +71299,7 @@ var init_legacy_migration_plan = __esm(() => {
|
|
|
70678
71299
|
});
|
|
70679
71300
|
|
|
70680
71301
|
// ../cli/dist/public/operations/repair-plan.js
|
|
70681
|
-
import { createHash as
|
|
71302
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
70682
71303
|
function isRecord21(value) {
|
|
70683
71304
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
70684
71305
|
}
|
|
@@ -70821,7 +71442,7 @@ function buildRepairPlan(payload, input, codeSnapshot) {
|
|
|
70821
71442
|
},
|
|
70822
71443
|
batches
|
|
70823
71444
|
};
|
|
70824
|
-
const planId = `repair-plan-${
|
|
71445
|
+
const planId = `repair-plan-${createHash38("sha256").update(stableStringify2(planCore)).digest("hex").slice(0, 24)}`;
|
|
70825
71446
|
return {
|
|
70826
71447
|
version: REPAIR_PLAN_VERSION,
|
|
70827
71448
|
planId,
|
|
@@ -73923,7 +74544,7 @@ var init_migrate = __esm(() => {
|
|
|
73923
74544
|
});
|
|
73924
74545
|
|
|
73925
74546
|
// ../cli/dist/operations/planning/compile-intent.js
|
|
73926
|
-
import { createHash as
|
|
74547
|
+
import { createHash as createHash39 } from "node:crypto";
|
|
73927
74548
|
import path77 from "node:path";
|
|
73928
74549
|
function compilePlanHash(plan) {
|
|
73929
74550
|
const { planHash: _ignored, ...body } = plan;
|
|
@@ -73933,7 +74554,7 @@ function text7(value) {
|
|
|
73933
74554
|
return typeof value === "string" ? value.trim() : "";
|
|
73934
74555
|
}
|
|
73935
74556
|
function hash2(value) {
|
|
73936
|
-
return
|
|
74557
|
+
return createHash39("sha256").update(canonicalize(value)).digest("hex");
|
|
73937
74558
|
}
|
|
73938
74559
|
function shortHash2(value, length = 8) {
|
|
73939
74560
|
return hash2(value).slice(0, length);
|
|
@@ -74080,7 +74701,7 @@ async function sourceHashes(context, locations) {
|
|
|
74080
74701
|
for (const relative of sourceFilesFor(locations)) {
|
|
74081
74702
|
try {
|
|
74082
74703
|
const contents = context.fs ? await context.fs.readFile(path77.join(context.workspaceRoot, relative)) : null;
|
|
74083
|
-
hashes[relative] = contents === null ? null :
|
|
74704
|
+
hashes[relative] = contents === null ? null : createHash39("sha256").update(contents).digest("hex");
|
|
74084
74705
|
} catch {
|
|
74085
74706
|
hashes[relative] = null;
|
|
74086
74707
|
}
|
|
@@ -74665,7 +75286,7 @@ var init_compile_intent = __esm(() => {
|
|
|
74665
75286
|
});
|
|
74666
75287
|
|
|
74667
75288
|
// ../cli/dist/operations/planning/apply-plan.js
|
|
74668
|
-
import { createHash as
|
|
75289
|
+
import { createHash as createHash40, randomUUID as randomUUID6 } from "node:crypto";
|
|
74669
75290
|
import path78 from "node:path";
|
|
74670
75291
|
function text8(value) {
|
|
74671
75292
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -74673,8 +75294,8 @@ function text8(value) {
|
|
|
74673
75294
|
function isRecord23(value) {
|
|
74674
75295
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
74675
75296
|
}
|
|
74676
|
-
function
|
|
74677
|
-
return
|
|
75297
|
+
function digest4(value) {
|
|
75298
|
+
return createHash40("sha256").update(value).digest("hex");
|
|
74678
75299
|
}
|
|
74679
75300
|
function relationships(step) {
|
|
74680
75301
|
if (!Array.isArray(step.relationships))
|
|
@@ -74838,7 +75459,7 @@ function validateEntityDeletionPlan(args) {
|
|
|
74838
75459
|
throw new Error("Entity deletion apply failed: approvedPlanHash does not match planHash");
|
|
74839
75460
|
}
|
|
74840
75461
|
const { planHash: _ignored, ...body } = args.plan;
|
|
74841
|
-
if (
|
|
75462
|
+
if (createHash40("sha256").update(JSON.stringify(body)).digest("hex") !== args.plan.planHash) {
|
|
74842
75463
|
throw new Error("Entity deletion apply failed: planHash does not match the canonical plan body");
|
|
74843
75464
|
}
|
|
74844
75465
|
if (!Array.isArray(args.plan.entityIds) || args.plan.entityIds.length === 0) {
|
|
@@ -74917,7 +75538,7 @@ async function validateSources(context, sourceHashes) {
|
|
|
74917
75538
|
throw new Error("Apply plan failed: source hashes require a filesystem-capable runtime");
|
|
74918
75539
|
let actual;
|
|
74919
75540
|
try {
|
|
74920
|
-
actual =
|
|
75541
|
+
actual = digest4(await context.fs.readFile(path78.join(context.workspaceRoot, relative)));
|
|
74921
75542
|
} catch {
|
|
74922
75543
|
actual = null;
|
|
74923
75544
|
}
|
|
@@ -74946,12 +75567,12 @@ async function resolveSourceWriteTarget(workspaceRoot, fsPort, write) {
|
|
|
74946
75567
|
const existing = await fsPort.readFile(absolute).catch(() => {
|
|
74947
75568
|
return;
|
|
74948
75569
|
});
|
|
74949
|
-
const beforeHash = existing === undefined ? null :
|
|
75570
|
+
const beforeHash = existing === undefined ? null : digest4(existing);
|
|
74950
75571
|
if (beforeHash !== write.beforeHash) {
|
|
74951
75572
|
throw new Error(`Apply plan failed: source hash changed for ${write.path}`);
|
|
74952
75573
|
}
|
|
74953
75574
|
const mode = write.mode ?? "write";
|
|
74954
|
-
if (mode === "write" && (write.body === undefined || write.afterHash === null ||
|
|
75575
|
+
if (mode === "write" && (write.body === undefined || write.afterHash === null || digest4(write.body) !== write.afterHash)) {
|
|
74955
75576
|
throw new Error(`Apply plan failed: afterHash does not match staged body for ${write.path}`);
|
|
74956
75577
|
}
|
|
74957
75578
|
if (mode === "delete" && write.afterHash !== null) {
|
|
@@ -74995,7 +75616,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
74995
75616
|
for (const entry of prior.entries) {
|
|
74996
75617
|
try {
|
|
74997
75618
|
const current = await context.fs.readFile(path78.resolve(context.workspaceRoot, entry.path));
|
|
74998
|
-
if (entry.afterHash === null ||
|
|
75619
|
+
if (entry.afterHash === null || digest4(current) !== entry.afterHash) {
|
|
74999
75620
|
allAfter = false;
|
|
75000
75621
|
}
|
|
75001
75622
|
} catch {
|
|
@@ -75023,7 +75644,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
75023
75644
|
} catch {
|
|
75024
75645
|
current = undefined;
|
|
75025
75646
|
}
|
|
75026
|
-
const currentHash = current === undefined ? null :
|
|
75647
|
+
const currentHash = current === undefined ? null : digest4(current);
|
|
75027
75648
|
if (currentHash !== entry.beforeHash && currentHash !== entry.afterHash) {
|
|
75028
75649
|
throw new Error(`Apply plan recovery refused: ${entry.path} changed outside its journal`);
|
|
75029
75650
|
}
|
|
@@ -77915,7 +78536,7 @@ init_generate();
|
|
|
77915
78536
|
init_presentation();
|
|
77916
78537
|
init_ir();
|
|
77917
78538
|
// src/skill-operations.ts
|
|
77918
|
-
import { createHash as
|
|
78539
|
+
import { createHash as createHash41 } from "node:crypto";
|
|
77919
78540
|
|
|
77920
78541
|
// src/skill-system/loader.ts
|
|
77921
78542
|
import { existsSync as existsSync44, readFileSync as readFileSync47, readdirSync as readdirSync13, realpathSync as realpathSync10 } from "node:fs";
|
|
@@ -78187,7 +78808,7 @@ async function executeSkillsLoad2(input, _context) {
|
|
|
78187
78808
|
assertNonEmptyString2(id, "id");
|
|
78188
78809
|
const bundle = loadBundledSkill2(id);
|
|
78189
78810
|
const resources = bundle.manifest.resources ?? [];
|
|
78190
|
-
const contentHash =
|
|
78811
|
+
const contentHash = createHash41("sha256").update(bundle.body, "utf8").digest("hex");
|
|
78191
78812
|
const resourceList = resources.length === 0 ? "none" : resources.join(", ");
|
|
78192
78813
|
return {
|
|
78193
78814
|
content: [
|