kibi-cli 2.20.0 → 2.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/commands/migrate.d.ts +2 -0
  2. package/dist/commands/migrate.d.ts.map +1 -1
  3. package/dist/commands/migrate.js +32 -6
  4. package/dist/commands/sync/discovery.d.ts.map +1 -1
  5. package/dist/commands/sync/discovery.js +14 -2
  6. package/dist/extractors/markdown.d.ts.map +1 -1
  7. package/dist/extractors/markdown.js +2 -1
  8. package/dist/operations/migration/kb-sources.d.ts +5 -1
  9. package/dist/operations/migration/kb-sources.d.ts.map +1 -1
  10. package/dist/operations/migration/kb-sources.js +28 -1
  11. package/dist/operations/mutation/source-authoring.d.ts +8 -0
  12. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  13. package/dist/operations/mutation/source-authoring.js +33 -0
  14. package/dist/operations/mutation/validation.d.ts.map +1 -1
  15. package/dist/operations/mutation/validation.js +2 -1
  16. package/dist/operations/semantic-advisor/clauses.d.ts +9 -0
  17. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  18. package/dist/operations/semantic-advisor/clauses.js +24 -0
  19. package/dist/public/operations/catalog.d.ts +2 -2
  20. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  21. package/dist/public/operations/migration-plan.js +37 -7
  22. package/dist/public/operations/specs/mutation-schemas.d.ts +2 -2
  23. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  24. package/dist/public/operations/specs/mutation-schemas.js +8 -17
  25. package/dist/public/operations/specs/upsert.d.ts +2 -2
  26. package/dist/public/schemas/entity.d.ts.map +1 -1
  27. package/dist/public/schemas/entity.js +2 -13
  28. package/dist/public/skills/kibi-usage/SKILL.md +3 -1
  29. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
  30. package/dist/public/skills/kibi-usage/resources/ui-requirements.md +2 -2
  31. package/dist/public/skills/kibi-usage/resources/workflows.md +1 -1
  32. package/dist/schemas/entity.schema.json +2 -25
  33. package/package.json +1 -1
  34. package/src/public/operations/migration-plan.ts +41 -9
  35. package/src/public/operations/specs/mutation-schemas.ts +8 -17
  36. package/src/public/schemas/entity.ts +2 -13
  37. package/src/public/skills/kibi-usage/SKILL.md +3 -1
  38. package/src/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
  39. package/src/public/skills/kibi-usage/resources/ui-requirements.md +2 -2
  40. package/src/public/skills/kibi-usage/resources/workflows.md +1 -1
  41. package/src/schemas/entity.schema.json +2 -25
@@ -5,6 +5,8 @@ interface MigrateOptions {
5
5
  applySafe?: boolean;
6
6
  approvedPlanHash?: string;
7
7
  approvedActionIds?: string[];
8
+ /** `--approved-action <id>` as the CLI parser spells it; same as approvedActionIds. */
9
+ approvedAction?: string[];
8
10
  workspaceRoot?: string;
9
11
  /** Internal migration-plan executor: create only the canonical baseline manifest. */
10
12
  initializeMissingConfig?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAiEA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAuKD,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,OAAO,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,MAAM,CAUR;AAsXD,wBAAgB,+BAA+B,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKtE;AAGD,wBAAsB,cAAc,CAClC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAiW/B"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAiEA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAuKD,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,OAAO,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,MAAM,CAUR;AAsXD,wBAAgB,+BAA+B,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKtE;AAGD,wBAAsB,cAAc,CAClC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAiW/B"}
@@ -761,20 +761,47 @@ async function buildWorkspaceMigrationPlan(workspaceRoot = process.cwd()) {
761
761
  }
762
762
  return mergeMigrationPlans(plans);
763
763
  }
