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.15.0";
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 ${payload.syncState} (snapshot ${payload.snapshotId}, dirty=${payload.dirty}, proofSnapshot=${enrichedPayload.proofSnapshot})`
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 ids = buildStableRequirementIds(input.claim);
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: { ...writeSet.subjectFact.properties, id: existingFactId }
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 readdirSync5, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
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 = readdirSync5(directory, { withFileTypes: true, encoding: "utf8" });
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 readdirSync6, unlinkSync as unlinkSync4 } from "node:fs";
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 readdirSync6(root)) {
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 readdirSync6(pendingRoot)) {
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 subjectKey = constrainedSubjects.length === 0 ? null : subjectArgument >= 0 ? predicateArgs[subjectArgument] ?? null : reviewedSubject ?? null;
57032
- const subjectPairing = constrainedSubjects.length === 0 ? "not_required" : subjectKey !== null && constrainedSubjects.includes(subjectKey) ? "paired" : "unpaired";
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 existing requirement ID to receive the requires_rule relationship."
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 readdirSync7, realpathSync as realpathSync8 } from "node:fs";
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 readdirSync7(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));
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 readdirSync7(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join20(dir, entry.name)).filter((root) => existsSync25(join20(root, SKILL_FILE_NAME)));
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
- structuredContent: { [selector]: choice, ...payload }
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 readdirSync8, renameSync as renameSync5, statSync as statSync10, unlinkSync as unlinkSync5, writeSync as writeSync2 } from "node:fs";
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 = readdirSync8(path53.dirname(absolute));
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 = readdirSync8(directory);
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 readdirSync9, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
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 readdirSync9(pendingRoot)) {
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 readdirSync9(relationshipsDir).filter((file) => file.endsWith(".yaml") || file.endsWith(".yml")).map((file) => path66.join(relationshipsDir, file)).filter((file) => {
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 readdirSync11, renameSync as renameSync12, rmSync as rmSync5, statSync as statSync12, writeFileSync as writeFileSync18 } from "node:fs";
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() && readdirSync11(dir).length === 0) {
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 readdirSync11(pendingRoot)) {
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 readdirSync12 } from "node:fs";
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 = readdirSync12(dirAbs, { withFileTypes: true });
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/operations/planning/compile-intent.js
75636
- import { createHash as createHash39 } from "node:crypto";
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 createHash39("sha256").update(canonicalize(value)).digest("hex");
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) || path79.isAbsolute(location.path) || location.path.split(/[\\/]/).includes("..")) {
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(isRecord22))
76148
+ relationships: mergeRelationships(step.relationships.filter(isRecord23))
75705
76149
  } : {}
75706
76150
  });
75707
76151
  continue;
75708
76152
  }
75709
76153
  const properties = {
75710
- ...isRecord22(previous.properties) ? previous.properties : {},
75711
- ...isRecord22(step.properties) ? step.properties : {}
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(isRecord22) : [],
75715
- ...Array.isArray(step.relationships) ? step.relationships.filter(isRecord22) : []
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 isRecord22(value) {
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 = isRecord22(step.properties) ? step.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 sourceHashes(context, locations) {
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(path79.join(context.workspaceRoot, relative)) : null;
75793
- hashes[relative] = contents === null ? null : createHash39("sha256").update(contents).digest("hex");
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 = isRecord22(step.properties) ? step.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 = isRecord22(step.document) ? step.document : {};
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(isRecord22) : [],
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(path79.join(context.workspaceRoot, source));
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(isRecord22) : []).map((relationship) => ({
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 = isRecord22(step.properties) ? step.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(isRecord22) : []).map(whatIfWitness);
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 (!isRecord22(parsed))
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(isRecord22) : [],
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 sourceHashes(context, args.sourceLocations);
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 createHash40, randomUUID as randomUUID6 } from "node:crypto";
76379
- import path80 from "node:path";
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 isRecord23(value) {
76827
+ function isRecord24(value) {
76384
76828
  return value !== null && typeof value === "object" && !Array.isArray(value);
76385
76829
  }
76386
76830
  function digest4(value) {
76387
- return createHash40("sha256").update(value).digest("hex");
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(isRecord23).map((relationship) => {
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 = isRecord23(step.properties) ? step.properties : {};
76409
- const document = isRecord23(step.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 (!isRecord23(args.plan))
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}${path80.sep}`)) {
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" || !isRecord23(action.payload))
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 (createHash40("sha256").update(JSON.stringify(body)).digest("hex") !== args.plan.planHash) {
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 (!isRecord23(args.plan))
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 || path80.isAbsolute(relative) || relative.split(/[\\/]/).includes(".."))
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(path80.join(context.workspaceRoot, relative)));
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 || path80.isAbsolute(write.path) || write.path.split(/[\\/]/).includes("..")) {
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 = path80.resolve(workspaceRoot, write.path);
76645
- const root = path80.resolve(workspaceRoot);
77088
+ const absolute = path82.resolve(workspaceRoot, write.path);
77089
+ const root = path82.resolve(workspaceRoot);
76646
77090
  assertSourceWriteStaysInWorkspace(root, absolute, write.path);
76647
- const relative = path80.relative(root, absolute).split(path80.sep).join("/");
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}${path80.sep}`)) {
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 = path80.join(context.workspaceRoot, ".kb", "recovery", `source-writes-${planHash.slice(0, 16)}.json`);
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(path80.resolve(context.workspaceRoot, entry.path));
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 = path80.resolve(context.workspaceRoot, entry.path);
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 = path80.join(context.workspaceRoot, ".kb", "recovery", `${journalId}-${entries.length}`);
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(path80.dirname(journalPath));
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(path80.dirname(absolute));
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(path80.dirname(journalPath));
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 = path80.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
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 = path80.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
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 (!isRecord23(args.plan))
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 = path80.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
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(path80.dirname(journalPath));
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 = path80.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
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(path80.join(workspaceRoot, relative)).catch(() => {
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 = path80.resolve(workspaceRoot);
77507
- const kbRoot = path80.join(workspaceRoot, ".kb");
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 = path80.relative(root, path80.resolve(shardPath)).split(path80.sep).join("/");
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 (isRecord23(structured.validationSummary)) {
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 = path80.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
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) => isRecord23(rewrite) && typeof rewrite.index === "number" && currentArgs[rewrite.index] === rewrite.from);
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 isRecord24(value) {
79677
+ function isRecord25(value) {
79328
79678
  return value !== null && typeof value === "object" && !Array.isArray(value);
79329
79679
  }
79330
79680
  function decodeRows(payload) {
79331
- if (!isRecord24(payload) || !isRecord24(payload.results)) {
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 (!isRecord24(binding)) {
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 (!isRecord24(term) || typeof term.value !== "string") {
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 createHash41 } from "node:crypto";
79978
+ import { createHash as createHash42 } from "node:crypto";
79629
79979
 
79630
79980
  // src/skill-system/loader.ts
79631
- import { existsSync as existsSync44, readFileSync as readFileSync50, readdirSync as readdirSync13, realpathSync as realpathSync10 } from "node:fs";
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 existsSync42, statSync as statSync13 } from "node:fs";
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 (existsSync42(resolved) && statSync13(resolved).isDirectory())
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 existsSync44(resolve29(moduleDir, "skills")) ? resolve29(moduleDir, "skills") : resolve29(moduleDir, "../skills");
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 (!existsSync44(dir))
80199
+ if (!existsSync45(dir))
79850
80200
  return [];
79851
- return readdirSync13(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join34(dir, entry.name)).filter((root) => existsSync44(join34(root, SKILL_FILE_NAME2))).map((root) => parseSkillBundle2(root).manifest).sort((a, b) => a.id.localeCompare(b.id));
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 (!existsSync44(dir))
80207
+ if (!existsSync45(dir))
79858
80208
  return [];
79859
- return readdirSync13(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join34(dir, entry.name)).filter((root) => existsSync44(join34(root, SKILL_FILE_NAME2)));
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 readFileSync50(candidate, "utf8");
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 = createHash41("sha256").update(bundle.body, "utf8").digest("hex");
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 path82 from "node:path";
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 = path82.dirname(current);
80410
+ const parent = path83.dirname(current);
80061
80411
  return parent === current ? undefined : parent;
80062
80412
  }
80063
80413
  function findUpwards(startDir, marker) {
80064
- let current = path82.resolve(startDir);
80414
+ let current = path83.resolve(startDir);
80065
80415
  while (current !== undefined) {
80066
- if (fs13.existsSync(path82.join(current, marker))) {
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 path82.resolve(envRoot);
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 path82.resolve(startDir);
80433
+ return path83.resolve(startDir);
80084
80434
  }
80085
80435
  function resolveEnvFilePath(envFileName, workspaceRoot) {
80086
- if (path82.isAbsolute(envFileName))
80436
+ if (path83.isAbsolute(envFileName))
80087
80437
  return envFileName;
80088
- return path82.resolve(workspaceRoot, envFileName);
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() || path82.join(options2.homedir ?? os2.homedir(), ".config");
80093
- return path82.join(xdg, "kibi", "env");
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();