kibi-runtime 2.13.0 → 2.13.1
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
|
@@ -6757,7 +6757,7 @@ function manifestVersion(manifestPath, expectedName) {
|
|
|
6757
6757
|
}
|
|
6758
6758
|
function cliVersion() {
|
|
6759
6759
|
if (true)
|
|
6760
|
-
return "2.
|
|
6760
|
+
return "2.16.0";
|
|
6761
6761
|
return manifestVersion(path2.join(moduleDirectory, "..", "package.json"), "kibi-cli") ?? "unknown";
|
|
6762
6762
|
}
|
|
6763
6763
|
function coreVersion() {
|
|
@@ -12218,7 +12218,7 @@ var init_search_answer = __esm(() => {
|
|
|
12218
12218
|
});
|
|
12219
12219
|
|
|
12220
12220
|
// ../cli/dist/utils/branch-store.js
|
|
12221
|
-
import { existsSync as existsSync10, readFileSync as readFileSync9, statSync as statSync6 } from "node:fs";
|
|
12221
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, readdirSync as readdirSync4, statSync as statSync6 } from "node:fs";
|
|
12222
12222
|
import * as path15 from "node:path";
|
|
12223
12223
|
function inspectBranchStore(workspaceRoot, branch) {
|
|
12224
12224
|
const storePath = branchStorePath(workspaceRoot, branch);
|
|
@@ -12354,9 +12354,86 @@ function branchStoreReason(inspection) {
|
|
|
12354
12354
|
remediation: inspection.recoveryRequired ? { command_argv: ["kibi", "branch", "recover"], applyRequired: true } : { command_argv: ["kibi", "branch", "ensure"], applyRequired: false }
|
|
12355
12355
|
};
|
|
12356
12356
|
}
|
|
12357
|
+
function countFiles(directory, extension) {
|
|
12358
|
+
let count = 0;
|
|
12359
|
+
let entries;
|
|
12360
|
+
try {
|
|
12361
|
+
entries = readdirSync4(directory, { withFileTypes: true });
|
|
12362
|
+
} catch {
|
|
12363
|
+
return 0;
|
|
12364
|
+
}
|
|
12365
|
+
for (const entry of entries) {
|
|
12366
|
+
if (entry.isDirectory()) {
|
|
12367
|
+
count += countFiles(path15.join(directory, entry.name), extension);
|
|
12368
|
+
} else if (entry.isFile() && entry.name.endsWith(extension)) {
|
|
12369
|
+
count += 1;
|
|
12370
|
+
}
|
|
12371
|
+
}
|
|
12372
|
+
return count;
|
|
12373
|
+
}
|
|
12374
|
+
function countAuthoredKbSources(workspaceRoot) {
|
|
12375
|
+
const kbRoot = path15.join(workspaceRoot, KB_ROOT);
|
|
12376
|
+
return AUTHORED_SOURCE_DIRECTORIES.reduce((total, [directory, extension]) => total + countFiles(path15.join(kbRoot, directory), extension), 0);
|
|
12377
|
+
}
|
|
12378
|
+
function branchStoreCompilation(inspection) {
|
|
12379
|
+
if (inspection.state === "missing") {
|
|
12380
|
+
return { compiled: false, generation: null };
|
|
12381
|
+
}
|
|
12382
|
+
const currentPath = path15.join(inspection.path, "CURRENT");
|
|
12383
|
+
let current = "";
|
|
12384
|
+
try {
|
|
12385
|
+
current = existsSync10(currentPath) ? readFileSync9(currentPath, "utf8").trim() : "";
|
|
12386
|
+
} catch {
|
|
12387
|
+
current = "";
|
|
12388
|
+
}
|
|
12389
|
+
if (current === "") {
|
|
12390
|
+
return { compiled: inspection.state === "healthy", generation: null };
|
|
12391
|
+
}
|
|
12392
|
+
const sequence = Number(current.split(":").at(-1));
|
|
12393
|
+
return {
|
|
12394
|
+
compiled: Number.isFinite(sequence) && sequence > 0 || journalHoldsGraphData(inspection.path),
|
|
12395
|
+
generation: current
|
|
12396
|
+
};
|
|
12397
|
+
}
|
|
12398
|
+
function journalHoldsGraphData(storePath) {
|
|
12399
|
+
try {
|
|
12400
|
+
return readdirSync4(path15.join(storePath, "rdf")).some((entry) => entry !== "lock" && !entry.startsWith("."));
|
|
12401
|
+
} catch {
|
|
12402
|
+
return false;
|
|
12403
|
+
}
|
|
12404
|
+
}
|
|
12405
|
+
function uncompiledBranchStoreReason(workspaceRoot, inspection, branch) {
|
|
12406
|
+
if (inspection.state !== "healthy" && inspection.state !== "missing") {
|
|
12407
|
+
return null;
|
|
12408
|
+
}
|
|
12409
|
+
const compilation = branchStoreCompilation(inspection);
|
|
12410
|
+
if (compilation.compiled)
|
|
12411
|
+
return null;
|
|
12412
|
+
const authoredSources = countAuthoredKbSources(workspaceRoot);
|
|
12413
|
+
if (authoredSources === 0)
|
|
12414
|
+
return null;
|
|
12415
|
+
const storeState = inspection.state === "missing" ? "does not exist yet" : `is empty (${compilation.generation ?? "no generation"}: nothing compiled)`;
|
|
12416
|
+
return {
|
|
12417
|
+
code: BRANCH_STORE_NOT_COMPILED,
|
|
12418
|
+
path: inspection.path,
|
|
12419
|
+
entityIds: [],
|
|
12420
|
+
detail: `The KB store for branch ${branch} ${storeState}, while .kb/ holds ${authoredSources} authored source file(s). Kibi compiles one store per branch and never copies another branch's, so every query and check reads an empty KB until this branch is compiled.`,
|
|
12421
|
+
remediation: { command_argv: ["kibi", "sync"], applyRequired: false },
|
|
12422
|
+
blocking: true,
|
|
12423
|
+
authoredSources,
|
|
12424
|
+
...compilation.generation !== null ? { generation: compilation.generation } : {}
|
|
12425
|
+
};
|
|
12426
|
+
}
|
|
12427
|
+
var BRANCH_STORE_NOT_COMPILED = "branch_store_not_compiled", BRANCH_STORE_NOT_COMPILED_RULE = "branch-store-not-compiled", AUTHORED_SOURCE_DIRECTORIES;
|
|
12357
12428
|
var init_branch_store = __esm(() => {
|
|
12358
12429
|
init_store_lock();
|
|
12359
12430
|
init_branch_store_locator();
|
|
12431
|
+
init_kb_paths();
|
|
12432
|
+
AUTHORED_SOURCE_DIRECTORIES = [
|
|
12433
|
+
...ENTITY_LANES.map((lane) => [lane, ".md"]),
|
|
12434
|
+
["adrs", ".md"],
|
|
12435
|
+
["relationships", ".yaml"]
|
|
12436
|
+
];
|
|
12360
12437
|
});
|
|
12361
12438
|
|
|
12362
12439
|
// ../cli/dist/utils/config.js
|
|
@@ -13381,8 +13458,27 @@ function buildActionsFromStatus(input) {
|
|
|
13381
13458
|
autoApplicable: configStatus.status !== "newer"
|
|
13382
13459
|
}));
|
|
13383
13460
|
}
|
|
13461
|
+
const uncompiled = (input.staleReasons ?? []).find((reason) => reason.code === BRANCH_STORE_NOT_COMPILED);
|
|
13462
|
+
if (uncompiled !== undefined) {
|
|
13463
|
+
actions.push(migrationAction({
|
|
13464
|
+
id: "branch-store-compile",
|
|
13465
|
+
code: BRANCH_STORE_NOT_COMPILED,
|
|
13466
|
+
category: "storage",
|
|
13467
|
+
safety: "automatic",
|
|
13468
|
+
invocation: { kind: "cli", command_argv: ["kibi", "sync"] },
|
|
13469
|
+
affectedFiles: [
|
|
13470
|
+
typeof store?.path === "string" ? store.path : ".kb/branches"
|
|
13471
|
+
],
|
|
13472
|
+
evidence: { reason: uncompiled },
|
|
13473
|
+
dependsOn: actions.map((action) => action.id).filter((id) => id === "branch-store-ensure" || id === "schema-config-upgrade"),
|
|
13474
|
+
postconditions: [{ branchStore: "compiled" }],
|
|
13475
|
+
autoApplicable: true
|
|
13476
|
+
}));
|
|
13477
|
+
}
|
|
13384
13478
|
for (const reason of input.staleReasons ?? []) {
|
|
13385
13479
|
const code = typeof reason.code === "string" ? reason.code : "stale_source";
|
|
13480
|
+
if (code === BRANCH_STORE_NOT_COMPILED)
|
|
13481
|
+
continue;
|
|
13386
13482
|
const file = typeof reason.path === "string" ? reason.path : "";
|
|
13387
13483
|
actions.push(migrationAction({
|
|
13388
13484
|
id: `freshness-${code}-${file}`,
|
|
@@ -13448,6 +13544,7 @@ function buildActionsFromStatus(input) {
|
|
|
13448
13544
|
}
|
|
13449
13545
|
var MIGRATION_PLAN_VERSION = "kibi.migration-plan.v2", PREDICATE_SCHEMA_ALIGNMENT_CODE = "predicate_schema_alignment";
|
|
13450
13546
|
var init_migration_plan = __esm(() => {
|
|
13547
|
+
init_branch_store();
|
|
13451
13548
|
init_config();
|
|
13452
13549
|
init_kb_manifest();
|
|
13453
13550
|
init_schema6_check_actions();
|
|
@@ -13659,7 +13756,8 @@ async function executeStatus(_input, context) {
|
|
|
13659
13756
|
}
|
|
13660
13757
|
const snapshotEvidence = await readWorkspaceSnapshot(context);
|
|
13661
13758
|
const existingReasons = payload.staleReasons ?? [];
|
|
13662
|
-
const storeReason = branchStoreReason(store);
|
|
13759
|
+
const storeReason = uncompiledBranchStoreReason(context.workspaceRoot, store, attachment.kbBranch) ?? branchStoreReason(store);
|
|
13760
|
+
const storeUncompiled = storeReason?.code === BRANCH_STORE_NOT_COMPILED;
|
|
13663
13761
|
const lockReason = storeLockJournalReason(store.path);
|
|
13664
13762
|
const compilerReason = compilerFingerprintReason(store.path);
|
|
13665
13763
|
const engineReason = engineStatus ? {
|
|
@@ -13682,6 +13780,7 @@ async function executeStatus(_input, context) {
|
|
|
13682
13780
|
const enrichedPayload = {
|
|
13683
13781
|
...payload,
|
|
13684
13782
|
...compilerReason ? { syncState: "stale", dirty: true } : {},
|
|
13783
|
+
...storeUncompiled && store.state === "healthy" ? { syncState: "stale", dirty: true } : {},
|
|
13685
13784
|
branchAttachment: attachment,
|
|
13686
13785
|
branchStore: store,
|
|
13687
13786
|
...engineStatus ? { engineStatus } : {},
|
|
@@ -13786,7 +13885,7 @@ async function executeStatus(_input, context) {
|
|
|
13786
13885
|
content: [
|
|
13787
13886
|
{
|
|
13788
13887
|
type: "text",
|
|
13789
|
-
text: `Branch ${payload.branch} is ${
|
|
13888
|
+
text: `Branch ${payload.branch} is ${enrichedPayload.syncState} (snapshot ${payload.snapshotId}, dirty=${enrichedPayload.dirty}, proofSnapshot=${enrichedPayload.proofSnapshot})${storeUncompiled ? `. Blocking: ${String(storeReason?.detail)} Run kibi sync.` : ""}`
|
|
13790
13889
|
}
|
|
13791
13890
|
],
|
|
13792
13891
|
structuredContent: statusWithPlan
|
|
@@ -23280,6 +23379,12 @@ var init_rule_registry_generated = __esm(() => {
|
|
|
23280
23379
|
enforcementClass: "canonical",
|
|
23281
23380
|
category: "integrity"
|
|
23282
23381
|
},
|
|
23382
|
+
{
|
|
23383
|
+
name: "branch-store-not-compiled",
|
|
23384
|
+
description: "The current branch's KB store must be compiled from the authored .kb/ sources; a missing or empty store is reported once, naming kibi sync, instead of every store-backed rule reading an empty KB",
|
|
23385
|
+
enforcementClass: "canonical",
|
|
23386
|
+
category: "integrity"
|
|
23387
|
+
},
|
|
23283
23388
|
{
|
|
23284
23389
|
name: "source-path-dangling",
|
|
23285
23390
|
description: "An authored entity's source field must name an existing workspace path (a #anchor suffix is ignored), an existing entity id, or an http(s) URL; a missing source is allowed",
|
|
@@ -23614,7 +23719,9 @@ function buildStableRequirementIds(claim) {
|
|
|
23614
23719
|
function buildStrictWriteSet(input) {
|
|
23615
23720
|
const statement = normalizeStatement(input.statement);
|
|
23616
23721
|
const confidence = normalizeConfidence(input.claim.confidence);
|
|
23617
|
-
const
|
|
23722
|
+
const minted = buildStableRequirementIds(input.claim);
|
|
23723
|
+
const requirementId = input.requirementId?.trim();
|
|
23724
|
+
const ids = requirementId ? { ...minted, reqId: requirementId } : minted;
|
|
23618
23725
|
const textRef = normalizeTextRef(input.claim.provenance, input.claim.source);
|
|
23619
23726
|
const metadataTags = buildMetadataTags({
|
|
23620
23727
|
confidence,
|
|
@@ -23904,6 +24011,9 @@ function normalizeEntityDirectory(directory) {
|
|
|
23904
24011
|
function buildEntitySourcePath(directory, entityId) {
|
|
23905
24012
|
return `${directory}/${entityId}.md`;
|
|
23906
24013
|
}
|
|
24014
|
+
function factSourcePath(factId) {
|
|
24015
|
+
return buildEntitySourcePath(resolveEntitySourcePaths().facts, factId);
|
|
24016
|
+
}
|
|
23907
24017
|
var STRICT_CONFIDENCE_THRESHOLD = 0.7, SUBJECT_KEY_CONVENTION, ORDERING_OPERATORS;
|
|
23908
24018
|
var init_strict_modeling = __esm(() => {
|
|
23909
24019
|
init_kb_paths();
|
|
@@ -27187,7 +27297,11 @@ function reuseExistingSubject(writeSet, existingFactId) {
|
|
|
27187
27297
|
subjectFact: {
|
|
27188
27298
|
...writeSet.subjectFact,
|
|
27189
27299
|
id: existingFactId,
|
|
27190
|
-
properties: {
|
|
27300
|
+
properties: {
|
|
27301
|
+
...writeSet.subjectFact.properties,
|
|
27302
|
+
id: existingFactId,
|
|
27303
|
+
source: factSourcePath(existingFactId)
|
|
27304
|
+
}
|
|
27191
27305
|
},
|
|
27192
27306
|
relationships: writeSet.relationships.map((relationship) => relationship.type === "constrains" ? { ...relationship, to: existingFactId } : relationship)
|
|
27193
27307
|
}
|
|
@@ -27213,10 +27327,11 @@ function possibleDuplicateObservation(claimKey, statement, source, candidates) {
|
|
|
27213
27327
|
}))
|
|
27214
27328
|
};
|
|
27215
27329
|
}
|
|
27216
|
-
async function applyVocabularyAlignment(context, extracted, claimKey) {
|
|
27330
|
+
async function applyVocabularyAlignment(context, extracted, claimKey, requirementId) {
|
|
27217
27331
|
const initial = buildStrictWriteSet({
|
|
27218
27332
|
claim: extracted.claim,
|
|
27219
|
-
statement: extracted.statement
|
|
27333
|
+
statement: extracted.statement,
|
|
27334
|
+
...requirementId !== undefined ? { requirementId } : {}
|
|
27220
27335
|
});
|
|
27221
27336
|
const unchanged = {
|
|
27222
27337
|
writeSet: initial,
|
|
@@ -27244,7 +27359,8 @@ async function applyVocabularyAlignment(context, extracted, claimKey) {
|
|
|
27244
27359
|
if (followsVocabulary) {
|
|
27245
27360
|
const rebuilt = buildStrictWriteSet({
|
|
27246
27361
|
claim: { ...extracted.claim, subjectKey: subject.subjectKey },
|
|
27247
|
-
statement: extracted.statement
|
|
27362
|
+
statement: extracted.statement,
|
|
27363
|
+
...requirementId !== undefined ? { requirementId } : {}
|
|
27248
27364
|
});
|
|
27249
27365
|
({ writeSet, replacedSubjectId } = reuseExistingSubject(rebuilt, subject.existingFactId));
|
|
27250
27366
|
} else {
|
|
@@ -27534,7 +27650,7 @@ async function handleKbModelRequirement(_prolog, args, workspaceRoot, context) {
|
|
|
27534
27650
|
if (conditional?.kind === "unparsed")
|
|
27535
27651
|
return unresolvedConditionalResult(args, extracted, conditional.reason, workspaceRoot);
|
|
27536
27652
|
const claimKey = semanticClaimKey(extracted.statement);
|
|
27537
|
-
const aligned = await applyVocabularyAlignment(context, extracted, claimKey);
|
|
27653
|
+
const aligned = await applyVocabularyAlignment(context, extracted, claimKey, normalizeOptionalString(args.requirementId));
|
|
27538
27654
|
const writeSet = aligned.writeSet;
|
|
27539
27655
|
const logicClaims = Array.from(new Set([...args.existingLogicClaims ?? [], claimKey]));
|
|
27540
27656
|
const plan = aligned.adjustPlan(strictWriteSetToApplyPlan(writeSet));
|
|
@@ -44852,13 +44968,13 @@ var init_check_policy_rules = __esm(() => {
|
|
|
44852
44968
|
});
|
|
44853
44969
|
|
|
44854
44970
|
// ../cli/dist/operations/migration/kb-sources.js
|
|
44855
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync7, readFileSync as readFileSync24, readdirSync as
|
|
44971
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync7, readFileSync as readFileSync24, readdirSync as readdirSync6, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
44856
44972
|
import path45 from "node:path";
|
|
44857
44973
|
import { isDeepStrictEqual } from "node:util";
|
|
44858
44974
|
function walkMarkdown(directory, files) {
|
|
44859
44975
|
let entries;
|
|
44860
44976
|
try {
|
|
44861
|
-
entries =
|
|
44977
|
+
entries = readdirSync6(directory, { withFileTypes: true, encoding: "utf8" });
|
|
44862
44978
|
} catch {
|
|
44863
44979
|
return;
|
|
44864
44980
|
}
|
|
@@ -53447,7 +53563,7 @@ var require_out4 = __commonJS(function(exports2, module2) {
|
|
|
53447
53563
|
import { execFile } from "node:child_process";
|
|
53448
53564
|
import { createHash as createHash24 } from "node:crypto";
|
|
53449
53565
|
import * as fs7 from "node:fs";
|
|
53450
|
-
import { existsSync as existsSync23, readFileSync as readFileSync27, readdirSync as
|
|
53566
|
+
import { existsSync as existsSync23, readFileSync as readFileSync27, readdirSync as readdirSync7, unlinkSync as unlinkSync4 } from "node:fs";
|
|
53451
53567
|
import * as path49 from "node:path";
|
|
53452
53568
|
import { promisify } from "node:util";
|
|
53453
53569
|
async function gitTrackedPaths(cwd) {
|
|
@@ -53461,7 +53577,7 @@ function pendingSourcePaths(cwd, recoverMissing) {
|
|
|
53461
53577
|
}
|
|
53462
53578
|
const paths = new Map;
|
|
53463
53579
|
const recoveredReceipts = [];
|
|
53464
|
-
for (const name of
|
|
53580
|
+
for (const name of readdirSync7(root)) {
|
|
53465
53581
|
if (!name.endsWith(".json"))
|
|
53466
53582
|
continue;
|
|
53467
53583
|
const receiptPath = path49.join(root, name);
|
|
@@ -53614,7 +53730,7 @@ async function discoverSourceFiles(cwd, options2 = {}) {
|
|
|
53614
53730
|
}
|
|
53615
53731
|
const pendingRoot = path49.join(cwd, ".kb", "recovery", "pending-sources");
|
|
53616
53732
|
if (options2.consumeTrackedPendingReceipts !== false && existsSync23(pendingRoot)) {
|
|
53617
|
-
for (const name of
|
|
53733
|
+
for (const name of readdirSync7(pendingRoot)) {
|
|
53618
53734
|
if (!name.endsWith(".json"))
|
|
53619
53735
|
continue;
|
|
53620
53736
|
try {
|
|
@@ -54176,7 +54292,8 @@ __export(exports_check_executor, {
|
|
|
54176
54292
|
buildSummary: () => buildSummary,
|
|
54177
54293
|
executeCheck: () => executeCheck,
|
|
54178
54294
|
getEffectiveRules: () => getEffectiveRules,
|
|
54179
|
-
resolveCheckRules: () => resolveCheckRules
|
|
54295
|
+
resolveCheckRules: () => resolveCheckRules,
|
|
54296
|
+
uncompiledBranchStoreViolation: () => uncompiledBranchStoreViolation
|
|
54180
54297
|
});
|
|
54181
54298
|
function requireProlog2(context) {
|
|
54182
54299
|
if (context.prolog === undefined) {
|
|
@@ -54212,6 +54329,33 @@ async function readStatusMigrationPlan(context) {
|
|
|
54212
54329
|
throw error;
|
|
54213
54330
|
}
|
|
54214
54331
|
}
|
|
54332
|
+
function uncompiledBranchStoreViolation(context, workspaceRoot) {
|
|
54333
|
+
let attachment;
|
|
54334
|
+
try {
|
|
54335
|
+
attachment = context.branchAttachment ?? resolveBranchAttachment(workspaceRoot);
|
|
54336
|
+
} catch {
|
|
54337
|
+
return null;
|
|
54338
|
+
}
|
|
54339
|
+
if ("error" in attachment)
|
|
54340
|
+
return null;
|
|
54341
|
+
const store = inspectBranchStore(workspaceRoot, attachment.kbBranch);
|
|
54342
|
+
const reason = uncompiledBranchStoreReason(workspaceRoot, store, attachment.kbBranch);
|
|
54343
|
+
if (reason === null)
|
|
54344
|
+
return null;
|
|
54345
|
+
return {
|
|
54346
|
+
rule: BRANCH_STORE_NOT_COMPILED_RULE,
|
|
54347
|
+
entityId: attachment.kbBranch,
|
|
54348
|
+
description: String(reason.detail),
|
|
54349
|
+
suggestion: "Run kibi sync to compile this branch's store from the authored .kb/ sources (or apply the branch-store-compile action of the returned migrationPlan with kb_apply_plan), then rerun kb_check. Run kibi init once to install the git hooks that compile a new branch on checkout.",
|
|
54350
|
+
source: store.path,
|
|
54351
|
+
evidence: {
|
|
54352
|
+
store: { state: store.state, path: store.path },
|
|
54353
|
+
authoredSources: reason.authoredSources,
|
|
54354
|
+
...reason.generation !== undefined ? { generation: reason.generation } : {},
|
|
54355
|
+
remediation: reason.remediation
|
|
54356
|
+
}
|
|
54357
|
+
};
|
|
54358
|
+
}
|
|
54215
54359
|
async function executeCheck(args, context, options2 = {}) {
|
|
54216
54360
|
try {
|
|
54217
54361
|
const workspaceRoot = args.workspaceRoot ?? context.workspaceRoot;
|
|
@@ -54227,6 +54371,39 @@ async function executeCheck(args, context, options2 = {}) {
|
|
|
54227
54371
|
...stagedEntityIdStyleDiagnostics(workspaceRoot, args)
|
|
54228
54372
|
];
|
|
54229
54373
|
const maxDiagnosticsOption = args.maxDiagnostics !== undefined ? { maxDiagnostics: args.maxDiagnostics } : {};
|
|
54374
|
+
const uncompiled = context.branchAttachment !== undefined || options2.branchStoreAttached === true ? uncompiledBranchStoreViolation(context, workspaceRoot) : null;
|
|
54375
|
+
if (uncompiled !== null) {
|
|
54376
|
+
const violations = [uncompiled];
|
|
54377
|
+
const statusPlan = await readStatusMigrationPlan(context);
|
|
54378
|
+
const migrationPlan = await migrationPlanForCheck(context, violations, [], statusPlan);
|
|
54379
|
+
return {
|
|
54380
|
+
content: [
|
|
54381
|
+
{
|
|
54382
|
+
type: "text",
|
|
54383
|
+
text: buildSummary({
|
|
54384
|
+
violations,
|
|
54385
|
+
impactResult,
|
|
54386
|
+
qualityDiagnostics: []
|
|
54387
|
+
})
|
|
54388
|
+
}
|
|
54389
|
+
],
|
|
54390
|
+
structuredContent: buildStructuredContent({
|
|
54391
|
+
violations,
|
|
54392
|
+
diagnostics: [
|
|
54393
|
+
{
|
|
54394
|
+
category: "SYNC_ERROR",
|
|
54395
|
+
severity: "error",
|
|
54396
|
+
message: uncompiled.description,
|
|
54397
|
+
...uncompiled.source !== undefined ? { file: uncompiled.source } : {},
|
|
54398
|
+
...uncompiled.suggestion !== undefined ? { suggestion: uncompiled.suggestion } : {}
|
|
54399
|
+
}
|
|
54400
|
+
],
|
|
54401
|
+
qualityDiagnostics: [],
|
|
54402
|
+
impactResult,
|
|
54403
|
+
migrationPlan
|
|
54404
|
+
})
|
|
54405
|
+
};
|
|
54406
|
+
}
|
|
54230
54407
|
if (rulesAllowlist.size === 0) {
|
|
54231
54408
|
const qualityDiagnostics = hasExplicitRules && options2.collectFullQualityDiagnosticsForExplicitRules !== true ? [] : impactResult ? impactQualityDiagnostics : await collectFullKbQualityDiagnostics({
|
|
54232
54409
|
prolog,
|
|
@@ -54327,6 +54504,8 @@ async function executeCheck(args, context, options2 = {}) {
|
|
|
54327
54504
|
}
|
|
54328
54505
|
var init_check_executor = __esm(() => {
|
|
54329
54506
|
init_aggregated_checks();
|
|
54507
|
+
init_branch_resolver();
|
|
54508
|
+
init_branch_store();
|
|
54330
54509
|
init_impact_diagnostics();
|
|
54331
54510
|
init_check_helpers();
|
|
54332
54511
|
init_check_policy_rules();
|
|
@@ -54340,7 +54519,7 @@ var init_check_executor = __esm(() => {
|
|
|
54340
54519
|
});
|
|
54341
54520
|
|
|
54342
54521
|
// ../cli/dist/public/operations/specs/check-rules.generated.js
|
|
54343
|
-
var SELECTABLE_RULE_NAMES, SELECTABLE_RULES_ALLOWED = "must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, source-relationship-parity, source-path-dangling, no-cycles, required-fields, deprecated-adr-no-successor, superseded-requirement-open, scenario-feasibility, scenario-feasibility-unknown, exception-claim-keys, numeric-string-value, rule-key-arguments-missing, domain-contradictions, logic-coverage, rule-safety, rule-verifiability, query-plan-safety, req-status-vocabulary, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, strict-readiness, semantic-completeness, related-requirement-unmodeled, proof-contract-symbols, entity-id-style, domain-redundancy, domain-implication, subject-key-identity, subject-key-shape, ontology-quality, exception-unapproved, exception-approval-self-attested, agent-requirement-unapproved, requirement-rationale-missing, symbol-owner-superseded, adr-unlinked, adr-proposed, predicate-schema-conformance, entity-context-missing, entity-context-acknowledged, policy-ownership, policy-markers";
|
|
54522
|
+
var SELECTABLE_RULE_NAMES, SELECTABLE_RULES_ALLOWED = "must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, source-relationship-parity, branch-store-not-compiled, source-path-dangling, no-cycles, required-fields, deprecated-adr-no-successor, superseded-requirement-open, scenario-feasibility, scenario-feasibility-unknown, exception-claim-keys, numeric-string-value, rule-key-arguments-missing, domain-contradictions, logic-coverage, rule-safety, rule-verifiability, query-plan-safety, req-status-vocabulary, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, strict-readiness, semantic-completeness, related-requirement-unmodeled, proof-contract-symbols, entity-id-style, domain-redundancy, domain-implication, subject-key-identity, subject-key-shape, ontology-quality, exception-unapproved, exception-approval-self-attested, agent-requirement-unapproved, requirement-rationale-missing, symbol-owner-superseded, adr-unlinked, adr-proposed, predicate-schema-conformance, entity-context-missing, entity-context-acknowledged, policy-ownership, policy-markers";
|
|
54344
54523
|
var init_check_rules_generated = __esm(() => {
|
|
54345
54524
|
SELECTABLE_RULE_NAMES = [
|
|
54346
54525
|
"must-priority-coverage",
|
|
@@ -54348,6 +54527,7 @@ var init_check_rules_generated = __esm(() => {
|
|
|
54348
54527
|
"symbol-traceability",
|
|
54349
54528
|
"no-dangling-refs",
|
|
54350
54529
|
"source-relationship-parity",
|
|
54530
|
+
"branch-store-not-compiled",
|
|
54351
54531
|
"source-path-dangling",
|
|
54352
54532
|
"no-cycles",
|
|
54353
54533
|
"required-fields",
|
|
@@ -57028,8 +57208,9 @@ function buildSuggestion(schema, text, subject, score, argumentBindings = {}, po
|
|
|
57028
57208
|
constrainedSubjects
|
|
57029
57209
|
})
|
|
57030
57210
|
]));
|
|
57031
|
-
const
|
|
57032
|
-
const
|
|
57211
|
+
const plannedSubjects = constrainedSubjects.length > 0 ? constrainedSubjects : explicitSubject ? [subject] : [];
|
|
57212
|
+
const subjectKey = plannedSubjects.length === 0 ? null : subjectArgument >= 0 ? predicateArgs[subjectArgument] ?? null : reviewedSubject ?? null;
|
|
57213
|
+
const subjectPairing = plannedSubjects.length === 0 ? "not_required" : subjectKey !== null && plannedSubjects.includes(subjectKey) ? "paired" : "unpaired";
|
|
57033
57214
|
const bindingProvenance = aggregateBindingProvenance(Object.values(bindingProvenanceByArgument));
|
|
57034
57215
|
const unboundArguments = schema.argument_names.filter((name) => undeclaredArguments.has(name) || !bindingCanBeApplied(bindingProvenanceByArgument[name] ?? "placeholder"));
|
|
57035
57216
|
if (subjectPairing === "unpaired") {
|
|
@@ -57831,7 +58012,7 @@ var init_modeling = __esm(() => {
|
|
|
57831
58012
|
},
|
|
57832
58013
|
requirementId: {
|
|
57833
58014
|
type: "string",
|
|
57834
|
-
description: "Optional
|
|
58015
|
+
description: "Optional requirement ID. The strict write set updates this requirement instead of minting a REQ-AUTO id, and a typed logic rule attaches its requires_rule relationship to it."
|
|
57835
58016
|
},
|
|
57836
58017
|
claimKey: {
|
|
57837
58018
|
type: "string",
|
|
@@ -61714,7 +61895,7 @@ var init_validation3 = __esm(() => {
|
|
|
61714
61895
|
});
|
|
61715
61896
|
|
|
61716
61897
|
// ../cli/dist/public/skill-system/loader.js
|
|
61717
|
-
import { existsSync as existsSync25, readFileSync as readFileSync29, readdirSync as
|
|
61898
|
+
import { existsSync as existsSync25, readFileSync as readFileSync29, readdirSync as readdirSync8, realpathSync as realpathSync8 } from "node:fs";
|
|
61718
61899
|
import { dirname as dirname11, join as join20, resolve as resolve16 } from "node:path";
|
|
61719
61900
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
61720
61901
|
function listBundledSkills() {
|
|
@@ -61735,7 +61916,7 @@ function readBundledSkillResource(id, resourcePath) {
|
|
|
61735
61916
|
function listFrom(dir) {
|
|
61736
61917
|
if (!existsSync25(dir))
|
|
61737
61918
|
return [];
|
|
61738
|
-
return
|
|
61919
|
+
return readdirSync8(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join20(dir, entry.name)).filter((root) => existsSync25(join20(root, SKILL_FILE_NAME))).map((root) => parseSkillBundle(root).manifest).sort((a, b) => a.id.localeCompare(b.id));
|
|
61739
61920
|
}
|
|
61740
61921
|
function findRoot(dir, id) {
|
|
61741
61922
|
return listRoots(dir).find((root) => parseSkillBundle(root).manifest.id === id);
|
|
@@ -61743,7 +61924,7 @@ function findRoot(dir, id) {
|
|
|
61743
61924
|
function listRoots(dir) {
|
|
61744
61925
|
if (!existsSync25(dir))
|
|
61745
61926
|
return [];
|
|
61746
|
-
return
|
|
61927
|
+
return readdirSync8(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join20(dir, entry.name)).filter((root) => existsSync25(join20(root, SKILL_FILE_NAME)));
|
|
61747
61928
|
}
|
|
61748
61929
|
function readBundle(bundle, id, resourcePath) {
|
|
61749
61930
|
const resource = normalizeResourcePath(resourcePath);
|
|
@@ -61898,6 +62079,28 @@ function requiredFields(spec) {
|
|
|
61898
62079
|
const required = spec.businessInputSchema.required;
|
|
61899
62080
|
return Array.isArray(required) ? required : [];
|
|
61900
62081
|
}
|
|
62082
|
+
function foreignParameterWarnings(selector, choice, routes, rest) {
|
|
62083
|
+
const route = routes[choice];
|
|
62084
|
+
if (route === undefined)
|
|
62085
|
+
return [];
|
|
62086
|
+
const own = new Set(Object.keys(properties2(route)));
|
|
62087
|
+
const equivalents = route.name === undefined ? {} : EQUIVALENT_PARAMETERS[route.name] ?? {};
|
|
62088
|
+
const warnings = [];
|
|
62089
|
+
for (const parameter of Object.keys(rest)) {
|
|
62090
|
+
if (own.has(parameter) || rest[parameter] === undefined)
|
|
62091
|
+
continue;
|
|
62092
|
+
const owners = Object.entries(routes).filter(([other, otherRoute]) => other !== choice && (parameter in properties2(otherRoute))).map(([other]) => `${selector}: ${other}`);
|
|
62093
|
+
if (owners.length === 0)
|
|
62094
|
+
continue;
|
|
62095
|
+
const equivalent = equivalents[parameter];
|
|
62096
|
+
warnings.push({
|
|
62097
|
+
parameter,
|
|
62098
|
+
message: `${parameter} is a ${owners.join(" / ")} argument; ${selector}: ${choice} ignored it.`,
|
|
62099
|
+
nextAction: equivalent !== undefined ? `Use ${equivalent} in ${selector}: ${choice}.` : `Drop ${parameter}, or switch to ${owners.join(" / ")} if that is what you meant.`
|
|
62100
|
+
});
|
|
62101
|
+
}
|
|
62102
|
+
return warnings;
|
|
62103
|
+
}
|
|
61901
62104
|
async function dispatchComposite(selector, routes, input, context) {
|
|
61902
62105
|
const choice = input[selector];
|
|
61903
62106
|
const route = typeof choice === "string" ? routes[choice] : undefined;
|
|
@@ -61916,16 +62119,46 @@ async function dispatchComposite(selector, routes, input, context) {
|
|
|
61916
62119
|
const structured = wrapped ? result.structuredContent : result;
|
|
61917
62120
|
const payload = isRecord(structured) ? structured : {};
|
|
61918
62121
|
const content = wrapped && Array.isArray(result.content) ? result.content : [{ type: "text", text: `${selector} ${String(choice)} completed` }];
|
|
62122
|
+
const ignored = foreignParameterWarnings(selector, String(choice), routes, rest);
|
|
62123
|
+
if (ignored.length === 0) {
|
|
62124
|
+
return {
|
|
62125
|
+
content,
|
|
62126
|
+
structuredContent: { [selector]: choice, ...payload }
|
|
62127
|
+
};
|
|
62128
|
+
}
|
|
62129
|
+
const asRecords = route.name !== undefined && RECORD_WARNING_OPERATIONS.has(route.name);
|
|
62130
|
+
const routedWarnings = Array.isArray(payload.warnings) ? {
|
|
62131
|
+
warnings: [
|
|
62132
|
+
...payload.warnings,
|
|
62133
|
+
...ignored.map((warning) => asRecords ? {
|
|
62134
|
+
kind: "parameter_ignored",
|
|
62135
|
+
message: warning.message,
|
|
62136
|
+
nextAction: warning.nextAction
|
|
62137
|
+
} : `${warning.message} ${warning.nextAction}`)
|
|
62138
|
+
]
|
|
62139
|
+
} : {};
|
|
61919
62140
|
return {
|
|
61920
|
-
content
|
|
61921
|
-
|
|
62141
|
+
content: [
|
|
62142
|
+
...content,
|
|
62143
|
+
{
|
|
62144
|
+
type: "text",
|
|
62145
|
+
text: ignored.map((warning) => `${warning.message} ${warning.nextAction}`).join(`
|
|
62146
|
+
`)
|
|
62147
|
+
}
|
|
62148
|
+
],
|
|
62149
|
+
structuredContent: { [selector]: choice, ...payload, ...routedWarnings }
|
|
61922
62150
|
};
|
|
61923
62151
|
}
|
|
61924
|
-
var SKILL_ROUTES, MODEL_ROUTES, skillsSpec, modelSpec;
|
|
62152
|
+
var EQUIVALENT_PARAMETERS, RECORD_WARNING_OPERATIONS, SKILL_ROUTES, MODEL_ROUTES, skillsSpec, modelSpec;
|
|
61925
62153
|
var init_composite = __esm(() => {
|
|
61926
62154
|
init_modeling();
|
|
61927
62155
|
init_semantic();
|
|
61928
62156
|
init_skills2();
|
|
62157
|
+
EQUIVALENT_PARAMETERS = {
|
|
62158
|
+
kb_suggest_predicates: { subjectKey: "subjectHint" },
|
|
62159
|
+
kb_model_requirement: { subjectHint: "subjectKey" }
|
|
62160
|
+
};
|
|
62161
|
+
RECORD_WARNING_OPERATIONS = new Set(["kb_model_requirement"]);
|
|
61929
62162
|
SKILL_ROUTES = {
|
|
61930
62163
|
list: skillsListSpec,
|
|
61931
62164
|
load: skillsLoadSpec,
|
|
@@ -64193,7 +64426,7 @@ var init_source_authoring = __esm(() => {
|
|
|
64193
64426
|
|
|
64194
64427
|
// ../cli/dist/operations/mutation/plan-apply-journal.js
|
|
64195
64428
|
import { createHash as createHash28, randomUUID as randomUUID3 } from "node:crypto";
|
|
64196
|
-
import { closeSync as closeSync3, existsSync as existsSync26, fsyncSync as fsyncSync2, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync30, readdirSync as
|
|
64429
|
+
import { closeSync as closeSync3, existsSync as existsSync26, fsyncSync as fsyncSync2, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync30, readdirSync as readdirSync9, renameSync as renameSync5, statSync as statSync10, unlinkSync as unlinkSync5, writeSync as writeSync2 } from "node:fs";
|
|
64197
64430
|
import path53 from "node:path";
|
|
64198
64431
|
function planApplyJournalId(planHash) {
|
|
64199
64432
|
return `plan-apply-${planHash.slice(0, 16).toLowerCase()}`;
|
|
@@ -64433,7 +64666,7 @@ function removeOrphanedStagedFiles(workspaceRoot, files) {
|
|
|
64433
64666
|
const prefix = `${path53.basename(absolute)}.kibi-stage-`;
|
|
64434
64667
|
let names;
|
|
64435
64668
|
try {
|
|
64436
|
-
names =
|
|
64669
|
+
names = readdirSync9(path53.dirname(absolute));
|
|
64437
64670
|
} catch {
|
|
64438
64671
|
continue;
|
|
64439
64672
|
}
|
|
@@ -64572,7 +64805,7 @@ async function recoverPendingPlanApplyJournals(context, options2) {
|
|
|
64572
64805
|
for (const directory of location.all) {
|
|
64573
64806
|
let names;
|
|
64574
64807
|
try {
|
|
64575
|
-
names =
|
|
64808
|
+
names = readdirSync9(directory);
|
|
64576
64809
|
} catch {
|
|
64577
64810
|
continue;
|
|
64578
64811
|
}
|
|
@@ -68895,7 +69128,7 @@ var init_staging = __esm(() => {
|
|
|
68895
69128
|
// ../cli/dist/commands/sync.js
|
|
68896
69129
|
import { execSync as execSync4 } from "node:child_process";
|
|
68897
69130
|
import { createHash as createHash32 } from "node:crypto";
|
|
68898
|
-
import { existsSync as existsSync34, mkdirSync as mkdirSync12, readFileSync as readFileSync40, readdirSync as
|
|
69131
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync12, readFileSync as readFileSync40, readdirSync as readdirSync10, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
|
|
68899
69132
|
import * as path66 from "node:path";
|
|
68900
69133
|
function relationshipKey2(relationship) {
|
|
68901
69134
|
return `${relationship.type}\x00${relationship.from}\x00${relationship.to}`;
|
|
@@ -68940,7 +69173,7 @@ function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissin
|
|
|
68940
69173
|
const pending = new Set;
|
|
68941
69174
|
const pendingRoot = path66.join(workspaceRoot, ".kb", "recovery", "pending-sources");
|
|
68942
69175
|
if (existsSync34(pendingRoot)) {
|
|
68943
|
-
for (const receiptName of
|
|
69176
|
+
for (const receiptName of readdirSync10(pendingRoot)) {
|
|
68944
69177
|
if (!receiptName.endsWith(".json"))
|
|
68945
69178
|
continue;
|
|
68946
69179
|
let receipt;
|
|
@@ -68982,7 +69215,7 @@ function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissin
|
|
|
68982
69215
|
}
|
|
68983
69216
|
}
|
|
68984
69217
|
try {
|
|
68985
|
-
return
|
|
69218
|
+
return readdirSync10(relationshipsDir).filter((file) => file.endsWith(".yaml") || file.endsWith(".yml")).map((file) => path66.join(relationshipsDir, file)).filter((file) => {
|
|
68986
69219
|
const relative = path66.relative(workspaceRoot, file).replaceAll(path66.sep, "/");
|
|
68987
69220
|
return tracked.has(relative) || pending.has(relative);
|
|
68988
69221
|
}).sort();
|
|
@@ -70946,7 +71179,7 @@ ${KIBI_BIN_RESOLVER}
|
|
|
70946
71179
|
|
|
70947
71180
|
// ../cli/dist/commands/legacy-storage-migration.js
|
|
70948
71181
|
import { createHash as createHash35 } from "node:crypto";
|
|
70949
|
-
import { existsSync as existsSync37, mkdirSync as mkdirSync15, readFileSync as readFileSync43, readdirSync as
|
|
71182
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync15, readFileSync as readFileSync43, readdirSync as readdirSync12, renameSync as renameSync12, rmSync as rmSync5, statSync as statSync12, writeFileSync as writeFileSync18 } from "node:fs";
|
|
70950
71183
|
import * as path72 from "node:path";
|
|
70951
71184
|
function stripGlobToRoot(pattern) {
|
|
70952
71185
|
const normalized = pattern.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
@@ -71103,7 +71336,7 @@ function pruneEmptyLegacyDirs(cwd, plan) {
|
|
|
71103
71336
|
const ordered = [...roots].sort((a, b) => b.length - a.length);
|
|
71104
71337
|
for (const dir of ordered) {
|
|
71105
71338
|
try {
|
|
71106
|
-
if (statSync12(dir).isDirectory() &&
|
|
71339
|
+
if (statSync12(dir).isDirectory() && readdirSync12(dir).length === 0) {
|
|
71107
71340
|
rmSync5(dir, { recursive: true });
|
|
71108
71341
|
}
|
|
71109
71342
|
} catch {}
|
|
@@ -71115,7 +71348,7 @@ function rewritePendingSourceReceiptPaths(cwd, moves) {
|
|
|
71115
71348
|
return 0;
|
|
71116
71349
|
const moveByFrom = new Map(moves.map((move) => [move.from, move.to]));
|
|
71117
71350
|
let rewritten = 0;
|
|
71118
|
-
for (const name of
|
|
71351
|
+
for (const name of readdirSync12(pendingRoot)) {
|
|
71119
71352
|
if (!name.endsWith(".json"))
|
|
71120
71353
|
continue;
|
|
71121
71354
|
const receiptPath = path72.join(pendingRoot, name);
|
|
@@ -71412,7 +71645,7 @@ var init_entity_body_context2 = __esm(() => {
|
|
|
71412
71645
|
});
|
|
71413
71646
|
|
|
71414
71647
|
// ../cli/dist/public/ignore-policy.js
|
|
71415
|
-
import { existsSync as existsSync38, readFileSync as readFileSync44, readdirSync as
|
|
71648
|
+
import { existsSync as existsSync38, readFileSync as readFileSync44, readdirSync as readdirSync13 } from "node:fs";
|
|
71416
71649
|
import * as path73 from "node:path";
|
|
71417
71650
|
function readIgnoreFileLines(filePath) {
|
|
71418
71651
|
if (!existsSync38(filePath))
|
|
@@ -71437,7 +71670,7 @@ function createRepoIgnorePolicy(workspaceRoot) {
|
|
|
71437
71670
|
function walk(dirAbs) {
|
|
71438
71671
|
let entries;
|
|
71439
71672
|
try {
|
|
71440
|
-
entries =
|
|
71673
|
+
entries = readdirSync13(dirAbs, { withFileTypes: true });
|
|
71441
71674
|
} catch {
|
|
71442
71675
|
return;
|
|
71443
71676
|
}
|
|
@@ -75632,9 +75865,220 @@ var init_migrate = __esm(() => {
|
|
|
75632
75865
|
]);
|
|
75633
75866
|
});
|
|
75634
75867
|
|
|
75635
|
-
// ../cli/dist/
|
|
75636
|
-
import {
|
|
75868
|
+
// ../cli/dist/proof/integrations.js
|
|
75869
|
+
import { existsSync as existsSync41, readFileSync as readFileSync48 } from "node:fs";
|
|
75637
75870
|
import path79 from "node:path";
|
|
75871
|
+
function integrationsPath(workspaceRoot) {
|
|
75872
|
+
return path79.join(workspaceRoot, PROOF_INTEGRATIONS_PATH);
|
|
75873
|
+
}
|
|
75874
|
+
function proofIntegrationErrors(value) {
|
|
75875
|
+
const file = record5(value);
|
|
75876
|
+
if (!file)
|
|
75877
|
+
return [
|
|
75878
|
+
`${PROOF_INTEGRATIONS_PATH} must be an object with version and integrations`
|
|
75879
|
+
];
|
|
75880
|
+
const errors = [];
|
|
75881
|
+
if (file.version !== PROOF_INTEGRATION_VERSION)
|
|
75882
|
+
errors.push(`version must be ${PROOF_INTEGRATION_VERSION}; received ${JSON.stringify(file.version ?? null)}`);
|
|
75883
|
+
if (!Array.isArray(file.integrations) || file.integrations.length === 0) {
|
|
75884
|
+
errors.push("integrations must be a non-empty array");
|
|
75885
|
+
return errors;
|
|
75886
|
+
}
|
|
75887
|
+
const seen = new Set;
|
|
75888
|
+
file.integrations.forEach((entry, index) => {
|
|
75889
|
+
const row = record5(entry);
|
|
75890
|
+
const label = `integrations[${index}]`;
|
|
75891
|
+
if (!row) {
|
|
75892
|
+
errors.push(`${label} must be an object`);
|
|
75893
|
+
return;
|
|
75894
|
+
}
|
|
75895
|
+
if (!nonEmpty(row.id))
|
|
75896
|
+
errors.push(`${label}.id must be a non-empty string`);
|
|
75897
|
+
else {
|
|
75898
|
+
if (seen.has(String(row.id)))
|
|
75899
|
+
errors.push(`${label}.id duplicates '${String(row.id)}'`);
|
|
75900
|
+
seen.add(String(row.id));
|
|
75901
|
+
}
|
|
75902
|
+
if (!nonEmpty(row.producer))
|
|
75903
|
+
errors.push(`${label}.producer must be one of: ${PRODUCER_KINDS.join(", ")} (or a custom producer id)`);
|
|
75904
|
+
if (!Array.isArray(row.command) || row.command.length === 0 || !row.command.every((argument) => nonEmpty(argument)))
|
|
75905
|
+
errors.push(`${label}.command must be a non-empty argv array`);
|
|
75906
|
+
if (nonEmpty(row.producer) && (row.producer === "junit" || row.producer === "tap") && !nonEmpty(row.artifact))
|
|
75907
|
+
errors.push(`${label}.artifact is required for producer '${String(row.producer)}' (path of the native report to convert)`);
|
|
75908
|
+
if (row.targets !== undefined) {
|
|
75909
|
+
if (!Array.isArray(row.targets) || row.targets.length === 0 || !row.targets.every((target) => nonEmpty(target)))
|
|
75910
|
+
errors.push(`${label}.targets must be a non-empty array of target names`);
|
|
75911
|
+
}
|
|
75912
|
+
if (row.options !== undefined && !record5(row.options))
|
|
75913
|
+
errors.push(`${label}.options must be an object when present`);
|
|
75914
|
+
if (row.description !== undefined && !nonEmpty(row.description))
|
|
75915
|
+
errors.push(`${label}.description must be a non-empty string when present`);
|
|
75916
|
+
});
|
|
75917
|
+
return errors;
|
|
75918
|
+
}
|
|
75919
|
+
function loadProofIntegrations(workspaceRoot) {
|
|
75920
|
+
const filePath = integrationsPath(workspaceRoot);
|
|
75921
|
+
if (!existsSync41(filePath)) {
|
|
75922
|
+
return {
|
|
75923
|
+
available: false,
|
|
75924
|
+
error: `No proof integration configuration at ${PROOF_INTEGRATIONS_PATH}. Run kibi proof inspect --json and apply its integrationPlan with kb_apply_plan to configure one.`
|
|
75925
|
+
};
|
|
75926
|
+
}
|
|
75927
|
+
let parsed;
|
|
75928
|
+
try {
|
|
75929
|
+
parsed = JSON.parse(readFileSync48(filePath, "utf8"));
|
|
75930
|
+
} catch (error) {
|
|
75931
|
+
return {
|
|
75932
|
+
available: false,
|
|
75933
|
+
error: `${PROOF_INTEGRATIONS_PATH} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
75934
|
+
};
|
|
75935
|
+
}
|
|
75936
|
+
const errors = proofIntegrationErrors(parsed);
|
|
75937
|
+
if (errors.length > 0)
|
|
75938
|
+
return {
|
|
75939
|
+
available: false,
|
|
75940
|
+
error: `Invalid ${PROOF_INTEGRATIONS_PATH}: ${errors.join("; ")}`
|
|
75941
|
+
};
|
|
75942
|
+
return { available: true, integrations: parsed };
|
|
75943
|
+
}
|
|
75944
|
+
function resolveIntegration(integrations, id) {
|
|
75945
|
+
return integrations.integrations.find((entry) => entry.id === id) ?? null;
|
|
75946
|
+
}
|
|
75947
|
+
function toExecution(integration) {
|
|
75948
|
+
return {
|
|
75949
|
+
id: integration.id,
|
|
75950
|
+
producer: integration.producer,
|
|
75951
|
+
...integration.producer_version !== undefined ? { producer_version: integration.producer_version } : {},
|
|
75952
|
+
command: integration.command,
|
|
75953
|
+
...integration.artifact !== undefined ? { artifact: integration.artifact } : {},
|
|
75954
|
+
...integration.targets !== undefined ? { targets: integration.targets } : {},
|
|
75955
|
+
...integration.options !== undefined ? { options: integration.options } : {}
|
|
75956
|
+
};
|
|
75957
|
+
}
|
|
75958
|
+
function record5(value) {
|
|
75959
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
75960
|
+
}
|
|
75961
|
+
function nonEmpty(value) {
|
|
75962
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
75963
|
+
}
|
|
75964
|
+
var PROOF_INTEGRATIONS_PATH = ".kb/proof/integrations.json", PRODUCER_KINDS;
|
|
75965
|
+
var init_integrations = __esm(() => {
|
|
75966
|
+
init_proof_protocol();
|
|
75967
|
+
PRODUCER_KINDS = [
|
|
75968
|
+
"command",
|
|
75969
|
+
"playwright",
|
|
75970
|
+
"junit",
|
|
75971
|
+
"tap"
|
|
75972
|
+
];
|
|
75973
|
+
});
|
|
75974
|
+
|
|
75975
|
+
// ../cli/dist/proof/integration-plan.js
|
|
75976
|
+
import { createHash as createHash39 } from "node:crypto";
|
|
75977
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync17, readFileSync as readFileSync49, renameSync as renameSync14, writeFileSync as writeFileSync20 } from "node:fs";
|
|
75978
|
+
import path80 from "node:path";
|
|
75979
|
+
function sha2563(bytes) {
|
|
75980
|
+
return createHash39("sha256").update(bytes).digest("hex");
|
|
75981
|
+
}
|
|
75982
|
+
function fileHash3(filePath) {
|
|
75983
|
+
try {
|
|
75984
|
+
return sha2563(readFileSync49(filePath));
|
|
75985
|
+
} catch {
|
|
75986
|
+
return null;
|
|
75987
|
+
}
|
|
75988
|
+
}
|
|
75989
|
+
function sourceHashes(root) {
|
|
75990
|
+
const hashes = {};
|
|
75991
|
+
for (const file of PROPOSAL_SOURCES) {
|
|
75992
|
+
const hash = fileHash3(path80.join(root, file));
|
|
75993
|
+
if (hash !== null)
|
|
75994
|
+
hashes[file] = hash;
|
|
75995
|
+
}
|
|
75996
|
+
return hashes;
|
|
75997
|
+
}
|
|
75998
|
+
function readIntegrationsFile(root) {
|
|
75999
|
+
try {
|
|
76000
|
+
const parsed = JSON.parse(readFileSync49(integrationsPath(root), "utf8"));
|
|
76001
|
+
return proofIntegrationErrors(parsed).length === 0 ? parsed : null;
|
|
76002
|
+
} catch {
|
|
76003
|
+
return null;
|
|
76004
|
+
}
|
|
76005
|
+
}
|
|
76006
|
+
function isRecord22(value) {
|
|
76007
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
76008
|
+
}
|
|
76009
|
+
function applyProofIntegrationAction(action, root) {
|
|
76010
|
+
const evidence = action.evidence;
|
|
76011
|
+
const integration = evidence.integration;
|
|
76012
|
+
if (evidence.path !== PROOF_INTEGRATIONS_PATH || evidence.mode !== "create" && evidence.mode !== "update" || !isRecord22(integration) || typeof integration.id !== "string")
|
|
76013
|
+
throw new Error(`Proof integration action '${action.id}' is malformed; rerun kibi proof inspect for a new plan.`);
|
|
76014
|
+
const planned = isRecord22(evidence.sourceHashes) ? evidence.sourceHashes : {};
|
|
76015
|
+
const live = sourceHashes(root);
|
|
76016
|
+
const changed = [
|
|
76017
|
+
...new Set([...Object.keys(planned), ...Object.keys(live)])
|
|
76018
|
+
].filter((file) => planned[file] !== live[file]);
|
|
76019
|
+
if (changed.length > 0)
|
|
76020
|
+
throw new Error(`Proof integration plan refused: ${changed.join(", ")} changed since planning; rerun kibi proof inspect and review the new plan.`);
|
|
76021
|
+
const filePath = integrationsPath(root);
|
|
76022
|
+
let integrations;
|
|
76023
|
+
if (evidence.mode === "create") {
|
|
76024
|
+
if (existsSync42(filePath))
|
|
76025
|
+
throw new Error(`Proof integration plan refused: ${PROOF_INTEGRATIONS_PATH} already exists and this plan only creates it. Run kibi proof inspect --update <integration id> for a plan that adds or replaces one named integration.`);
|
|
76026
|
+
integrations = [integration];
|
|
76027
|
+
} else {
|
|
76028
|
+
if (fileHash3(filePath) !== evidence.previousFileHash)
|
|
76029
|
+
throw new Error(`Proof integration plan refused: ${PROOF_INTEGRATIONS_PATH} changed since planning; rerun kibi proof inspect --update ${integration.id}.`);
|
|
76030
|
+
const current = readIntegrationsFile(root);
|
|
76031
|
+
if (current === null)
|
|
76032
|
+
throw new Error(`Proof integration plan refused: ${PROOF_INTEGRATIONS_PATH} is not a valid ${PROOF_INTEGRATION_VERSION} file.`);
|
|
76033
|
+
integrations = current.integrations.some((entry) => entry.id === integration.id) ? current.integrations.map((entry) => entry.id === integration.id ? integration : entry) : [...current.integrations, integration];
|
|
76034
|
+
}
|
|
76035
|
+
const file = { version: PROOF_INTEGRATION_VERSION, integrations };
|
|
76036
|
+
const errors = proofIntegrationErrors(file);
|
|
76037
|
+
if (errors.length > 0)
|
|
76038
|
+
throw new Error(`Proof integration plan refused: the result would be invalid (${errors.join("; ")}).`);
|
|
76039
|
+
mkdirSync17(path80.dirname(filePath), { recursive: true });
|
|
76040
|
+
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
76041
|
+
writeFileSync20(temporary, `${JSON.stringify(file, null, 2)}
|
|
76042
|
+
`, "utf8");
|
|
76043
|
+
renameSync14(temporary, filePath);
|
|
76044
|
+
}
|
|
76045
|
+
var PROOF_INTEGRATION_CONFIGURE = "proof_integration_configure", PROPOSAL_SOURCES;
|
|
76046
|
+
var init_integration_plan = __esm(() => {
|
|
76047
|
+
init_migration_plan();
|
|
76048
|
+
init_proof_protocol();
|
|
76049
|
+
init_integrations();
|
|
76050
|
+
PROPOSAL_SOURCES = [
|
|
76051
|
+
"package.json",
|
|
76052
|
+
"bun.lock",
|
|
76053
|
+
"bun.lockb",
|
|
76054
|
+
"pnpm-lock.yaml",
|
|
76055
|
+
"yarn.lock",
|
|
76056
|
+
"playwright.config.ts",
|
|
76057
|
+
"playwright.config.mjs",
|
|
76058
|
+
"playwright.config.js",
|
|
76059
|
+
"vitest.config.ts",
|
|
76060
|
+
"vitest.config.mjs",
|
|
76061
|
+
"vitest.config.js",
|
|
76062
|
+
"jest.config.ts",
|
|
76063
|
+
"jest.config.mjs",
|
|
76064
|
+
"jest.config.js",
|
|
76065
|
+
"pytest.ini",
|
|
76066
|
+
"pyproject.toml",
|
|
76067
|
+
"setup.cfg",
|
|
76068
|
+
"tox.ini",
|
|
76069
|
+
"go.mod",
|
|
76070
|
+
"Cargo.toml",
|
|
76071
|
+
"pom.xml",
|
|
76072
|
+
"build.gradle",
|
|
76073
|
+
"build.gradle.kts",
|
|
76074
|
+
"Gemfile",
|
|
76075
|
+
"Rakefile"
|
|
76076
|
+
];
|
|
76077
|
+
});
|
|
76078
|
+
|
|
76079
|
+
// ../cli/dist/operations/planning/compile-intent.js
|
|
76080
|
+
import { createHash as createHash40 } from "node:crypto";
|
|
76081
|
+
import path81 from "node:path";
|
|
75638
76082
|
function compilePlanHash(plan) {
|
|
75639
76083
|
const { planHash: _ignored, ...body } = plan;
|
|
75640
76084
|
return hash2(body);
|
|
@@ -75643,7 +76087,7 @@ function text7(value) {
|
|
|
75643
76087
|
return typeof value === "string" ? value.trim() : "";
|
|
75644
76088
|
}
|
|
75645
76089
|
function hash2(value) {
|
|
75646
|
-
return
|
|
76090
|
+
return createHash40("sha256").update(canonicalize(value)).digest("hex");
|
|
75647
76091
|
}
|
|
75648
76092
|
function shortHash2(value, length = 8) {
|
|
75649
76093
|
return hash2(value).slice(0, length);
|
|
@@ -75671,7 +76115,7 @@ function requiredIntent(args) {
|
|
|
75671
76115
|
return intent;
|
|
75672
76116
|
}
|
|
75673
76117
|
function validateLocation(location) {
|
|
75674
|
-
if (!text7(location.path) ||
|
|
76118
|
+
if (!text7(location.path) || path81.isAbsolute(location.path) || location.path.split(/[\\/]/).includes("..")) {
|
|
75675
76119
|
throw new Error("Compile intent failed: sourceLocations.path must be workspace-relative");
|
|
75676
76120
|
}
|
|
75677
76121
|
}
|
|
@@ -75701,25 +76145,25 @@ function mergeSteps(steps) {
|
|
|
75701
76145
|
merged.set(key, {
|
|
75702
76146
|
...step,
|
|
75703
76147
|
...Array.isArray(step.relationships) ? {
|
|
75704
|
-
relationships: mergeRelationships(step.relationships.filter(
|
|
76148
|
+
relationships: mergeRelationships(step.relationships.filter(isRecord23))
|
|
75705
76149
|
} : {}
|
|
75706
76150
|
});
|
|
75707
76151
|
continue;
|
|
75708
76152
|
}
|
|
75709
76153
|
const properties = {
|
|
75710
|
-
...
|
|
75711
|
-
...
|
|
76154
|
+
...isRecord23(previous.properties) ? previous.properties : {},
|
|
76155
|
+
...isRecord23(step.properties) ? step.properties : {}
|
|
75712
76156
|
};
|
|
75713
76157
|
const relationships = mergeRelationships([
|
|
75714
|
-
...Array.isArray(previous.relationships) ? previous.relationships.filter(
|
|
75715
|
-
...Array.isArray(step.relationships) ? step.relationships.filter(
|
|
76158
|
+
...Array.isArray(previous.relationships) ? previous.relationships.filter(isRecord23) : [],
|
|
76159
|
+
...Array.isArray(step.relationships) ? step.relationships.filter(isRecord23) : []
|
|
75716
76160
|
]);
|
|
75717
76161
|
merged.set(key, { ...previous, ...step, properties, relationships });
|
|
75718
76162
|
}
|
|
75719
76163
|
const rank = (step) => ({ test: 1, scenario: 2, req: 3 })[text7(step.type)] ?? 0;
|
|
75720
76164
|
return [...merged.values()].sort((left, right) => rank(left) - rank(right) || text7(left.id).localeCompare(text7(right.id)));
|
|
75721
76165
|
}
|
|
75722
|
-
function
|
|
76166
|
+
function isRecord23(value) {
|
|
75723
76167
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
75724
76168
|
}
|
|
75725
76169
|
function withRequirementInventory(steps, requirementId, receipt, propositions) {
|
|
@@ -75740,7 +76184,7 @@ function withRequirementInventory(steps, requirementId, receipt, propositions) {
|
|
|
75740
76184
|
return steps.map((step) => {
|
|
75741
76185
|
if (text7(step.type) !== "req" || text7(step.id) !== requirementId)
|
|
75742
76186
|
return step;
|
|
75743
|
-
const properties =
|
|
76187
|
+
const properties = isRecord23(step.properties) ? step.properties : {};
|
|
75744
76188
|
return {
|
|
75745
76189
|
...step,
|
|
75746
76190
|
properties: {
|
|
@@ -75785,12 +76229,12 @@ function propositionDisposition2(proposition, suggestion) {
|
|
|
75785
76229
|
function sourceFilesFor(locations) {
|
|
75786
76230
|
return Array.from(new Set((locations ?? []).map((location) => location.path.trim()).filter(Boolean))).sort();
|
|
75787
76231
|
}
|
|
75788
|
-
async function
|
|
76232
|
+
async function sourceHashes2(context, locations) {
|
|
75789
76233
|
const hashes = {};
|
|
75790
76234
|
for (const relative of sourceFilesFor(locations)) {
|
|
75791
76235
|
try {
|
|
75792
|
-
const contents = context.fs ? await context.fs.readFile(
|
|
75793
|
-
hashes[relative] = contents === null ? null :
|
|
76236
|
+
const contents = context.fs ? await context.fs.readFile(path81.join(context.workspaceRoot, relative)) : null;
|
|
76237
|
+
hashes[relative] = contents === null ? null : createHash40("sha256").update(contents).digest("hex");
|
|
75794
76238
|
} catch {
|
|
75795
76239
|
hashes[relative] = null;
|
|
75796
76240
|
}
|
|
@@ -75812,12 +76256,12 @@ async function withDocumentTargets(context, prolog, steps, requirement, now) {
|
|
|
75812
76256
|
for (const step of steps) {
|
|
75813
76257
|
const type = text7(step.type);
|
|
75814
76258
|
const id = text7(step.id);
|
|
75815
|
-
const properties =
|
|
76259
|
+
const properties = isRecord23(step.properties) ? step.properties : {};
|
|
75816
76260
|
if (type === "symbol" || Object.keys(properties).length === 0) {
|
|
75817
76261
|
targeted.push(step);
|
|
75818
76262
|
continue;
|
|
75819
76263
|
}
|
|
75820
|
-
const stepDocument =
|
|
76264
|
+
const stepDocument = isRecord23(step.document) ? step.document : {};
|
|
75821
76265
|
const document = type === "req" && id === requirement.id ? {
|
|
75822
76266
|
...requirement.body !== undefined ? { body: requirement.body } : {},
|
|
75823
76267
|
...requirement.path !== undefined ? { path: requirement.path } : {}
|
|
@@ -75827,7 +76271,7 @@ async function withDocumentTargets(context, prolog, steps, requirement, now) {
|
|
|
75827
76271
|
type,
|
|
75828
76272
|
id,
|
|
75829
76273
|
properties,
|
|
75830
|
-
relationships: Array.isArray(step.relationships) ? step.relationships.filter(
|
|
76274
|
+
relationships: Array.isArray(step.relationships) ? step.relationships.filter(isRecord23) : [],
|
|
75831
76275
|
document
|
|
75832
76276
|
};
|
|
75833
76277
|
const { entity } = validateUpsertInput(input, now);
|
|
@@ -75846,7 +76290,7 @@ async function existingRequirementBody(context, source) {
|
|
|
75846
76290
|
if (!context.fs || !source.endsWith(".md"))
|
|
75847
76291
|
return;
|
|
75848
76292
|
try {
|
|
75849
|
-
const raw = await context.fs.readFile(
|
|
76293
|
+
const raw = await context.fs.readFile(path81.join(context.workspaceRoot, source));
|
|
75850
76294
|
return readAuthoredEntity(String(raw), source)?.body ?? undefined;
|
|
75851
76295
|
} catch {
|
|
75852
76296
|
return;
|
|
@@ -75857,12 +76301,12 @@ function generatedRequirementId(intent) {
|
|
|
75857
76301
|
}
|
|
75858
76302
|
function planWhatIfGoal(steps, now) {
|
|
75859
76303
|
return buildWhatIfAnalysisGoal(steps.map((step) => {
|
|
75860
|
-
const relationships = (Array.isArray(step.relationships) ? step.relationships.filter(
|
|
76304
|
+
const relationships = (Array.isArray(step.relationships) ? step.relationships.filter(isRecord23) : []).map((relationship) => ({
|
|
75861
76305
|
type: text7(relationship.type),
|
|
75862
76306
|
from: text7(relationship.from),
|
|
75863
76307
|
to: text7(relationship.to)
|
|
75864
76308
|
}));
|
|
75865
|
-
const properties =
|
|
76309
|
+
const properties = isRecord23(step.properties) ? step.properties : {};
|
|
75866
76310
|
if (Object.keys(properties).length === 0) {
|
|
75867
76311
|
return {
|
|
75868
76312
|
entity: { id: text7(step.id), type: text7(step.type) },
|
|
@@ -75894,7 +76338,7 @@ function whatIfWitness(witness) {
|
|
|
75894
76338
|
};
|
|
75895
76339
|
}
|
|
75896
76340
|
function whatIfWitnesses(value) {
|
|
75897
|
-
return (Array.isArray(value) ? value.filter(
|
|
76341
|
+
return (Array.isArray(value) ? value.filter(isRecord23) : []).map(whatIfWitness);
|
|
75898
76342
|
}
|
|
75899
76343
|
function parseWhatIfAnalysis(raw) {
|
|
75900
76344
|
if (typeof raw !== "string")
|
|
@@ -75911,7 +76355,7 @@ function parseWhatIfAnalysis(raw) {
|
|
|
75911
76355
|
const after = whatIfWitnesses(parsed);
|
|
75912
76356
|
return { after, introduced: after, removed: [], unchanged: [] };
|
|
75913
76357
|
}
|
|
75914
|
-
if (!
|
|
76358
|
+
if (!isRecord23(parsed))
|
|
75915
76359
|
return null;
|
|
75916
76360
|
return {
|
|
75917
76361
|
after: whatIfWitnesses(parsed.after),
|
|
@@ -75986,7 +76430,7 @@ function applyAcceptedProposals(steps, proposals) {
|
|
|
75986
76430
|
if (!existing)
|
|
75987
76431
|
continue;
|
|
75988
76432
|
const relationships = mergeRelationships([
|
|
75989
|
-
...Array.isArray(existing.relationships) ? existing.relationships.filter(
|
|
76433
|
+
...Array.isArray(existing.relationships) ? existing.relationships.filter(isRecord23) : [],
|
|
75990
76434
|
proposal.relationship
|
|
75991
76435
|
]);
|
|
75992
76436
|
byId.set(targetId, { ...existing, relationships });
|
|
@@ -76294,7 +76738,7 @@ async function executeCompileIntent(args, context) {
|
|
|
76294
76738
|
diagnostics.push("Change mode to update and supply requirementId to revise an existing requirement.");
|
|
76295
76739
|
const unresolved = propositions.some((proposition) => proposition.status === "ambiguous" || proposition.status === "ontology_gap") || diagnostics.some((entry) => entry.includes("unresolved") || entry.includes("not found") || entry.includes("different content"));
|
|
76296
76740
|
let statusValue = contradictions.outcome === "conflict" ? "blocked" : unresolved ? "needs_resolution" : "ready";
|
|
76297
|
-
const sourceHashMap = await
|
|
76741
|
+
const sourceHashMap = await sourceHashes2(context, args.sourceLocations);
|
|
76298
76742
|
let planSteps = stepsWithAcceptedProposals;
|
|
76299
76743
|
const sourceInput = {
|
|
76300
76744
|
excerpt: args.sourceExcerpt,
|
|
@@ -76375,21 +76819,21 @@ var init_compile_intent = __esm(() => {
|
|
|
76375
76819
|
});
|
|
76376
76820
|
|
|
76377
76821
|
// ../cli/dist/operations/planning/apply-plan.js
|
|
76378
|
-
import { createHash as
|
|
76379
|
-
import
|
|
76822
|
+
import { createHash as createHash41, randomUUID as randomUUID6 } from "node:crypto";
|
|
76823
|
+
import path82 from "node:path";
|
|
76380
76824
|
function text8(value) {
|
|
76381
76825
|
return typeof value === "string" ? value.trim() : "";
|
|
76382
76826
|
}
|
|
76383
|
-
function
|
|
76827
|
+
function isRecord24(value) {
|
|
76384
76828
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
76385
76829
|
}
|
|
76386
76830
|
function digest4(value) {
|
|
76387
|
-
return
|
|
76831
|
+
return createHash41("sha256").update(value).digest("hex");
|
|
76388
76832
|
}
|
|
76389
76833
|
function relationships(step) {
|
|
76390
76834
|
if (!Array.isArray(step.relationships))
|
|
76391
76835
|
return [];
|
|
76392
|
-
return step.relationships.filter(
|
|
76836
|
+
return step.relationships.filter(isRecord24).map((relationship) => {
|
|
76393
76837
|
const type = text8(relationship.type);
|
|
76394
76838
|
const from = text8(relationship.from);
|
|
76395
76839
|
const to = text8(relationship.to);
|
|
@@ -76405,8 +76849,8 @@ function asUpsert(step) {
|
|
|
76405
76849
|
throw new Error(`Apply plan failed: unsupported step entity type '${type}'`);
|
|
76406
76850
|
if (!id)
|
|
76407
76851
|
throw new Error("Apply plan failed: every step needs an entity id");
|
|
76408
|
-
const properties =
|
|
76409
|
-
const document =
|
|
76852
|
+
const properties = isRecord24(step.properties) ? step.properties : {};
|
|
76853
|
+
const document = isRecord24(step.document) ? {
|
|
76410
76854
|
...typeof step.document.path === "string" ? { path: step.document.path } : {},
|
|
76411
76855
|
...typeof step.document.body === "string" ? { body: step.document.body } : {}
|
|
76412
76856
|
} : undefined;
|
|
@@ -76419,7 +76863,7 @@ function asUpsert(step) {
|
|
|
76419
76863
|
};
|
|
76420
76864
|
}
|
|
76421
76865
|
function validateCompilePlanShape(args) {
|
|
76422
|
-
if (!
|
|
76866
|
+
if (!isRecord24(args.plan))
|
|
76423
76867
|
throw new Error("Apply plan failed: plan must be an object");
|
|
76424
76868
|
if (args.plan.version !== "kibi.compile-plan.v1")
|
|
76425
76869
|
throw new Error("Apply plan failed: unsupported plan version");
|
|
@@ -76441,7 +76885,7 @@ function isBootstrapApplyArgs(args) {
|
|
|
76441
76885
|
return "plan" in args && args.plan.version === "kibi.bootstrap-plan.v1";
|
|
76442
76886
|
}
|
|
76443
76887
|
function assertSourceWriteStaysInWorkspace(root, absolute, writePath) {
|
|
76444
|
-
if (absolute !== root && !absolute.startsWith(`${root}${
|
|
76888
|
+
if (absolute !== root && !absolute.startsWith(`${root}${path82.sep}`)) {
|
|
76445
76889
|
throw new Error(`Apply plan failed: sourceWrites.path escapes workspace: ${writePath}`);
|
|
76446
76890
|
}
|
|
76447
76891
|
}
|
|
@@ -76459,7 +76903,7 @@ function orderBootstrapActions(actions, completed = new Set) {
|
|
|
76459
76903
|
for (const action of actions) {
|
|
76460
76904
|
if (!action.id || byId.has(action.id))
|
|
76461
76905
|
throw new Error("Bootstrap apply failed: action IDs must be unique");
|
|
76462
|
-
if (action.kind !== "upsert" || !
|
|
76906
|
+
if (action.kind !== "upsert" || !isRecord24(action.payload))
|
|
76463
76907
|
throw new Error(`Bootstrap apply failed: action '${action.id}' is invalid`);
|
|
76464
76908
|
byId.set(action.id, action);
|
|
76465
76909
|
}
|
|
@@ -76548,7 +76992,7 @@ function validateEntityDeletionPlan(args) {
|
|
|
76548
76992
|
throw new Error("Entity deletion apply failed: approvedPlanHash does not match planHash");
|
|
76549
76993
|
}
|
|
76550
76994
|
const { planHash: _ignored, ...body } = args.plan;
|
|
76551
|
-
if (
|
|
76995
|
+
if (createHash41("sha256").update(JSON.stringify(body)).digest("hex") !== args.plan.planHash) {
|
|
76552
76996
|
throw new Error("Entity deletion apply failed: planHash does not match the canonical plan body");
|
|
76553
76997
|
}
|
|
76554
76998
|
if (!Array.isArray(args.plan.entityIds) || args.plan.entityIds.length === 0) {
|
|
@@ -76559,7 +77003,7 @@ function validateEntityDeletionPlan(args) {
|
|
|
76559
77003
|
}
|
|
76560
77004
|
}
|
|
76561
77005
|
function validateMigrationPlanShape(args) {
|
|
76562
|
-
if (!
|
|
77006
|
+
if (!isRecord24(args.plan))
|
|
76563
77007
|
throw new Error("Migration apply failed: plan must be an object");
|
|
76564
77008
|
if (args.plan.version !== "kibi.migration-plan.v2")
|
|
76565
77009
|
throw new Error("Migration apply failed: unsupported plan version");
|
|
@@ -76621,13 +77065,13 @@ function topologicalActions(actions) {
|
|
|
76621
77065
|
async function validateSources(context, sourceHashes) {
|
|
76622
77066
|
let checked = 0;
|
|
76623
77067
|
for (const [relative, expected] of Object.entries(sourceHashes)) {
|
|
76624
|
-
if (!relative ||
|
|
77068
|
+
if (!relative || path82.isAbsolute(relative) || relative.split(/[\\/]/).includes(".."))
|
|
76625
77069
|
throw new Error("Apply plan failed: source hash paths must be workspace-relative");
|
|
76626
77070
|
if (!context.fs)
|
|
76627
77071
|
throw new Error("Apply plan failed: source hashes require a filesystem-capable runtime");
|
|
76628
77072
|
let actual;
|
|
76629
77073
|
try {
|
|
76630
|
-
actual = digest4(await context.fs.readFile(
|
|
77074
|
+
actual = digest4(await context.fs.readFile(path82.join(context.workspaceRoot, relative)));
|
|
76631
77075
|
} catch {
|
|
76632
77076
|
actual = null;
|
|
76633
77077
|
}
|
|
@@ -76638,19 +77082,19 @@ async function validateSources(context, sourceHashes) {
|
|
|
76638
77082
|
return checked;
|
|
76639
77083
|
}
|
|
76640
77084
|
async function resolveSourceWriteTarget(workspaceRoot, fsPort, write) {
|
|
76641
|
-
if (!write.path ||
|
|
77085
|
+
if (!write.path || path82.isAbsolute(write.path) || write.path.split(/[\\/]/).includes("..")) {
|
|
76642
77086
|
throw new Error(`Apply plan failed: sourceWrites.path must be workspace-relative: ${write.path}`);
|
|
76643
77087
|
}
|
|
76644
|
-
const absolute =
|
|
76645
|
-
const root =
|
|
77088
|
+
const absolute = path82.resolve(workspaceRoot, write.path);
|
|
77089
|
+
const root = path82.resolve(workspaceRoot);
|
|
76646
77090
|
assertSourceWriteStaysInWorkspace(root, absolute, write.path);
|
|
76647
|
-
const relative =
|
|
77091
|
+
const relative = path82.relative(root, absolute).split(path82.sep).join("/");
|
|
76648
77092
|
if (relative === ".kb" || isDerivedKbPath(relative)) {
|
|
76649
77093
|
throw new Error("Apply plan failed: sourceWrites.path cannot target Kibi's derived .kb runtime trees");
|
|
76650
77094
|
}
|
|
76651
77095
|
const realRoot = canonicalFilesystemPath(root);
|
|
76652
77096
|
const realExisting = canonicalFilesystemPath(absolute);
|
|
76653
|
-
if (realExisting !== realRoot && !realExisting.startsWith(`${realRoot}${
|
|
77097
|
+
if (realExisting !== realRoot && !realExisting.startsWith(`${realRoot}${path82.sep}`)) {
|
|
76654
77098
|
throw new Error(`Apply plan failed: sourceWrites.path follows a symlink outside the workspace: ${write.path}`);
|
|
76655
77099
|
}
|
|
76656
77100
|
const existing = await fsPort.readFile(absolute).catch(() => {
|
|
@@ -76681,7 +77125,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76681
77125
|
throw new Error("Apply plan failed: sourceWrites require a filesystem-capable runtime");
|
|
76682
77126
|
}
|
|
76683
77127
|
const fsPort = context.fs;
|
|
76684
|
-
const journalPath =
|
|
77128
|
+
const journalPath = path82.join(context.workspaceRoot, ".kb", "recovery", `source-writes-${planHash.slice(0, 16)}.json`);
|
|
76685
77129
|
const journalId = `source-writes-${planHash.slice(0, 16)}`;
|
|
76686
77130
|
const sameEntries = (entries) => entries.length === writes.length && entries.every((entry) => writes.some((write) => write.path === entry.path && (write.mode ?? "write") === entry.mode && write.beforeHash === entry.beforeHash && write.afterHash === entry.afterHash));
|
|
76687
77131
|
const readJournal = async () => {
|
|
@@ -76704,7 +77148,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76704
77148
|
let allAfter = true;
|
|
76705
77149
|
for (const entry of prior.entries) {
|
|
76706
77150
|
try {
|
|
76707
|
-
const current = await context.fs.readFile(
|
|
77151
|
+
const current = await context.fs.readFile(path82.resolve(context.workspaceRoot, entry.path));
|
|
76708
77152
|
if (entry.afterHash === null || digest4(current) !== entry.afterHash) {
|
|
76709
77153
|
allAfter = false;
|
|
76710
77154
|
}
|
|
@@ -76726,7 +77170,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76726
77170
|
}
|
|
76727
77171
|
if (prior && (prior.state === "prepared" || prior.state === "publishing_sources")) {
|
|
76728
77172
|
for (const entry of prior.entries) {
|
|
76729
|
-
const absolute =
|
|
77173
|
+
const absolute = path82.resolve(context.workspaceRoot, entry.path);
|
|
76730
77174
|
let current;
|
|
76731
77175
|
try {
|
|
76732
77176
|
current = await context.fs.readFile(absolute);
|
|
@@ -76759,7 +77203,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76759
77203
|
const { absolute, existing, mode } = await resolveSourceWriteTarget(context.workspaceRoot, fsPort, write);
|
|
76760
77204
|
originals.push({ absolute, body: existing });
|
|
76761
77205
|
paths.push(write.path);
|
|
76762
|
-
const stageBase =
|
|
77206
|
+
const stageBase = path82.join(context.workspaceRoot, ".kb", "recovery", `${journalId}-${entries.length}`);
|
|
76763
77207
|
entries.push({
|
|
76764
77208
|
path: write.path,
|
|
76765
77209
|
mode,
|
|
@@ -76770,7 +77214,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76770
77214
|
afterStage: `${stageBase}.after`
|
|
76771
77215
|
});
|
|
76772
77216
|
}
|
|
76773
|
-
await context.fs.mkdir(
|
|
77217
|
+
await context.fs.mkdir(path82.dirname(journalPath));
|
|
76774
77218
|
for (let index = 0;index < writes.length; index += 1) {
|
|
76775
77219
|
const original = originals[index];
|
|
76776
77220
|
const entry = entries[index];
|
|
@@ -76791,7 +77235,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76791
77235
|
const write = writes[index];
|
|
76792
77236
|
if (!absolute || !write)
|
|
76793
77237
|
continue;
|
|
76794
|
-
await context.fs.mkdir(
|
|
77238
|
+
await context.fs.mkdir(path82.dirname(absolute));
|
|
76795
77239
|
await context.fs.writeFile(journalPath, `${JSON.stringify({ version: 1, planHash, state: "publishing_sources", entries }, null, 2)}
|
|
76796
77240
|
`);
|
|
76797
77241
|
if ((write.mode ?? "write") === "delete") {
|
|
@@ -76843,7 +77287,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76843
77287
|
} catch {}
|
|
76844
77288
|
}
|
|
76845
77289
|
try {
|
|
76846
|
-
await context.fs.mkdir(
|
|
77290
|
+
await context.fs.mkdir(path82.dirname(journalPath));
|
|
76847
77291
|
await context.fs.writeFile(journalPath, `${JSON.stringify({ version: 1, planHash, state: "rolled_back", entries }, null, 2)}
|
|
76848
77292
|
`);
|
|
76849
77293
|
} catch {}
|
|
@@ -76860,7 +77304,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
|
|
|
76860
77304
|
async function markSourceJournal(context, journalId, state) {
|
|
76861
77305
|
if (!journalId || !context.fs)
|
|
76862
77306
|
return;
|
|
76863
|
-
const journalPath =
|
|
77307
|
+
const journalPath = path82.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
|
|
76864
77308
|
try {
|
|
76865
77309
|
const current = JSON.parse(await context.fs.readFile(journalPath));
|
|
76866
77310
|
await context.fs.writeFile(journalPath, `${JSON.stringify({ ...current, state }, null, 2)}
|
|
@@ -76875,7 +77319,7 @@ async function executeSourceRecovery(args, context, onCommitted = () => {
|
|
|
76875
77319
|
if (!/^[A-Za-z0-9._-]+$/.test(args.recoveryJournalId)) {
|
|
76876
77320
|
throw new Error("Source recovery journal ID is invalid");
|
|
76877
77321
|
}
|
|
76878
|
-
const journalPath =
|
|
77322
|
+
const journalPath = path82.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
|
|
76879
77323
|
const journal = JSON.parse(await context.fs.readFile(journalPath));
|
|
76880
77324
|
if (journal.version !== 1 || typeof journal.planHash !== "string" || !Array.isArray(journal.entries) || !["sources_committed", "compiled_published", "repair_required"].includes(journal.state ?? "")) {
|
|
76881
77325
|
throw new Error("Source recovery requires a committed or repair_required journal");
|
|
@@ -76952,7 +77396,7 @@ async function assertBootstrapPlanCurrent(args, operationContext) {
|
|
|
76952
77396
|
async function preflightApplyPlan(args, context) {
|
|
76953
77397
|
if (!("plan" in args))
|
|
76954
77398
|
return;
|
|
76955
|
-
if (!
|
|
77399
|
+
if (!isRecord24(args.plan))
|
|
76956
77400
|
throw new Error("Apply plan failed: plan must be an object");
|
|
76957
77401
|
if (typeof args.approvedPlanHash !== "string" || !/^[a-f0-9]{64}$/i.test(args.approvedPlanHash))
|
|
76958
77402
|
throw new Error("Apply plan failed: approvedPlanHash must be the SHA-256 planHash returned with the plan");
|
|
@@ -76991,7 +77435,7 @@ async function executeBootstrapPlan(args, context, recovery = false, remainingAc
|
|
|
76991
77435
|
if (!status)
|
|
76992
77436
|
throw new Error("Bootstrap apply failed: status returned no payload");
|
|
76993
77437
|
const journalId = `bootstrap-${args.plan.planHash.slice(0, 16)}`;
|
|
76994
|
-
const journalPath =
|
|
77438
|
+
const journalPath = path82.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
|
|
76995
77439
|
if (!recovery && context.fs) {
|
|
76996
77440
|
try {
|
|
76997
77441
|
await context.fs.readFile(journalPath);
|
|
@@ -77024,7 +77468,7 @@ async function executeBootstrapPlan(args, context, recovery = false, remainingAc
|
|
|
77024
77468
|
const writeJournal = async (state, activeActionId, currentCheckpoint = lastCheckpoint) => {
|
|
77025
77469
|
if (!context.fs)
|
|
77026
77470
|
return;
|
|
77027
|
-
await context.fs.mkdir(
|
|
77471
|
+
await context.fs.mkdir(path82.dirname(journalPath));
|
|
77028
77472
|
await context.fs.writeFile(journalPath, `${JSON.stringify({
|
|
77029
77473
|
version: 2,
|
|
77030
77474
|
kind: "bootstrap",
|
|
@@ -77294,7 +77738,7 @@ async function dispatchApplyPlan(args, context, onCommitted, recovered) {
|
|
|
77294
77738
|
throw new Error("Bootstrap recovery requires a filesystem-capable runtime");
|
|
77295
77739
|
if (!/^bootstrap-[a-f0-9]{16}$/.test(args.recoveryJournalId))
|
|
77296
77740
|
throw new Error("Bootstrap recovery journal ID is invalid");
|
|
77297
|
-
const journalPath =
|
|
77741
|
+
const journalPath = path82.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
|
|
77298
77742
|
const journal = JSON.parse(await context.fs.readFile(journalPath));
|
|
77299
77743
|
if (journal.version !== 2 || journal.kind !== "bootstrap" || !journal.plan)
|
|
77300
77744
|
throw new Error("Bootstrap recovery journal is invalid");
|
|
@@ -77478,7 +77922,7 @@ async function planFileWrites(context, prolog, fsPort, sourceWrites, steps, now)
|
|
|
77478
77922
|
const relative = canonicalSourcePath(context, step.input, step.entity, existing);
|
|
77479
77923
|
let file = files.get(relative);
|
|
77480
77924
|
if (file === undefined) {
|
|
77481
|
-
const existingBytes = await fsPort.readFile(
|
|
77925
|
+
const existingBytes = await fsPort.readFile(path82.join(workspaceRoot, relative)).catch(() => {
|
|
77482
77926
|
return;
|
|
77483
77927
|
});
|
|
77484
77928
|
const before = existingBytes ?? null;
|
|
@@ -77503,8 +77947,8 @@ async function planFileWrites(context, prolog, fsPort, sourceWrites, steps, now)
|
|
|
77503
77947
|
file.after = after;
|
|
77504
77948
|
file.afterHash = contentHash(after);
|
|
77505
77949
|
}
|
|
77506
|
-
const root =
|
|
77507
|
-
const kbRoot =
|
|
77950
|
+
const root = path82.resolve(workspaceRoot);
|
|
77951
|
+
const kbRoot = path82.join(workspaceRoot, ".kb");
|
|
77508
77952
|
const createdAt = now.toISOString();
|
|
77509
77953
|
for (const step of steps) {
|
|
77510
77954
|
for (const relationship of step.relationships) {
|
|
@@ -77515,7 +77959,7 @@ async function planFileWrites(context, prolog, fsPort, sourceWrites, steps, now)
|
|
|
77515
77959
|
continue;
|
|
77516
77960
|
const shardPath = computeShardPath(kbRoot, from);
|
|
77517
77961
|
assertRelationshipShardContained(workspaceRoot, shardPath);
|
|
77518
|
-
const relative =
|
|
77962
|
+
const relative = path82.relative(root, path82.resolve(shardPath)).split(path82.sep).join("/");
|
|
77519
77963
|
let file = files.get(relative);
|
|
77520
77964
|
if (file === undefined) {
|
|
77521
77965
|
const existing = await fsPort.readFile(shardPath).catch(() => null);
|
|
@@ -77967,7 +78411,7 @@ function withRecoveryReport(result, recovered) {
|
|
|
77967
78411
|
action: recovery.action,
|
|
77968
78412
|
restoredPaths: recovery.restoredPaths
|
|
77969
78413
|
}));
|
|
77970
|
-
if (
|
|
78414
|
+
if (isRecord24(structured.validationSummary)) {
|
|
77971
78415
|
const summary = structured.validationSummary;
|
|
77972
78416
|
return {
|
|
77973
78417
|
content,
|
|
@@ -78000,7 +78444,7 @@ async function applyingBootstrapJournal(args, context) {
|
|
|
78000
78444
|
return;
|
|
78001
78445
|
if (!/^bootstrap-[a-f0-9]{16}$/.test(args.recoveryJournalId))
|
|
78002
78446
|
return;
|
|
78003
|
-
const journalPath =
|
|
78447
|
+
const journalPath = path82.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
|
|
78004
78448
|
try {
|
|
78005
78449
|
const journal = JSON.parse(await context.fs.readFile(journalPath));
|
|
78006
78450
|
return journal.kind === "bootstrap" && journal.state === "applying" ? journalPath : undefined;
|
|
@@ -78214,6 +78658,14 @@ async function applyMigrationAction(action, context) {
|
|
|
78214
78658
|
case "missing_exact_branch_store":
|
|
78215
78659
|
await branchEnsureCommand({ workspaceRoot: context.workspaceRoot });
|
|
78216
78660
|
return;
|
|
78661
|
+
case BRANCH_STORE_NOT_COMPILED: {
|
|
78662
|
+
const result = await syncCommand({
|
|
78663
|
+
workspaceRoot: context.workspaceRoot
|
|
78664
|
+
});
|
|
78665
|
+
if (!result.success)
|
|
78666
|
+
throw new Error("Compiling the branch store (kibi sync) did not complete successfully.");
|
|
78667
|
+
return;
|
|
78668
|
+
}
|
|
78217
78669
|
case "damaged_exact_branch_store":
|
|
78218
78670
|
await branchRecoverCommand({
|
|
78219
78671
|
apply: true,
|
|
@@ -78243,6 +78695,9 @@ async function applyMigrationAction(action, context) {
|
|
|
78243
78695
|
case PREDICATE_SCHEMA_ALIGNMENT_CODE:
|
|
78244
78696
|
await applyPredicateSchemaAlignment(action, context);
|
|
78245
78697
|
return;
|
|
78698
|
+
case PROOF_INTEGRATION_CONFIGURE:
|
|
78699
|
+
applyProofIntegrationAction(action, context.workspaceRoot);
|
|
78700
|
+
return;
|
|
78246
78701
|
default:
|
|
78247
78702
|
if (SCHEMA6_AUTOMATIC_CODES.has(action.code)) {
|
|
78248
78703
|
await applySchema6MigrationAction(action, context);
|
|
@@ -78267,7 +78722,7 @@ async function applyPredicateSchemaAlignment(action, context) {
|
|
|
78267
78722
|
const currentNamespace = typeof current?.predicate_namespace === "string" && current.predicate_namespace !== "" ? current.predicate_namespace : "default";
|
|
78268
78723
|
const currentArgs = Array.isArray(current?.predicate_args) ? current.predicate_args : [];
|
|
78269
78724
|
const rewrites = Array.isArray(evidence.rewrites) ? evidence.rewrites : [];
|
|
78270
|
-
const unchanged = current !== undefined && current.fact_kind === "predicate" && currentNamespace === evidence.namespace && rewrites.every((rewrite) =>
|
|
78725
|
+
const unchanged = current !== undefined && current.fact_kind === "predicate" && currentNamespace === evidence.namespace && rewrites.every((rewrite) => isRecord24(rewrite) && typeof rewrite.index === "number" && currentArgs[rewrite.index] === rewrite.from);
|
|
78271
78726
|
if (!unchanged)
|
|
78272
78727
|
throw new Error(`Predicate fact ${input.id} changed since planning; rerun kibi check and approve the new plan.`);
|
|
78273
78728
|
await executeUpsert(input, operationContext);
|
|
@@ -78278,11 +78733,13 @@ var init_apply_plan = __esm(() => {
|
|
|
78278
78733
|
init_branch();
|
|
78279
78734
|
init_migrate();
|
|
78280
78735
|
init_sync();
|
|
78736
|
+
init_integration_plan();
|
|
78281
78737
|
init_discovery_entities();
|
|
78282
78738
|
init_discovery_executors();
|
|
78283
78739
|
init_migration_plan();
|
|
78284
78740
|
init_migration_plan();
|
|
78285
78741
|
init_shards();
|
|
78742
|
+
init_branch_store();
|
|
78286
78743
|
init_canonical_path();
|
|
78287
78744
|
init_kb_paths();
|
|
78288
78745
|
init_types();
|
|
@@ -78719,113 +79176,6 @@ function evaluateContractAgainstRun(artifact, contract) {
|
|
|
78719
79176
|
}
|
|
78720
79177
|
var MAX_ATTRIBUTED_MEMBERS = 5;
|
|
78721
79178
|
|
|
78722
|
-
// ../cli/dist/proof/integrations.js
|
|
78723
|
-
import { existsSync as existsSync41, readFileSync as readFileSync48 } from "node:fs";
|
|
78724
|
-
import path81 from "node:path";
|
|
78725
|
-
function integrationsPath(workspaceRoot) {
|
|
78726
|
-
return path81.join(workspaceRoot, PROOF_INTEGRATIONS_PATH);
|
|
78727
|
-
}
|
|
78728
|
-
function proofIntegrationErrors(value) {
|
|
78729
|
-
const file = record5(value);
|
|
78730
|
-
if (!file)
|
|
78731
|
-
return [
|
|
78732
|
-
`${PROOF_INTEGRATIONS_PATH} must be an object with version and integrations`
|
|
78733
|
-
];
|
|
78734
|
-
const errors = [];
|
|
78735
|
-
if (file.version !== PROOF_INTEGRATION_VERSION)
|
|
78736
|
-
errors.push(`version must be ${PROOF_INTEGRATION_VERSION}; received ${JSON.stringify(file.version ?? null)}`);
|
|
78737
|
-
if (!Array.isArray(file.integrations) || file.integrations.length === 0) {
|
|
78738
|
-
errors.push("integrations must be a non-empty array");
|
|
78739
|
-
return errors;
|
|
78740
|
-
}
|
|
78741
|
-
const seen = new Set;
|
|
78742
|
-
file.integrations.forEach((entry, index) => {
|
|
78743
|
-
const row = record5(entry);
|
|
78744
|
-
const label = `integrations[${index}]`;
|
|
78745
|
-
if (!row) {
|
|
78746
|
-
errors.push(`${label} must be an object`);
|
|
78747
|
-
return;
|
|
78748
|
-
}
|
|
78749
|
-
if (!nonEmpty(row.id))
|
|
78750
|
-
errors.push(`${label}.id must be a non-empty string`);
|
|
78751
|
-
else {
|
|
78752
|
-
if (seen.has(String(row.id)))
|
|
78753
|
-
errors.push(`${label}.id duplicates '${String(row.id)}'`);
|
|
78754
|
-
seen.add(String(row.id));
|
|
78755
|
-
}
|
|
78756
|
-
if (!nonEmpty(row.producer))
|
|
78757
|
-
errors.push(`${label}.producer must be one of: ${PRODUCER_KINDS.join(", ")} (or a custom producer id)`);
|
|
78758
|
-
if (!Array.isArray(row.command) || row.command.length === 0 || !row.command.every((argument) => nonEmpty(argument)))
|
|
78759
|
-
errors.push(`${label}.command must be a non-empty argv array`);
|
|
78760
|
-
if (nonEmpty(row.producer) && (row.producer === "junit" || row.producer === "tap") && !nonEmpty(row.artifact))
|
|
78761
|
-
errors.push(`${label}.artifact is required for producer '${String(row.producer)}' (path of the native report to convert)`);
|
|
78762
|
-
if (row.targets !== undefined) {
|
|
78763
|
-
if (!Array.isArray(row.targets) || row.targets.length === 0 || !row.targets.every((target) => nonEmpty(target)))
|
|
78764
|
-
errors.push(`${label}.targets must be a non-empty array of target names`);
|
|
78765
|
-
}
|
|
78766
|
-
if (row.options !== undefined && !record5(row.options))
|
|
78767
|
-
errors.push(`${label}.options must be an object when present`);
|
|
78768
|
-
if (row.description !== undefined && !nonEmpty(row.description))
|
|
78769
|
-
errors.push(`${label}.description must be a non-empty string when present`);
|
|
78770
|
-
});
|
|
78771
|
-
return errors;
|
|
78772
|
-
}
|
|
78773
|
-
function loadProofIntegrations(workspaceRoot) {
|
|
78774
|
-
const filePath = integrationsPath(workspaceRoot);
|
|
78775
|
-
if (!existsSync41(filePath)) {
|
|
78776
|
-
return {
|
|
78777
|
-
available: false,
|
|
78778
|
-
error: `No proof integration configuration at ${PROOF_INTEGRATIONS_PATH}. Run bootstrap for this repository to configure proof producers.`
|
|
78779
|
-
};
|
|
78780
|
-
}
|
|
78781
|
-
let parsed;
|
|
78782
|
-
try {
|
|
78783
|
-
parsed = JSON.parse(readFileSync48(filePath, "utf8"));
|
|
78784
|
-
} catch (error) {
|
|
78785
|
-
return {
|
|
78786
|
-
available: false,
|
|
78787
|
-
error: `${PROOF_INTEGRATIONS_PATH} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
78788
|
-
};
|
|
78789
|
-
}
|
|
78790
|
-
const errors = proofIntegrationErrors(parsed);
|
|
78791
|
-
if (errors.length > 0)
|
|
78792
|
-
return {
|
|
78793
|
-
available: false,
|
|
78794
|
-
error: `Invalid ${PROOF_INTEGRATIONS_PATH}: ${errors.join("; ")}`
|
|
78795
|
-
};
|
|
78796
|
-
return { available: true, integrations: parsed };
|
|
78797
|
-
}
|
|
78798
|
-
function resolveIntegration(integrations, id) {
|
|
78799
|
-
return integrations.integrations.find((entry) => entry.id === id) ?? null;
|
|
78800
|
-
}
|
|
78801
|
-
function toExecution(integration) {
|
|
78802
|
-
return {
|
|
78803
|
-
id: integration.id,
|
|
78804
|
-
producer: integration.producer,
|
|
78805
|
-
...integration.producer_version !== undefined ? { producer_version: integration.producer_version } : {},
|
|
78806
|
-
command: integration.command,
|
|
78807
|
-
...integration.artifact !== undefined ? { artifact: integration.artifact } : {},
|
|
78808
|
-
...integration.targets !== undefined ? { targets: integration.targets } : {},
|
|
78809
|
-
...integration.options !== undefined ? { options: integration.options } : {}
|
|
78810
|
-
};
|
|
78811
|
-
}
|
|
78812
|
-
function record5(value) {
|
|
78813
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
78814
|
-
}
|
|
78815
|
-
function nonEmpty(value) {
|
|
78816
|
-
return typeof value === "string" && value.trim().length > 0;
|
|
78817
|
-
}
|
|
78818
|
-
var PROOF_INTEGRATIONS_PATH = ".kb/proof/integrations.json", PRODUCER_KINDS;
|
|
78819
|
-
var init_integrations = __esm(() => {
|
|
78820
|
-
init_proof_protocol();
|
|
78821
|
-
PRODUCER_KINDS = [
|
|
78822
|
-
"command",
|
|
78823
|
-
"playwright",
|
|
78824
|
-
"junit",
|
|
78825
|
-
"tap"
|
|
78826
|
-
];
|
|
78827
|
-
});
|
|
78828
|
-
|
|
78829
79179
|
// ../cli/dist/operations/mutation/entity-projection.js
|
|
78830
79180
|
function projectEntityProperties(entity) {
|
|
78831
79181
|
const relationshipKeys = new Set(RELATIONSHIP_TYPES2);
|
|
@@ -79324,11 +79674,11 @@ function validateInput(input) {
|
|
|
79324
79674
|
}
|
|
79325
79675
|
return endpoint;
|
|
79326
79676
|
}
|
|
79327
|
-
function
|
|
79677
|
+
function isRecord25(value) {
|
|
79328
79678
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
79329
79679
|
}
|
|
79330
79680
|
function decodeRows(payload) {
|
|
79331
|
-
if (!
|
|
79681
|
+
if (!isRecord25(payload) || !isRecord25(payload.results)) {
|
|
79332
79682
|
throw new Error("SPARQL endpoint returned an invalid result document");
|
|
79333
79683
|
}
|
|
79334
79684
|
const bindings = payload.results.bindings;
|
|
@@ -79336,12 +79686,12 @@ function decodeRows(payload) {
|
|
|
79336
79686
|
throw new Error("SPARQL endpoint returned an invalid bindings array");
|
|
79337
79687
|
}
|
|
79338
79688
|
const rows = bindings.map((binding) => {
|
|
79339
|
-
if (!
|
|
79689
|
+
if (!isRecord25(binding)) {
|
|
79340
79690
|
throw new Error("SPARQL endpoint returned an invalid binding");
|
|
79341
79691
|
}
|
|
79342
79692
|
const row = {};
|
|
79343
79693
|
for (const [variable, term] of Object.entries(binding)) {
|
|
79344
|
-
if (!
|
|
79694
|
+
if (!isRecord25(term) || typeof term.value !== "string") {
|
|
79345
79695
|
throw new Error(`SPARQL endpoint returned an invalid ${variable} term`);
|
|
79346
79696
|
}
|
|
79347
79697
|
row[variable] = term.value;
|
|
@@ -79625,10 +79975,10 @@ init_generate();
|
|
|
79625
79975
|
init_presentation();
|
|
79626
79976
|
init_ir();
|
|
79627
79977
|
// src/skill-operations.ts
|
|
79628
|
-
import { createHash as
|
|
79978
|
+
import { createHash as createHash42 } from "node:crypto";
|
|
79629
79979
|
|
|
79630
79980
|
// src/skill-system/loader.ts
|
|
79631
|
-
import { existsSync as
|
|
79981
|
+
import { existsSync as existsSync45, readFileSync as readFileSync51, readdirSync as readdirSync14, realpathSync as realpathSync10 } from "node:fs";
|
|
79632
79982
|
import { dirname as dirname22, join as join34, resolve as resolve29 } from "node:path";
|
|
79633
79983
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
79634
79984
|
|
|
@@ -79675,7 +80025,7 @@ class SkillOversizeError2 extends Error {
|
|
|
79675
80025
|
}
|
|
79676
80026
|
|
|
79677
80027
|
// src/skill-system/paths.ts
|
|
79678
|
-
import { existsSync as
|
|
80028
|
+
import { existsSync as existsSync43, statSync as statSync13 } from "node:fs";
|
|
79679
80029
|
import { isAbsolute as isAbsolute19, join as join33, normalize as normalize3, relative as relative20, resolve as resolve27 } from "node:path";
|
|
79680
80030
|
var SKILL_FILE_NAME2 = "SKILL.md";
|
|
79681
80031
|
function normalizeResourcePath2(pathLike) {
|
|
@@ -79691,7 +80041,7 @@ function isWithinRoot3(rootDir, candidatePath) {
|
|
|
79691
80041
|
}
|
|
79692
80042
|
function resolveSkillFilePath2(pathLike) {
|
|
79693
80043
|
const resolved = resolve27(pathLike);
|
|
79694
|
-
if (
|
|
80044
|
+
if (existsSync43(resolved) && statSync13(resolved).isDirectory())
|
|
79695
80045
|
return join33(resolved, SKILL_FILE_NAME2);
|
|
79696
80046
|
return resolved.endsWith(SKILL_FILE_NAME2) ? resolved : join33(resolved, SKILL_FILE_NAME2);
|
|
79697
80047
|
}
|
|
@@ -79816,7 +80166,7 @@ function isStringArray2(value) {
|
|
|
79816
80166
|
var moduleDir = dirname22(fileURLToPath5(import.meta.url));
|
|
79817
80167
|
var overrideSkillsDir;
|
|
79818
80168
|
function defaultBundledSkillsDir2() {
|
|
79819
|
-
return
|
|
80169
|
+
return existsSync45(resolve29(moduleDir, "skills")) ? resolve29(moduleDir, "skills") : resolve29(moduleDir, "../skills");
|
|
79820
80170
|
}
|
|
79821
80171
|
function setBundledSkillsDir2(dir) {
|
|
79822
80172
|
overrideSkillsDir = dir;
|
|
@@ -79846,17 +80196,17 @@ function readBundledSkillResourceFrom2(skillsDir, id, resourcePath) {
|
|
|
79846
80196
|
return readBundle2(loadBundledSkillFrom2(skillsDir, id), id, resourcePath);
|
|
79847
80197
|
}
|
|
79848
80198
|
function listFrom2(dir) {
|
|
79849
|
-
if (!
|
|
80199
|
+
if (!existsSync45(dir))
|
|
79850
80200
|
return [];
|
|
79851
|
-
return
|
|
80201
|
+
return readdirSync14(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join34(dir, entry.name)).filter((root) => existsSync45(join34(root, SKILL_FILE_NAME2))).map((root) => parseSkillBundle2(root).manifest).sort((a, b) => a.id.localeCompare(b.id));
|
|
79852
80202
|
}
|
|
79853
80203
|
function findRoot2(dir, id) {
|
|
79854
80204
|
return listRoots2(dir).find((root) => parseSkillBundle2(root).manifest.id === id);
|
|
79855
80205
|
}
|
|
79856
80206
|
function listRoots2(dir) {
|
|
79857
|
-
if (!
|
|
80207
|
+
if (!existsSync45(dir))
|
|
79858
80208
|
return [];
|
|
79859
|
-
return
|
|
80209
|
+
return readdirSync14(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join34(dir, entry.name)).filter((root) => existsSync45(join34(root, SKILL_FILE_NAME2)));
|
|
79860
80210
|
}
|
|
79861
80211
|
function readBundle2(bundle, id, resourcePath) {
|
|
79862
80212
|
const resource = normalizeResourcePath2(resourcePath);
|
|
@@ -79874,7 +80224,7 @@ function readBundle2(bundle, id, resourcePath) {
|
|
|
79874
80224
|
throw new SkillResourceNotFoundError2(id, resourcePath);
|
|
79875
80225
|
}
|
|
79876
80226
|
assertMaxBytes2(candidate, RESOURCE_MAX_BYTES2);
|
|
79877
|
-
return
|
|
80227
|
+
return readFileSync51(candidate, "utf8");
|
|
79878
80228
|
}
|
|
79879
80229
|
// src/skill-operations.ts
|
|
79880
80230
|
function assertNonEmptyString2(value, field) {
|
|
@@ -79897,7 +80247,7 @@ async function executeSkillsLoad2(input, _context) {
|
|
|
79897
80247
|
assertNonEmptyString2(id, "id");
|
|
79898
80248
|
const bundle = loadBundledSkill2(id);
|
|
79899
80249
|
const resources = bundle.manifest.resources ?? [];
|
|
79900
|
-
const contentHash =
|
|
80250
|
+
const contentHash = createHash42("sha256").update(bundle.body, "utf8").digest("hex");
|
|
79901
80251
|
const resourceList = resources.length === 0 ? "none" : resources.join(", ");
|
|
79902
80252
|
return {
|
|
79903
80253
|
content: [
|
|
@@ -80031,7 +80381,7 @@ init_symbols_coordinator2();
|
|
|
80031
80381
|
// ../cli/dist/env/bootstrap.js
|
|
80032
80382
|
import fs13 from "node:fs";
|
|
80033
80383
|
import os2 from "node:os";
|
|
80034
|
-
import
|
|
80384
|
+
import path83 from "node:path";
|
|
80035
80385
|
var WORKSPACE_ENV_KEYS = [
|
|
80036
80386
|
"KIBI_WORKSPACE",
|
|
80037
80387
|
"KIBI_PROJECT_ROOT",
|
|
@@ -80057,13 +80407,13 @@ function readFirstEnv(env, keys) {
|
|
|
80057
80407
|
return null;
|
|
80058
80408
|
}
|
|
80059
80409
|
function nextAncestorDirectory2(current) {
|
|
80060
|
-
const parent =
|
|
80410
|
+
const parent = path83.dirname(current);
|
|
80061
80411
|
return parent === current ? undefined : parent;
|
|
80062
80412
|
}
|
|
80063
80413
|
function findUpwards(startDir, marker) {
|
|
80064
|
-
let current =
|
|
80414
|
+
let current = path83.resolve(startDir);
|
|
80065
80415
|
while (current !== undefined) {
|
|
80066
|
-
if (fs13.existsSync(
|
|
80416
|
+
if (fs13.existsSync(path83.join(current, marker))) {
|
|
80067
80417
|
return current;
|
|
80068
80418
|
}
|
|
80069
80419
|
current = nextAncestorDirectory2(current);
|
|
@@ -80073,24 +80423,24 @@ function findUpwards(startDir, marker) {
|
|
|
80073
80423
|
function resolveKibiWorkspaceRoot(startDir = process.cwd(), env = process.env) {
|
|
80074
80424
|
const envRoot = readFirstEnv(env, WORKSPACE_ENV_KEYS);
|
|
80075
80425
|
if (envRoot)
|
|
80076
|
-
return
|
|
80426
|
+
return path83.resolve(envRoot);
|
|
80077
80427
|
const kbRoot = findUpwards(startDir, ".kb");
|
|
80078
80428
|
if (kbRoot)
|
|
80079
80429
|
return kbRoot;
|
|
80080
80430
|
const gitRoot = findUpwards(startDir, ".git");
|
|
80081
80431
|
if (gitRoot)
|
|
80082
80432
|
return gitRoot;
|
|
80083
|
-
return
|
|
80433
|
+
return path83.resolve(startDir);
|
|
80084
80434
|
}
|
|
80085
80435
|
function resolveEnvFilePath(envFileName, workspaceRoot) {
|
|
80086
|
-
if (
|
|
80436
|
+
if (path83.isAbsolute(envFileName))
|
|
80087
80437
|
return envFileName;
|
|
80088
|
-
return
|
|
80438
|
+
return path83.resolve(workspaceRoot, envFileName);
|
|
80089
80439
|
}
|
|
80090
80440
|
function resolveKibiUserEnvPath(options2 = {}) {
|
|
80091
80441
|
const env = options2.env ?? process.env;
|
|
80092
|
-
const xdg = options2.xdgConfigHome?.trim() || env.XDG_CONFIG_HOME?.trim() ||
|
|
80093
|
-
return
|
|
80442
|
+
const xdg = options2.xdgConfigHome?.trim() || env.XDG_CONFIG_HOME?.trim() || path83.join(options2.homedir ?? os2.homedir(), ".config");
|
|
80443
|
+
return path83.join(xdg, "kibi", "env");
|
|
80094
80444
|
}
|
|
80095
80445
|
function resolveKibiProjectEnvPath(workspaceRoot, env = process.env) {
|
|
80096
80446
|
const override = env.KIBI_ENV_FILE?.trim();
|