764
+ /**
765
+ * The action ids approved on the command line. The CLI parser stores
766
+ * `--approved-action` as `approvedAction`; in-process callers pass
767
+ * `approvedActionIds`. Either spelling limits `--apply-safe` to those ids.
768
+ */
769
+ // implements REQ-cli-schema-migration
770
+ function approvedActionIdsOf(options) {
771
+ const ids = [
772
+ ...(options.approvedActionIds ?? []),
773
+ ...(options.approvedAction ?? []),
774
+ ]
775
+ .map((id) => id.trim())
776
+ .filter((id) => id.length > 0);
777
+ return [...new Set(ids)];
778
+ }
764
779
  async function migratePlanCommand(options) {
765
780
  const workspaceRoot = path.resolve(options.workspaceRoot ?? process.cwd());
766
781
  const plan = await buildWorkspaceMigrationPlan(workspaceRoot);
767
- if (options.applySafe === true) {
768
- if (!options.approvedPlanHash) {
782
+ // `--yes` with JSON output applies every ready automatic action of the plan
783
+ // it would otherwise only print; `--dry-run` still only prints it.
784
+ const approveWholePlan = options.applySafe !== true &&
785
+ options.yes === true &&
786
+ options.dryRun !== true &&
787
+ options.format === "json";
788
+ if (options.applySafe === true || approveWholePlan) {
789
+ const approvedPlanHash = approveWholePlan
790
+ ? plan.planHash
791
+ : options.approvedPlanHash;
792
+ if (!approvedPlanHash) {
769
793
  console.error("--apply-safe requires --approved-plan-hash <sha256>.");
770
794
  return { exitCode: 2 };
771
795
  }
772
- if (options.approvedPlanHash !== plan.planHash) {
796
+ if (approvedPlanHash !== plan.planHash) {
773
797
  console.error("Migration plan changed; regenerate the plan and approve its current hash.");
774
798
  return { exitCode: 2 };
775
799
  }
776
- const approvedActionIds = options.approvedActionIds && options.approvedActionIds.length > 0
777
- ? options.approvedActionIds
800
+ const explicitActionIds = approveWholePlan
801
+ ? []
802
+ : approvedActionIdsOf(options);
803
+ const approvedActionIds = explicitActionIds.length > 0
804
+ ? explicitActionIds
778
805
  : plan.actions
779
806
  .filter((action) => action.state === "ready" && action.autoApplicable)
780
807
  .map((action) => action.id);
@@ -788,7 +815,6 @@ async function migratePlanCommand(options) {
788
815
  import("../public/operations/specs/planning.js"),
789
816
  import("../cli-json-command.js"),
790
817
  ]);
791
- const approvedPlanHash = options.approvedPlanHash;
792
818
  const execute = () => executeOperation(createCliRuntime({ workspaceRoot }), applyPlanSpec, {
793
819
  plan,
794
820
  approvedPlanHash,
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/discovery.ts"],"names":[],"mappings":"AAkCA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,+EAA+E;IAC/E,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AA2FH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOlD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAShE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUxD;AAED,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,SAAS,4BAA4B,EAAE,GAChD,IAAI,CA6CN;AAsBD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,GAAG,IAAI,CAIf;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC;IACT,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,4BAA4B,EAAE,4BAA4B,EAAE,CAAC;CAC9D,CAAC,CA+FD"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/discovery.ts"],"names":[],"mappings":"AAkCA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,+EAA+E;IAC/E,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAwGH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOlD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAShE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUxD;AAED,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,SAAS,4BAA4B,EAAE,GAChD,IAAI,CA6CN;AAsBD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,GAAG,IAAI,CAIf;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC;IACT,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,4BAA4B,EAAE,4BAA4B,EAAE,CAAC;CAC9D,CAAC,CAgGD"}
@@ -34,7 +34,14 @@ async function gitTrackedPaths(cwd) {
34
34
  .filter(Boolean)
35
35
  .map((value) => value.replaceAll("\\", "/")));
36
36
  }
37
- function pendingSourcePaths(cwd, recoverMissing) {
37
+ /**
38
+ * The sources bound by pending receipts. A receipt whose file Git now tracks
39
+ * is kept as an input but not compared, whatever its hash says: the tracked
40
+ * bytes are the authored input, and the caller retires that receipt. Only a
41
+ * receipt for a still-untracked file can refuse the sync on hash drift.
42
+ */
43
+ // implements REQ-core-atomic-upsert-persistence
44
+ function pendingSourcePaths(cwd, recoverMissing, tracked = new Set()) {
38
45
  const root = path.join(cwd, ".kb", "recovery", "pending-sources");
39
46
  if (!existsSync(root)) {
40
47
  return { paths: new Map(), recoveredReceipts: [] };
@@ -53,6 +60,11 @@ function pendingSourcePaths(cwd, recoverMissing) {
53
60
  typeof receipt.afterHash === "string" &&
54
61
  /^[a-f0-9]{64}$/i.test(receipt.afterHash)) {
55
62
  const relative = receipt.path.replaceAll("\\", "/");
63
+ if (tracked.has(relative)) {
64
+ // Still an authored input; only the stale hash is ignored.
65
+ paths.set(relative, receipt.afterHash);
66
+ continue;
67
+ }
56
68
  const absolute = path.resolve(cwd, relative);
57
69
  if (!absolute.startsWith(`${path.resolve(cwd)}${path.sep}`)) {
58
70
  throw new Error(`Pending source receipt escapes workspace: ${relative}`);
@@ -199,7 +211,7 @@ export async function discoverSourceFiles(cwd, options = {}) {
199
211
  const recoveredPendingReceiptPaths = [];
200
212
  if (options.trackedOnly) {
201
213
  const tracked = await gitTrackedPaths(cwd);
202
- const pending = pendingSourcePaths(cwd, options.recoverMissingPendingSources === true);
214
+ const pending = pendingSourcePaths(cwd, options.recoverMissingPendingSources === true, tracked);
203
215
  recoveredPendingReceiptPaths.push(...pending.recoveredReceipts);
204
216
  entityMarkdownFiles = filterTracked(cwd, entityMarkdownFiles, tracked, new Set(pending.paths.keys()));
205
217
  manifestFiles = filterTracked(cwd, manifestFiles, tracked, new Set(pending.paths.keys()));
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@ import { readFileSync } from "node:fs";
20
20
  import Ajv from "ajv";
21
21
  import { load as yamlLoad } from "js-yaml";
22
22
  import { withoutContextSections } from "../entity-body-context.js";
23
- import { semanticClaimKey } from "../operations/semantic-advisor/clauses.js";
23
+ import { deriveFactClaimKey, semanticClaimKey, } from "../operations/semantic-advisor/clauses.js";
24
24
  import { normalizeEntityOrigin, } from "../public/entity-origin.js";
25
25
  import { PROOF_BINDINGS_SCHEMA, PROOF_CONTRACT_SCHEMA, } from "../public/proof-protocol.js";
26
26
  import { proofReceiptHistoryErrors, } from "../public/proof-receipt.js";
@@ -671,6 +671,7 @@ function extractFromMarkdownContent(content, filePath) {
671
671
  hint: "Fix the entity fields so they match the public schema.",
672
672
  });
673
673
  }
674
+ deriveFactClaimKey(entity);
674
675
  if (entity.type === "fact" &&
675
676
  entity.claim_key !== undefined &&
676
677
  entity.claim_text !== undefined) {
@@ -47,7 +47,11 @@ export declare function withTopLevelField(content: string, key: string, value: s
47
47
  * change (the key gone, every other key parsing identically).
48
48
  */
49
49
  export declare function withoutTopLevelField(content: string, key: string): string | null;
50
- /** Replace a file's bytes atomically. */
50
+ /**
51
+ * Replace a file's bytes atomically. A migration rewrite of an untracked
52
+ * `.kb/` source also rebinds its pending-source receipt, so the next sync
53
+ * reads the rewritten file instead of refusing it as hash drift.
54
+ */
51
55
  export declare function writeFileAtomically(filePath: string, content: string): void;
52
56
  export declare function readText(filePath: string): string | null;
53
57
  //# sourceMappingURL=kb-sources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kb-sources.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/kb-sources.ts"],"names":[],"mappings":"AA8BA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,yBAAyB,CAAC;AAEjC,yEAAyE;AAEzE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAuBH,0EAA0E;AAE1E,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,KAAK,GAAE,SAAS,UAAU,EAAiB,GAC1C,gBAAgB,EAAE,CAkBpB;AAED,6DAA6D;AAE7D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,IAAI,GAAG,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAczE;AAUD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAe3E;AAeD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAyBf;AAQD;;;;;;GAMG;AAEH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAsBf;AAED,yCAAyC;AAEzC,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK3E;AAGD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxD"}
1
+ {"version":3,"file":"kb-sources.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/kb-sources.ts"],"names":[],"mappings":"AA+BA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,yBAAyB,CAAC;AAGjC,yEAAyE;AAEzE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAuBH,0EAA0E;AAE1E,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,KAAK,GAAE,SAAS,UAAU,EAAiB,GAC1C,gBAAgB,EAAE,CAkBpB;AAED,6DAA6D;AAE7D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,IAAI,GAAG,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAczE;AAUD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAe3E;AAeD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAyBf;AAQD;;;;;;GAMG;AAEH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAsBf;AAID;;;;GAIG;AAEH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAY3E;AAqBD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxD"}
@@ -15,11 +15,13 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
+ import { createHash } from "node:crypto";
18
19
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync, } from "node:fs";
19
20
  import path from "node:path";
20
21
  import { isDeepStrictEqual } from "node:util";
21
22
  import { load as loadYaml } from "js-yaml";
22
23
  import { ENTITY_LANES, KB_PATHS, } from "../../utils/kb-paths.js";
24
+ import { republishPendingSourceReceipt } from "../mutation/source-authoring.js";
23
25
  function walkMarkdown(directory, files) {
24
26
  let entries;
25
27
  try {
@@ -214,13 +216,38 @@ export function withoutTopLevelField(content, key) {
214
216
  }
215
217
  return match === null ? content : `${slice.prefix}${text}${slice.suffix}`;
216
218
  }
217
- /** Replace a file's bytes atomically. */
219
+ const KB_ROOT_DIRNAME = ".kb";
220
+ /**
221
+ * Replace a file's bytes atomically. A migration rewrite of an untracked
222
+ * `.kb/` source also rebinds its pending-source receipt, so the next sync
223
+ * reads the rewritten file instead of refusing it as hash drift.
224
+ */
218
225
  // implements REQ-cli-schema-migration
219
226
  export function writeFileAtomically(filePath, content) {
220
227
  mkdirSync(path.dirname(filePath), { recursive: true });
221
228
  const tempPath = `${filePath}.kibi-migrate-${process.pid}-${Date.now()}`;
222
229
  writeFileSync(tempPath, content, "utf8");
223
230
  renameSync(tempPath, filePath);
231
+ const source = kbSourceLocation(filePath);
232
+ if (source === null)
233
+ return;
234
+ republishPendingSourceReceipt(source.workspaceRoot, source.relativePath, createHash("sha256").update(content, "utf8").digest("hex"));
235
+ }
236
+ /**
237
+ * The workspace root and workspace-relative path of a file under `.kb/`, or
238
+ * `null` for a file outside any knowledge root.
239
+ */
240
+ function kbSourceLocation(filePath) {
241
+ const absolute = path.resolve(filePath);
242
+ const segments = absolute.split(path.sep);
243
+ const index = segments.lastIndexOf(KB_ROOT_DIRNAME);
244
+ if (index <= 0)
245
+ return null;
246
+ const workspaceRoot = segments.slice(0, index).join(path.sep) || path.sep;
247
+ return {
248
+ workspaceRoot,
249
+ relativePath: segments.slice(index).join("/"),
250
+ };
224
251
  }
225
252
  // implements REQ-cli-schema-migration
226
253
  export function readText(filePath) {
@@ -26,6 +26,14 @@ export declare function restoreFileTimes(absolutePath: string, times: FileTimes
26
26
  * removed file makes every later sync fail on a missing pending source.
27
27
  */
28
28
  export declare function retirePendingSourceReceipt(workspaceRoot: string, relativePath: string): void;
29
+ /**
30
+ * Rebind the pending receipt of an untracked source that a migration rewrote
31
+ * in place. A receipt pins the file to exact bytes; a rewrite that leaves the
32
+ * old hash behind makes every later sync refuse the file as "hash drift", so
33
+ * a migration republishes the receipt it finds, and leaves a file without
34
+ * one alone (tracked sources carry no receipt). Returns whether one existed.
35
+ */
36
+ export declare function republishPendingSourceReceipt(workspaceRoot: string, relativePath: string, afterHash: string): boolean;
29
37
  export declare function resolveContainedSourcePath(workspaceRoot: string, relative: string): string;
30
38
  export declare function normalizeAuthoredSourcePath(workspaceRoot: string, source: string): string;
31
39
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"source-authoring.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/source-authoring.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"source-authoring.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/source-authoring.ts"],"names":[],"mappings":"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"}
@@ -82,6 +82,39 @@ export function retirePendingSourceReceipt(workspaceRoot, relativePath) {
82
82
  throw error;
83
83
  }
84
84
  }
85
+ /**
86
+ * Rebind the pending receipt of an untracked source that a migration rewrote
87
+ * in place. A receipt pins the file to exact bytes; a rewrite that leaves the
88
+ * old hash behind makes every later sync refuse the file as "hash drift", so
89
+ * a migration republishes the receipt it finds, and leaves a file without
90
+ * one alone (tracked sources carry no receipt). Returns whether one existed.
91
+ */
92
+ // implements REQ-cli-schema-migration, REQ-core-atomic-upsert-persistence
93
+ export function republishPendingSourceReceipt(workspaceRoot, relativePath, afterHash) {
94
+ const receiptPath = pendingReceiptPath(workspaceRoot, relativePath);
95
+ const raw = readPendingSourceReceiptBytes(receiptPath);
96
+ if (raw === null)
97
+ return false;
98
+ let receipt;
99
+ try {
100
+ const parsed = JSON.parse(raw);
101
+ receipt =
102
+ parsed !== null && typeof parsed === "object"
103
+ ? parsed
104
+ : {};
105
+ }
106
+ catch {
107
+ receipt = {};
108
+ }
109
+ fs.writeFileSync(receiptPath, `${JSON.stringify({
110
+ version: 1,
111
+ ...receipt,
112
+ path: relativePath,
113
+ afterHash,
114
+ rebasedAt: new Date().toISOString(),
115
+ }, null, 2)}\n`, { mode: 0o600 });
116
+ return true;
117
+ }
85
118
  /**
86
119
  * Authored YAML round-trips keep long scalars on one line, matching sync and
87
120
  * coordinate refresh output, so editing one entry never refolds the others.
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validation.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,oCAAoC,CAAC;AAO5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAqI/D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,IAAI,GACR,eAAe,CA4DjB;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validation.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,0BAA0B,EAC3B,MAAM,oCAAoC,CAAC;AAU5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAqI/D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,IAAI,GACR,eAAe,CA6DjB;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
@@ -4,7 +4,7 @@ import entitySchema from "../../public/schemas/entity.js";
4
4
  import relationshipSchema from "../../public/schemas/relationship.js";
5
5
  // implements REQ-kibi-operation-interface-parity
6
6
  import { SYMBOL_ROLES, isAllowedGranularityReason, } from "../../public/symbol-granularity.js";
7
- import { semanticClaimKey } from "../semantic-advisor/clauses.js";
7
+ import { deriveFactClaimKey, semanticClaimKey, } from "../semantic-advisor/clauses.js";
8
8
  import { factKindShapeHints, validateFactModelingShape, valueFieldHint, } from "./strict-fact.js";
9
9
  const ajv = new Ajv({ strict: false });
10
10
  const schema = entitySchema;
@@ -128,6 +128,7 @@ export function validateUpsertInput(input, now) {
128
128
  if (!validateEntity(entity)) {
129
129
  throw new Error(`Entity validation failed: ${formatEntityErrors(entity, validateEntity.errors ?? [])}`);
130
130
  }
131
+ deriveFactClaimKey(entity);
131
132
  validateSymbolSourceFile(entity);
132
133
  validateProofExemptionPairing(entity);
133
134
  if (entity.type === "test" && Array.isArray(entity.proof_receipts)) {
@@ -9,5 +9,14 @@ export declare function hasNormativeAssertion(text: string): boolean;
9
9
  export declare function modeledClaimRole(text: string, modality?: string): "normative" | "descriptive";
10
10
  export declare function normalizeSemanticClause(value: string): string;
11
11
  export declare function semanticClaimKey(text: string): string;
12
+ /**
13
+ * Fill `claim_key` from `claim_text` on a fact that may ground a claim.
14
+ *
15
+ * The key is a pure function of the text, so a caller that sends the text
16
+ * alone has given Kibi everything it needs; a supplied key is still checked
17
+ * against the derived one by the entity validators. Observation and meta
18
+ * facts quote a claim without owning it, so they stay keyless.
19
+ */
20
+ export declare function deriveFactClaimKey(entity: Record<string, unknown>): void;
12
21
  export declare function extractSemanticClauses(text: string, suppliedClauses?: readonly string[]): readonly SemanticClause[];
13
22
  //# sourceMappingURL=clauses.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;AAmBH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAQD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,GAAG,aAAa,CAG7B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AA4BD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,SAAS,cAAc,EAAE,CA4B3B"}
1
+ {"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;AAmBH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAQD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,GAAG,aAAa,CAG7B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AAKD;;;;;;;GAOG;AAEH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWxE;AA4BD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,SAAS,cAAc,EAAE,CA4B3B"}
@@ -38,6 +38,30 @@ export function semanticClaimKey(text) {
38
38
  const digest = createHash("sha256").update(normalized).digest("hex");
39
39
  return `CLAIM-${digest.slice(0, 16).toUpperCase()}`;
40
40
  }
41
+ /** Fact kinds that quote a claim as a review note and never ground it. */
42
+ const NON_GROUNDING_FACT_KINDS = new Set(["observation", "meta"]);
43
+ /**
44
+ * Fill `claim_key` from `claim_text` on a fact that may ground a claim.
45
+ *
46
+ * The key is a pure function of the text, so a caller that sends the text
47
+ * alone has given Kibi everything it needs; a supplied key is still checked
48
+ * against the derived one by the entity validators. Observation and meta
49
+ * facts quote a claim without owning it, so they stay keyless.
50
+ */
51
+ // implements REQ-kibi-review-observation-claim-text-v2
52
+ export function deriveFactClaimKey(entity) {
53
+ if (entity.type !== "fact")
54
+ return;
55
+ if (entity.claim_key !== undefined)
56
+ return;
57
+ if (typeof entity.claim_text !== "string")
58
+ return;
59
+ if (typeof entity.fact_kind === "string" &&
60
+ NON_GROUNDING_FACT_KINDS.has(entity.fact_kind)) {
61
+ return;
62
+ }
63
+ entity.claim_key = semanticClaimKey(entity.claim_text);
64
+ }
41
65
  function detectedClauses(text) {
42
66
  return text
43
67
  .split(/(?:\r?\n)+|;|(?<=[.!?])\s+(?=[A-Z0-9])/)
@@ -1521,11 +1521,11 @@ export declare const OPERATION_CATALOG: readonly [{
1521
1521
  readonly claim_key: {
1522
1522
  readonly type: "string";
1523
1523
  readonly pattern: "^CLAIM-[A-F0-9]{16}$";
1524
- readonly description: "Stable semantic-advisor key for the atomic prose clause grounded by this fact.";
1524
+ readonly description: "Stable key of the atomic prose clause grounded by this fact, derived from claim_text. Optional: when omitted, Kibi derives it; when sent, it must equal the derived key.";
1525
1525
  };
1526
1526
  readonly claim_text: {
1527
1527
  readonly type: "string";
1528
- readonly description: "Exact atomic requirement clause represented by this fact, retained for human audit. Requires claim_key, except on an observation or meta fact, which may quote the clause it is about without claim_key.";
1528
+ readonly description: "Exact atomic requirement clause represented by this fact, retained for human audit. On a grounding fact Kibi derives claim_key from it; an observation or meta fact quotes the clause it is about without a key.";
1529
1529
  };
1530
1530
  readonly predicate_name: {
1531
1531
  readonly type: "string";
@@ -1 +1 @@
1
- {"version":3,"file":"migration-plan.d.ts","sourceRoot":"","sources":["../../../src/public/operations/migration-plan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"migration-plan.d.ts","sourceRoot":"","sources":["../../../src/public/operations/migration-plan.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import * as path from "node:path";
4
+ import { planLegacyStorageMigration } from "../../commands/legacy-storage-migration.js";
4
5
  import { BRANCH_STORE_NOT_COMPILED } from "../../utils/branch-store.js";
5
6
  import { legacyConfigExists } from "../../utils/config.js";
6
7
  import { MTIME_SOURCE_REASON_CODES } from "../../utils/content-freshness.js";
@@ -488,6 +489,13 @@ export function buildActionsFromStatus(input) {
488
489
  }
489
490
  const storeState = typeof store?.state === "string" ? store.state : null;
490
491
  const legacyStorageMigrationRequired = legacyConfigExists(input.workspaceRoot);
492
+ // A legacy cutover that cannot move its files (a destination already
493
+ // exists, a malformed config) is an operator decision, not an automatic
494
+ // step that fails when applied and takes the compile with it.
495
+ const legacyStorage = legacyStorageMigrationRequired
496
+ ? planLegacyStorageMigration(input.workspaceRoot)
497
+ : null;
498
+ const legacyStorageBlocked = legacyStorage !== null && legacyStorage.blockers.length > 0;
491
499
  if (storeState === "missing") {
492
500
  actions.push(migrationAction({
493
501
  id: "branch-store-ensure",
@@ -520,6 +528,7 @@ export function buildActionsFromStatus(input) {
520
528
  }));
521
529
  }
522
530
  if (configStatus.needsMigration || legacyStorageMigrationRequired) {
531
+ const operatorOnly = configStatus.status === "newer" || legacyStorageBlocked;
523
532
  actions.push(migrationAction({
524
533
  id: "schema-config-upgrade",
525
534
  code: configStatus.status === "invalid"
@@ -528,17 +537,34 @@ export function buildActionsFromStatus(input) {
528
537
  ? "legacy_storage_migration"
529
538
  : "schema_version_upgrade",
530
539
  category: "schema",
531
- state: configStatus.status === "newer" ? "blocked" : "ready",
532
- safety: configStatus.status === "newer" ? "operator" : "automatic",
533
- invocation: { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
540
+ state: operatorOnly ? "blocked" : "ready",
541
+ safety: operatorOnly ? "operator" : "automatic",
542
+ invocation: legacyStorageBlocked
543
+ ? {
544
+ kind: "review",
545
+ instruction: `The legacy .kb/config.json still names knowledge files outside .kb/ and Kibi cannot move them: ${legacyStorage?.blockers.join(" ")} Keep one copy of each conflicting file (the .kb/ one is what Kibi compiles), remove or git-rm the legacy copy, then run 'kibi migrate --yes' to retire .kb/config.json.`,
546
+ }
547
+ : { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
534
548
  affectedFiles: [
535
549
  ".kb/manifest.json",
536
550
  ".kb/migrations",
537
551
  ".kb/config.json",
552
+ ...(legacyStorage?.moves.map((move) => move.from) ?? []),
538
553
  ],
539
- evidence: { configStatus },
554
+ evidence: {
555
+ configStatus,
556
+ ...(legacyStorage === null
557
+ ? {}
558
+ : {
559
+ legacyStorage: {
560
+ moves: legacyStorage.moves,
561
+ blockers: legacyStorage.blockers,
562
+ legacyConfig: legacyStorage.legacyConfig,
563
+ },
564
+ }),
565
+ },
540
566
  dependsOn: storeState === "missing" ? ["branch-store-ensure"] : [],
541
- autoApplicable: configStatus.status !== "newer",
567
+ autoApplicable: !operatorOnly,
542
568
  }));
543
569
  }
544
570
  // implements REQ-cli-status-pre-first-sync
@@ -558,9 +584,13 @@ export function buildActionsFromStatus(input) {
558
584
  typeof store?.path === "string" ? store.path : ".kb/branches",
559
585
  ],
560
586
  evidence: { reason: uncompiled },
587
+ // A blocked schema step waits on an operator; the compile still runs
588
+ // from the .kb/ sources Kibi already reads.
561
589
  dependsOn: actions
562
- .map((action) => action.id)
563
- .filter((id) => id === "branch-store-ensure" || id === "schema-config-upgrade"),
590
+ .filter((action) => action.state === "ready" &&
591
+ (action.id === "branch-store-ensure" ||
592
+ action.id === "schema-config-upgrade"))
593
+ .map((action) => action.id),
564
594
  postconditions: [{ branchStore: "compiled" }],
565
595
  autoApplicable: true,
566
596
  }));
@@ -522,11 +522,11 @@ export declare const ENTITY_PROPERTIES_SCHEMA: {
522
522
  readonly claim_key: {
523
523
  readonly type: "string";
524
524
  readonly pattern: "^CLAIM-[A-F0-9]{16}$";
525
- readonly description: "Stable semantic-advisor key for the atomic prose clause grounded by this fact.";
525
+ readonly description: "Stable key of the atomic prose clause grounded by this fact, derived from claim_text. Optional: when omitted, Kibi derives it; when sent, it must equal the derived key.";
526
526
  };
527
527
  readonly claim_text: {
528
528
  readonly type: "string";
529
- readonly description: "Exact atomic requirement clause represented by this fact, retained for human audit. Requires claim_key, except on an observation or meta fact, which may quote the clause it is about without claim_key.";
529
+ readonly description: "Exact atomic requirement clause represented by this fact, retained for human audit. On a grounding fact Kibi derives claim_key from it; an observation or meta fact quotes the clause it is about without a key.";
530
530
  };
531
531
  readonly predicate_name: {
532
532
  readonly type: "string";
@@ -1 +1 @@
1
- {"version":3,"file":"mutation-schemas.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/mutation-schemas.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,gFASf,CAAC;AAoBX,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoX3B,CAAC;AAEX,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;CA8CvB,CAAC"}
1
+ {"version":3,"file":"mutation-schemas.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/mutation-schemas.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,gFASf,CAAC;AAWX,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoX3B,CAAC;AAEX,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;CA8CvB,CAAC"}
@@ -11,22 +11,13 @@ export const ENTITY_TYPES = [
11
11
  "symbol",
12
12
  "fact",
13
13
  ];
14
- // An observation or meta fact may quote a claim in claim_text alone: it is a
15
- // non-grounding review note, so it does not claim the clause's key.
14
+ // A claim_key names the clause in claim_text, so it never travels alone. The
15
+ // reverse is open: Kibi derives a missing claim_key from claim_text on a
16
+ // grounding fact, and an observation or meta fact quotes a claim without one.
17
+ // implements REQ-kibi-review-observation-claim-text-v2
16
18
  const CLAIM_PROVENANCE_CONDITIONAL = JSON.parse(`{
17
- "if": {
18
- "anyOf": [
19
- { "required": ["claim_key"] },
20
- {
21
- "required": ["claim_text"],
22
- "not": {
23
- "properties": { "fact_kind": { "enum": ["observation", "meta"] } },
24
- "required": ["fact_kind"]
25
- }
26
- }
27
- ]
28
- },
29
- "then": { "required": ["claim_key", "claim_text"] }
19
+ "if": { "required": ["claim_key"] },
20
+ "then": { "required": ["claim_text"] }
30
21
  }`);
31
22
  export const ENTITY_PROPERTIES_SCHEMA = {
32
23
  type: "object",
@@ -251,11 +242,11 @@ export const ENTITY_PROPERTIES_SCHEMA = {
251
242
  claim_key: {
252
243
  type: "string",
253
244
  pattern: "^CLAIM-[A-F0-9]{16}$",
254
- description: "Stable semantic-advisor key for the atomic prose clause grounded by this fact.",
245
+ description: "Stable key of the atomic prose clause grounded by this fact, derived from claim_text. Optional: when omitted, Kibi derives it; when sent, it must equal the derived key.",
255
246
  },
256
247
  claim_text: {
257
248
  type: "string",
258
- description: "Exact atomic requirement clause represented by this fact, retained for human audit. Requires claim_key, except on an observation or meta fact, which may quote the clause it is about without claim_key.",
249
+ description: "Exact atomic requirement clause represented by this fact, retained for human audit. On a grounding fact Kibi derives claim_key from it; an observation or meta fact quotes the clause it is about without a key.",
259
250
  },
260
251
  predicate_name: {
261
252
  type: "string",
@@ -539,11 +539,11 @@ export declare const upsertSpec: {
539
539
  readonly claim_key: {
540
540
  readonly type: "string";
541
541
  readonly pattern: "^CLAIM-[A-F0-9]{16}$";
542
- readonly description: "Stable semantic-advisor key for the atomic prose clause grounded by this fact.";
542
+ readonly description: "Stable key of the atomic prose clause grounded by this fact, derived from claim_text. Optional: when omitted, Kibi derives it; when sent, it must equal the derived key.";
543
543
  };
544
544
  readonly claim_text: {
545
545
  readonly type: "string";
546
- readonly description: "Exact atomic requirement clause represented by this fact, retained for human audit. Requires claim_key, except on an observation or meta fact, which may quote the clause it is about without claim_key.";
546
+ readonly description: "Exact atomic requirement clause represented by this fact, retained for human audit. On a grounding fact Kibi derives claim_key from it; an observation or meta fact quotes the clause it is about without a key.";
547
547
  };
548
548
  readonly predicate_name: {
549
549
  readonly type: "string";
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/entity.ts"],"names":[],"mappings":"AAmUA,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CA4ZzC,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/public/schemas/entity.ts"],"names":[],"mappings":"AAwTA,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CA4ZzC,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -22,19 +22,8 @@ import { PROOF_RECEIPT_SCHEMA } from "../proof-receipt.js";
22
22
  import { SYMBOL_ROLES } from "../symbol-granularity.js";
23
23
  const factConditionals = JSON.parse(`[
24
24
  {
25
- "if": {
26
- "anyOf": [
27
- { "required": ["claim_key"] },
28
- {
29
- "required": ["claim_text"],
30
- "not": {
31
- "properties": { "fact_kind": { "enum": ["observation", "meta"] } },
32
- "required": ["fact_kind"]
33
- }
34
- }
35
- ]
36
- },
37
- "then": { "required": ["claim_key", "claim_text"] }
25
+ "if": { "required": ["claim_key"] },
26
+ "then": { "required": ["claim_text"] }
38
27
  },
39
28
  {
40
29
  "if": {
@@ -2,7 +2,7 @@
2
2
  id: kibi-usage
3
3
  name: Kibi Usage
4
4
  description: Use Kibi's source-first, exact-Git, migration-aware, proof-aware operations safely across MCP or the trusted local CLI, including partial completion repair.
5
- version: 2.15.2
5
+ version: 2.15.3
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -369,6 +369,8 @@ For each relational clause, call `kb_model` with `mode: "predicates"`, that clau
369
369
  reviewed `schemaId`. If `binding_status` is `incomplete`, supply
370
370
  `argumentBindings` and retry. Persist `fact_kind: predicate` with the same
371
371
  `claim_key` / `claim_text`, then link `REQ -> fact` with `requires_predicate`.
372
+ `claim_key` is derived from `claim_text`, so a ground fact may send the exact
373
+ clause alone and Kibi fills the key in; a sent key must equal the derived one.
372
374
  Use `kb_model` with `mode: "requirement"` for strict scalar clauses. Use
373
375
  `fact_kind: observation` only for a true ontology gap. The manifest is not
374
376
  grounding: run `logic-coverage` so each key binds to one ground fact.
@@ -6,7 +6,7 @@ Requirement prose remains the human-readable source. Facts add queryable semanti
6
6
 
7
7
  Logical coverage is clause-based, not entity-based. Give `kb_model` (`mode: "analyze"`) the complete requirement body and verify that its `clauses` list contains every atomic obligation. Supply the `clauses` input yourself when automatic splitting would combine or omit obligations. For every normative clause:
8
8
 
9
- - preserve the returned stable key as `claim_key` and the exact clause as `claim_text` on its ground fact;
9
+ - put the exact clause as `claim_text` on its ground fact, with the returned stable key as `claim_key` or none (Kibi derives a missing key; a sent key must match);
10
10
  - add the key to the exact current `logic_claims` set, removing only stale keys whose propositions no longer exist in the source;
11
11
  - link it through exactly one `requires_property` for `property_value`, one `requires_predicate` for `predicate`, or one `requires_rule` for a safe `rule` fact;
12
12
  - leave ambiguity and ontology gaps visibly unresolved—observations do not satisfy `logic-coverage`.
@@ -126,8 +126,8 @@ diagnostics (`symbol_semantic_review_needed`).
126
126
  `requires_predicate`.
127
127
  3. Scalar placement/alignment/order clauses: `kb_model` (`mode: "requirement"`), apply the strict
128
128
  subject/property plan and `constrains` / `requires_property`.
129
- 4. Preserve `claim_key` / `claim_text`; merge every key into the requirement
130
- `logic_claims` manifest.
129
+ 4. Preserve `claim_key` / `claim_text` (a missing key is derived from the
130
+ text); merge every key into the requirement `logic_claims` manifest.
131
131
  5. `kb_upsert` with `dryRun: true`, create endpoints first, then sequential `kb_upsert`.
132
132
  6. `kb_check` with `logic-coverage`, `predicate-verifiability`, `domain-contradictions`,
133
133
  then a final unfiltered `kb_check`.
@@ -203,7 +203,7 @@ Optional per-project workflow for recording what the screen should look like. No
203
203
  2. Run `kb_model` with `mode: "analyze"` on the description; audit or supply `clauses`.
204
204
  3. For relational layout clauses ("X must remain visually aligned with Y"), call `kb_model` with `mode: "predicates"`, apply the returned `fact_kind: predicate` plan with `predicate_name: visual_layout_rule` and `requires_predicate`.
205
205
  4. For scalar placement, alignment, and ordering clauses, call `kb_model` with `mode: "requirement"` and apply strict `fact_kind: subject` / `fact_kind: property_value` facts linked with `constrains` / `requires_property`. Model header order as indexed property keys (`nav_order_1`, `nav_order_2`, ...) against one subject region.
206
- 5. Preserve `claim_key` / `claim_text` on every ground fact and merge every key into the requirement `logic_claims` manifest.
206
+ 5. Preserve `claim_key` / `claim_text` on every ground fact (a missing `claim_key` is derived from `claim_text`) and merge every key into the requirement `logic_claims` manifest.
207
207
  6. Model UI components as `symbol` entities with `sourceFile` and `symbol_role: behavioral`, linked `implements` to the requirement.
208
208
  7. `kb_upsert` with `dryRun: true`, create endpoints first, then sequential `kb_upsert`. Run `kb_check` with `logic-coverage`, `predicate-verifiability`, and `domain-contradictions`, then a final unfiltered `kb_check`.
209
209
 
@@ -1675,35 +1675,12 @@
1675
1675
  },
1676
1676
  {
1677
1677
  "if": {
1678
- "anyOf": [
1679
- {
1680
- "required": [
1681
- "claim_key"
1682
- ]
1683
- },
1684
- {
1685
- "required": [
1686
- "claim_text"
1687
- ],
1688
- "not": {
1689
- "properties": {
1690
- "fact_kind": {
1691
- "enum": [
1692
- "observation",
1693
- "meta"
1694
- ]
1695
- }
1696
- },
1697
- "required": [
1698
- "fact_kind"
1699
- ]
1700
- }
1701
- }
1678
+ "required": [
1679
+ "claim_key"
1702
1680
  ]
1703
1681
  },
1704
1682
  "then": {
1705
1683
  "required": [
1706
- "claim_key",
1707
1684
  "claim_text"
1708
1685
  ]
1709
1686
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cli",
3
- "version": "2.20.0",
3
+ "version": "2.21.0",
4
4
  "type": "module",
5
5
  "description": "Kibi CLI for knowledge base management",
6
6
  "engines": {
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import * as path from "node:path";
4
+ import { planLegacyStorageMigration } from "../../commands/legacy-storage-migration.js";
4
5
  import { BRANCH_STORE_NOT_COMPILED } from "../../utils/branch-store.js";
5
6
  import { legacyConfigExists } from "../../utils/config.js";
6
7
  import { MTIME_SOURCE_REASON_CODES } from "../../utils/content-freshness.js";
@@ -688,6 +689,14 @@ export function buildActionsFromStatus(input: {
688
689
  const legacyStorageMigrationRequired = legacyConfigExists(
689
690
  input.workspaceRoot,
690
691
  );
692
+ // A legacy cutover that cannot move its files (a destination already
693
+ // exists, a malformed config) is an operator decision, not an automatic
694
+ // step that fails when applied and takes the compile with it.
695
+ const legacyStorage = legacyStorageMigrationRequired
696
+ ? planLegacyStorageMigration(input.workspaceRoot)
697
+ : null;
698
+ const legacyStorageBlocked =
699
+ legacyStorage !== null && legacyStorage.blockers.length > 0;
691
700
  if (storeState === "missing") {
692
701
  actions.push(
693
702
  migrationAction({
@@ -724,6 +733,8 @@ export function buildActionsFromStatus(input: {
724
733
  }
725
734
 
726
735
  if (configStatus.needsMigration || legacyStorageMigrationRequired) {
736
+ const operatorOnly =
737
+ configStatus.status === "newer" || legacyStorageBlocked;
727
738
  actions.push(
728
739
  migrationAction({
729
740
  id: "schema-config-upgrade",
@@ -734,17 +745,34 @@ export function buildActionsFromStatus(input: {
734
745
  ? "legacy_storage_migration"
735
746
  : "schema_version_upgrade",
736
747
  category: "schema",
737
- state: configStatus.status === "newer" ? "blocked" : "ready",
738
- safety: configStatus.status === "newer" ? "operator" : "automatic",
739
- invocation: { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
748
+ state: operatorOnly ? "blocked" : "ready",
749
+ safety: operatorOnly ? "operator" : "automatic",
750
+ invocation: legacyStorageBlocked
751
+ ? {
752
+ kind: "review",
753
+ instruction: `The legacy .kb/config.json still names knowledge files outside .kb/ and Kibi cannot move them: ${legacyStorage?.blockers.join(" ")} Keep one copy of each conflicting file (the .kb/ one is what Kibi compiles), remove or git-rm the legacy copy, then run 'kibi migrate --yes' to retire .kb/config.json.`,
754
+ }
755
+ : { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
740
756
  affectedFiles: [
741
757
  ".kb/manifest.json",
742
758
  ".kb/migrations",
743
759
  ".kb/config.json",
760
+ ...(legacyStorage?.moves.map((move) => move.from) ?? []),
744
761
  ],
745
- evidence: { configStatus },
762
+ evidence: {
763
+ configStatus,
764
+ ...(legacyStorage === null
765
+ ? {}
766
+ : {
767
+ legacyStorage: {
768
+ moves: legacyStorage.moves,
769
+ blockers: legacyStorage.blockers,
770
+ legacyConfig: legacyStorage.legacyConfig,
771
+ },
772
+ }),
773
+ },
746
774
  dependsOn: storeState === "missing" ? ["branch-store-ensure"] : [],
747
- autoApplicable: configStatus.status !== "newer",
775
+ autoApplicable: !operatorOnly,
748
776
  }),
749
777
  );
750
778
  }
@@ -769,12 +797,16 @@ export function buildActionsFromStatus(input: {
769
797
  typeof store?.path === "string" ? store.path : ".kb/branches",
770
798
  ],
771
799
  evidence: { reason: uncompiled },
800
+ // A blocked schema step waits on an operator; the compile still runs
801
+ // from the .kb/ sources Kibi already reads.
772
802
  dependsOn: actions
773
- .map((action) => action.id)
774
803
  .filter(
775
- (id) =>
776
- id === "branch-store-ensure" || id === "schema-config-upgrade",
777
- ),
804
+ (action) =>
805
+ action.state === "ready" &&
806
+ (action.id === "branch-store-ensure" ||
807
+ action.id === "schema-config-upgrade"),
808
+ )
809
+ .map((action) => action.id),
778
810
  postconditions: [{ branchStore: "compiled" }],
779
811
  autoApplicable: true,
780
812
  }),
@@ -19,22 +19,13 @@ export const ENTITY_TYPES = [
19
19
  "fact",
20
20
  ] as const;
21
21
 
22
- // An observation or meta fact may quote a claim in claim_text alone: it is a
23
- // non-grounding review note, so it does not claim the clause's key.
22
+ // A claim_key names the clause in claim_text, so it never travels alone. The
23
+ // reverse is open: Kibi derives a missing claim_key from claim_text on a
24
+ // grounding fact, and an observation or meta fact quotes a claim without one.
25
+ // implements REQ-kibi-review-observation-claim-text-v2
24
26
  const CLAIM_PROVENANCE_CONDITIONAL = JSON.parse(`{
25
- "if": {
26
- "anyOf": [
27
- { "required": ["claim_key"] },
28
- {
29
- "required": ["claim_text"],
30
- "not": {
31
- "properties": { "fact_kind": { "enum": ["observation", "meta"] } },
32
- "required": ["fact_kind"]
33
- }
34
- }
35
- ]
36
- },
37
- "then": { "required": ["claim_key", "claim_text"] }
27
+ "if": { "required": ["claim_key"] },
28
+ "then": { "required": ["claim_text"] }
38
29
  }`) as Record<string, unknown>;
39
30
 
40
31
  export const ENTITY_PROPERTIES_SCHEMA = {
@@ -293,12 +284,12 @@ export const ENTITY_PROPERTIES_SCHEMA = {
293
284
  type: "string",
294
285
  pattern: "^CLAIM-[A-F0-9]{16}$",
295
286
  description:
296
- "Stable semantic-advisor key for the atomic prose clause grounded by this fact.",
287
+ "Stable key of the atomic prose clause grounded by this fact, derived from claim_text. Optional: when omitted, Kibi derives it; when sent, it must equal the derived key.",
297
288
  },
298
289
  claim_text: {
299
290
  type: "string",
300
291
  description:
301
- "Exact atomic requirement clause represented by this fact, retained for human audit. Requires claim_key, except on an observation or meta fact, which may quote the clause it is about without claim_key.",
292
+ "Exact atomic requirement clause represented by this fact, retained for human audit. On a grounding fact Kibi derives claim_key from it; an observation or meta fact quotes the clause it is about without a key.",
302
293
  },
303
294
  predicate_name: {
304
295
  type: "string",
@@ -42,19 +42,8 @@ type VerificationPerspective = "internal" | "consumer";
42
42
 
43
43
  const factConditionals = JSON.parse(`[
44
44
  {
45
- "if": {
46
- "anyOf": [
47
- { "required": ["claim_key"] },
48
- {
49
- "required": ["claim_text"],
50
- "not": {
51
- "properties": { "fact_kind": { "enum": ["observation", "meta"] } },
52
- "required": ["fact_kind"]
53
- }
54
- }
55
- ]
56
- },
57
- "then": { "required": ["claim_key", "claim_text"] }
45
+ "if": { "required": ["claim_key"] },
46
+ "then": { "required": ["claim_text"] }
58
47
  },
59
48
  {
60
49
  "if": {
@@ -2,7 +2,7 @@
2
2
  id: kibi-usage
3
3
  name: Kibi Usage
4
4
  description: Use Kibi's source-first, exact-Git, migration-aware, proof-aware operations safely across MCP or the trusted local CLI, including partial completion repair.
5
- version: 2.15.2
5
+ version: 2.15.3
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -369,6 +369,8 @@ For each relational clause, call `kb_model` with `mode: "predicates"`, that clau
369
369
  reviewed `schemaId`. If `binding_status` is `incomplete`, supply
370
370
  `argumentBindings` and retry. Persist `fact_kind: predicate` with the same
371
371
  `claim_key` / `claim_text`, then link `REQ -> fact` with `requires_predicate`.
372
+ `claim_key` is derived from `claim_text`, so a ground fact may send the exact
373
+ clause alone and Kibi fills the key in; a sent key must equal the derived one.
372
374
  Use `kb_model` with `mode: "requirement"` for strict scalar clauses. Use
373
375
  `fact_kind: observation` only for a true ontology gap. The manifest is not
374
376
  grounding: run `logic-coverage` so each key binds to one ground fact.
@@ -6,7 +6,7 @@ Requirement prose remains the human-readable source. Facts add queryable semanti
6
6
 
7
7
  Logical coverage is clause-based, not entity-based. Give `kb_model` (`mode: "analyze"`) the complete requirement body and verify that its `clauses` list contains every atomic obligation. Supply the `clauses` input yourself when automatic splitting would combine or omit obligations. For every normative clause:
8
8
 
9
- - preserve the returned stable key as `claim_key` and the exact clause as `claim_text` on its ground fact;
9
+ - put the exact clause as `claim_text` on its ground fact, with the returned stable key as `claim_key` or none (Kibi derives a missing key; a sent key must match);
10
10
  - add the key to the exact current `logic_claims` set, removing only stale keys whose propositions no longer exist in the source;
11
11
  - link it through exactly one `requires_property` for `property_value`, one `requires_predicate` for `predicate`, or one `requires_rule` for a safe `rule` fact;
12
12
  - leave ambiguity and ontology gaps visibly unresolved—observations do not satisfy `logic-coverage`.
@@ -126,8 +126,8 @@ diagnostics (`symbol_semantic_review_needed`).
126
126
  `requires_predicate`.
127
127
  3. Scalar placement/alignment/order clauses: `kb_model` (`mode: "requirement"`), apply the strict
128
128
  subject/property plan and `constrains` / `requires_property`.
129
- 4. Preserve `claim_key` / `claim_text`; merge every key into the requirement
130
- `logic_claims` manifest.
129
+ 4. Preserve `claim_key` / `claim_text` (a missing key is derived from the
130
+ text); merge every key into the requirement `logic_claims` manifest.
131
131
  5. `kb_upsert` with `dryRun: true`, create endpoints first, then sequential `kb_upsert`.
132
132
  6. `kb_check` with `logic-coverage`, `predicate-verifiability`, `domain-contradictions`,
133
133
  then a final unfiltered `kb_check`.
@@ -203,7 +203,7 @@ Optional per-project workflow for recording what the screen should look like. No
203
203
  2. Run `kb_model` with `mode: "analyze"` on the description; audit or supply `clauses`.
204
204
  3. For relational layout clauses ("X must remain visually aligned with Y"), call `kb_model` with `mode: "predicates"`, apply the returned `fact_kind: predicate` plan with `predicate_name: visual_layout_rule` and `requires_predicate`.
205
205
  4. For scalar placement, alignment, and ordering clauses, call `kb_model` with `mode: "requirement"` and apply strict `fact_kind: subject` / `fact_kind: property_value` facts linked with `constrains` / `requires_property`. Model header order as indexed property keys (`nav_order_1`, `nav_order_2`, ...) against one subject region.
206
- 5. Preserve `claim_key` / `claim_text` on every ground fact and merge every key into the requirement `logic_claims` manifest.
206
+ 5. Preserve `claim_key` / `claim_text` on every ground fact (a missing `claim_key` is derived from `claim_text`) and merge every key into the requirement `logic_claims` manifest.
207
207
  6. Model UI components as `symbol` entities with `sourceFile` and `symbol_role: behavioral`, linked `implements` to the requirement.
208
208
  7. `kb_upsert` with `dryRun: true`, create endpoints first, then sequential `kb_upsert`. Run `kb_check` with `logic-coverage`, `predicate-verifiability`, and `domain-contradictions`, then a final unfiltered `kb_check`.
209
209
 
@@ -1675,35 +1675,12 @@
1675
1675
  },
1676
1676
  {
1677
1677
  "if": {
1678
- "anyOf": [
1679
- {
1680
- "required": [
1681
- "claim_key"
1682
- ]
1683
- },
1684
- {
1685
- "required": [
1686
- "claim_text"
1687
- ],
1688
- "not": {
1689
- "properties": {
1690
- "fact_kind": {
1691
- "enum": [
1692
- "observation",
1693
- "meta"
1694
- ]
1695
- }
1696
- },
1697
- "required": [
1698
- "fact_kind"
1699
- ]
1700
- }
1701
- }
1678
+ "required": [
1679
+ "claim_key"
1702
1680
  ]
1703
1681
  },
1704
1682
  "then": {
1705
1683
  "required": [
1706
- "claim_key",
1707
1684
  "claim_text"
1708
1685
  ]
1709
1686
  }