kibi-cli 2.16.0 → 2.18.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 (83) hide show
  1. package/dist/cli-protocol.d.ts.map +1 -1
  2. package/dist/cli-protocol.js +13 -0
  3. package/dist/cli-register-proof.d.ts +6 -0
  4. package/dist/cli-register-proof.d.ts.map +1 -1
  5. package/dist/cli-register-proof.js +46 -2
  6. package/dist/commands/doctor.d.ts.map +1 -1
  7. package/dist/commands/doctor.js +9 -3
  8. package/dist/commands/sync/untracked-targets.d.ts.map +1 -1
  9. package/dist/commands/sync/untracked-targets.js +39 -9
  10. package/dist/commands/sync.d.ts.map +1 -1
  11. package/dist/commands/sync.js +26 -5
  12. package/dist/engine.d.ts +4 -0
  13. package/dist/engine.d.ts.map +1 -1
  14. package/dist/engine.js +40 -10
  15. package/dist/operations/modeling/predicate-applicability.d.ts.map +1 -1
  16. package/dist/operations/modeling/predicate-applicability.js +12 -3
  17. package/dist/operations/modeling/predicate-catalog-4.d.ts.map +1 -1
  18. package/dist/operations/modeling/predicate-catalog-4.js +4 -0
  19. package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
  20. package/dist/operations/modeling/predicate-loader.js +3 -0
  21. package/dist/operations/modeling/predicate-score-3.js +1 -1
  22. package/dist/operations/modeling/predicate-types.d.ts +5 -0
  23. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  24. package/dist/operations/modeling/predicate-utils.d.ts.map +1 -1
  25. package/dist/operations/modeling/predicate-utils.js +2 -3
  26. package/dist/operations/mutation/source-authoring.d.ts +9 -0
  27. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  28. package/dist/operations/mutation/source-authoring.js +38 -2
  29. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  30. package/dist/operations/planning/apply-plan.js +33 -8
  31. package/dist/operations/planning/migration-refusal.d.ts +14 -0
  32. package/dist/operations/planning/migration-refusal.d.ts.map +1 -0
  33. package/dist/operations/planning/migration-refusal.js +17 -0
  34. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  35. package/dist/operations/semantic-advisor/clauses.js +7 -1
  36. package/dist/operations/semantic-advisor/shared.d.ts +7 -0
  37. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  38. package/dist/operations/semantic-advisor/shared.js +22 -3
  39. package/dist/prolog/store-lock.d.ts +22 -0
  40. package/dist/prolog/store-lock.d.ts.map +1 -1
  41. package/dist/prolog/store-lock.js +45 -1
  42. package/dist/prolog.d.ts +7 -1
  43. package/dist/prolog.d.ts.map +1 -1
  44. package/dist/prolog.js +21 -3
  45. package/dist/proof/inspect.d.ts +9 -0
  46. package/dist/proof/inspect.d.ts.map +1 -1
  47. package/dist/proof/inspect.js +10 -0
  48. package/dist/proof/integration-plan.d.ts +2 -1
  49. package/dist/proof/integration-plan.d.ts.map +1 -1
  50. package/dist/proof/integration-plan.js +30 -13
  51. package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
  52. package/dist/public/impact/coverage-depth-quality.js +29 -1
  53. package/dist/public/operations/contracts.d.ts.map +1 -1
  54. package/dist/public/operations/contracts.js +3 -0
  55. package/dist/public/operations/discovery-executors.d.ts +14 -1
  56. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  57. package/dist/public/operations/discovery-executors.js +62 -12
  58. package/dist/public/operations/migration-plan.d.ts +2 -0
  59. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  60. package/dist/public/operations/migration-plan.js +31 -0
  61. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  62. package/dist/public/operations/result-envelope.js +23 -3
  63. package/dist/public/operations/source-relationship-parity.d.ts.map +1 -1
  64. package/dist/public/operations/source-relationship-parity.js +55 -1
  65. package/dist/public/skills/kibi-usage/SKILL.md +19 -4
  66. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +3 -3
  67. package/dist/public/skills/kibi-usage/resources/proof.md +44 -3
  68. package/dist/utils/branch-store.d.ts +8 -0
  69. package/dist/utils/branch-store.d.ts.map +1 -1
  70. package/dist/utils/branch-store.js +27 -1
  71. package/dist/utils/content-freshness.d.ts +13 -0
  72. package/dist/utils/content-freshness.d.ts.map +1 -0
  73. package/dist/utils/content-freshness.js +161 -0
  74. package/package.json +2 -2
  75. package/src/public/impact/coverage-depth-quality.ts +46 -1
  76. package/src/public/operations/contracts.ts +3 -0
  77. package/src/public/operations/discovery-executors.ts +89 -11
  78. package/src/public/operations/migration-plan.ts +44 -0
  79. package/src/public/operations/result-envelope.ts +31 -3
  80. package/src/public/operations/source-relationship-parity.ts +60 -3
  81. package/src/public/skills/kibi-usage/SKILL.md +19 -4
  82. package/src/public/skills/kibi-usage/resources/fact-lanes.md +3 -3
  83. package/src/public/skills/kibi-usage/resources/proof.md +44 -3
@@ -1 +1 @@
1
- {"version":3,"file":"cli-protocol.d.ts","sourceRoot":"","sources":["../src/cli-protocol.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMpE,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG;IAC1C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CACpD,CAAC;AAGF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,iBAAS,WAAW,CAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAAG,cAAc,EAClC,IAAI,CAAC,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,EACD,SAAS,UAAO,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,iBAAiB,CAwBnB;AA4BD;;;;GAIG;AAEH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,EACvC,KAAK,EAAE,OAAO,GACb,iBAAiB,CAWnB;AAGD,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAwE5B"}
1
+ {"version":3,"file":"cli-protocol.d.ts","sourceRoot":"","sources":["../src/cli-protocol.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMpE,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG;IAC1C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CACpD,CAAC;AAGF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,iBAAS,WAAW,CAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAAG,cAAc,EAClC,IAAI,CAAC,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,EACD,SAAS,UAAO,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,iBAAiB,CAwBnB;AA4BD;;;;GAIG;AAEH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,EACvC,KAAK,EAAE,OAAO,GACb,iBAAiB,CAWnB;AAGD,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAqF5B"}
@@ -78,6 +78,19 @@ export async function executeOperation(catalogName, input, context) {
78
78
  if (!protocolValid(spec, envelope)) {
79
79
  return errorResult(catalogName, new OperationError("PROTOCOL_VALIDATION_FAILED", "Operation produced a result that does not satisfy its generated output contract."), spec);
80
80
  }
81
+ // A result the operation itself reports as an error (a rejected
82
+ // bootstrap, a refused migration plan) exits non-zero like any other.
83
+ if (envelope.status === "error") {
84
+ return {
85
+ exitCode: 1,
86
+ stdout: `${JSON.stringify(envelope)}\n`,
87
+ ...(envelope.error
88
+ ? {
89
+ stderr: `Error [${envelope.error.code}]: ${envelope.error.message}\n`,
90
+ }
91
+ : {}),
92
+ };
93
+ }
81
94
  return { exitCode: 0, stdout: `${JSON.stringify(envelope)}\n` };
82
95
  }
83
96
  catch (error) {
@@ -1,3 +1,9 @@
1
1
  import type { Command } from "commander";
2
2
  export declare function registerProofCommand(program: Command): void;
3
+ /**
4
+ * `--command` for `kibi proof inspect`: a JSON array of argv strings, or
5
+ * space-separated words (no shell quoting; Kibi runs integrations with
6
+ * `shell: false`).
7
+ */
8
+ export declare function parseCommandOption(value: string): readonly string[];
3
9
  //# sourceMappingURL=cli-register-proof.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-register-proof.d.ts","sourceRoot":"","sources":["../src/cli-register-proof.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6L3D"}
1
+ {"version":3,"file":"cli-register-proof.d.ts","sourceRoot":"","sources":["../src/cli-register-proof.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2M3D;AAED;;;;GAIG;AAEH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAwBnE"}
@@ -41,9 +41,16 @@ export function registerProofCommand(program) {
41
41
  .command("inspect")
42
42
  .description("Detect test infrastructure, propose a proof integration and return the reviewed plan that writes .kb/proof/integrations.json")
43
43
  .option("--update <id>", "Plan adding or replacing this integration in an existing .kb/proof/integrations.json")
44
+ .option("--command <command>", 'Command the proposed integration runs instead of the detected one: space-separated words, or a JSON array of argv strings (e.g. \'["npx","vitest","run","tests/e2e"]\')')
44
45
  .option("--json", "Emit structured JSON", false)
45
46
  .action(withExitCode(async (options) => {
46
- const result = await (await import("./proof/inspect.js")).inspectProofEnvironment(process.cwd(), options.update === undefined ? {} : { update: options.update });
47
+ const command = options.command === undefined
48
+ ? undefined
49
+ : parseCommandOption(options.command);
50
+ const result = await (await import("./proof/inspect.js")).inspectProofEnvironment(process.cwd(), {
51
+ ...(options.update === undefined ? {} : { update: options.update }),
52
+ ...(command === undefined ? {} : { command }),
53
+ });
47
54
  if (options.json) {
48
55
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
49
56
  return undefined;
@@ -109,6 +116,33 @@ export function registerProofCommand(program) {
109
116
  });
110
117
  }));
111
118
  }
119
+ /**
120
+ * `--command` for `kibi proof inspect`: a JSON array of argv strings, or
121
+ * space-separated words (no shell quoting; Kibi runs integrations with
122
+ * `shell: false`).
123
+ */
124
+ // implements REQ-kibi-verification-evidence-contract
125
+ export function parseCommandOption(value) {
126
+ const trimmed = value.trim();
127
+ if (trimmed.startsWith("[")) {
128
+ let parsed;
129
+ try {
130
+ parsed = JSON.parse(trimmed);
131
+ }
132
+ catch {
133
+ throw new Error("--command must be a JSON array of argv strings or space-separated words.");
134
+ }
135
+ if (!Array.isArray(parsed) ||
136
+ parsed.length === 0 ||
137
+ !parsed.every((entry) => typeof entry === "string" && entry !== ""))
138
+ throw new Error("--command must be a JSON array of non-empty argv strings.");
139
+ return parsed;
140
+ }
141
+ const words = trimmed.split(/\s+/).filter((word) => word !== "");
142
+ if (words.length === 0)
143
+ throw new Error("--command must not be empty.");
144
+ return words;
145
+ }
112
146
  function renderInspection(result) {
113
147
  const inspection = result;
114
148
  const lines = ["Proof environment", ""];
@@ -128,7 +162,15 @@ function renderInspection(result) {
128
162
  if (inspection.ciWorkflows.length > 0)
129
163
  lines.push(`CI workflows: ${inspection.ciWorkflows.join(", ")}`);
130
164
  lines.push("");
131
- lines.push(`Current integration: ${inspection.currentIntegration ?? "none"}`);
165
+ const configured = inspection.currentIntegrations ?? [];
166
+ if (configured.length === 0) {
167
+ lines.push(`Current integration: ${inspection.currentIntegration ?? "none"}`);
168
+ }
169
+ else {
170
+ lines.push("Current integrations:");
171
+ for (const entry of configured)
172
+ lines.push(` ${entry.id} (${entry.producer}: ${entry.command.join(" ")})`);
173
+ }
132
174
  lines.push("");
133
175
  lines.push(`Recommendation: ${inspection.recommendation}`);
134
176
  if (inspection.missing.length > 0) {
@@ -145,6 +187,8 @@ function renderInspection(result) {
145
187
  if (inspection.integrationPlan) {
146
188
  const plan = inspection.integrationPlan;
147
189
  lines.push(`Integration plan: ${plan.planHash.slice(0, 12)} (actions: ${plan.actions.map((action) => action.id).join(", ")}); rerun with --json for the plan to pass to kb_apply_plan.`);
190
+ if (inspection.integrationPlanReason)
191
+ lines.push(inspection.integrationPlanReason);
148
192
  }
149
193
  else if (inspection.integrationPlanReason) {
150
194
  lines.push("");
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AA2FA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAmH/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AA4FA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAmH/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
@@ -26,7 +26,7 @@ import { describeConfiguredCapabilityPlugins, readProjectKibiConfig, } from "../
26
26
  import { SwiplResolutionError, inspectSwiplBundle, probeRequiredLibraries, resolveSwipl, } from "../prolog/swipl-resolver.js";
27
27
  import { buildMigrationPlan, migrationAction, } from "../public/operations/migration-plan.js";
28
28
  import { resolveBranchAttachment, resolveReadBranchAttachment, } from "../utils/branch-resolver.js";
29
- import { branchStoreCompilation, inspectBranchStore, uncompiledBranchStoreReason, } from "../utils/branch-store.js";
29
+ import { branchStoreCompilation, inspectBranchStore, storeLockTakeoverReason, uncompiledBranchStoreReason, } from "../utils/branch-store.js";
30
30
  import { resolveGitRepository, } from "../utils/git-repository-context.js";
31
31
  import { readKbManifestStatus } from "../utils/kb-manifest.js";
32
32
  import { hasManagedHooks, outdatedManagedHooks } from "./init-helpers.js";
@@ -692,11 +692,17 @@ function checkBranchStore() {
692
692
  };
693
693
  }
694
694
  const compilation = branchStoreCompilation(store);
695
+ // implements REQ-core-journaled-engine-persistence
696
+ const takeover = storeLockTakeoverReason(store.path);
695
697
  if (compilation.compiled) {
696
698
  return {
697
699
  passed: true,
698
- message: `Compiled for ${branch}${compilation.generation ? ` (${compilation.generation})` : ""}`,
699
- details: { ...details, generation: compilation.generation },
700
+ message: `Compiled for ${branch}${compilation.generation ? ` (${compilation.generation})` : ""}${takeover ? `. ${String(takeover.detail)}` : ""}`,
701
+ details: {
702
+ ...details,
703
+ generation: compilation.generation,
704
+ ...(takeover ? { lockTakeover: takeover } : {}),
705
+ },
700
706
  };
701
707
  }
702
708
  const reason = uncompiledBranchStoreReason(workspaceRoot, store, branch);
@@ -1 +1 @@
1
- {"version":3,"file":"untracked-targets.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/untracked-targets.ts"],"names":[],"mappings":"AAsBA,UAAU,oBAAoB;IAC5B,YAAY,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAC5D,MAAM,CAAC;IACZ,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1D;AAQD;;;;;;;;;;;GAWG;AAEH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,IAAI,GAAE,OAAO,CAAC,oBAAoB,CAAM,GACvC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiDrB"}
1
+ {"version":3,"file":"untracked-targets.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/untracked-targets.ts"],"names":[],"mappings":"AAyBA,UAAU,oBAAoB;IAC5B,YAAY,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAC5D,MAAM,CAAC;IACZ,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1D;AAQD;;;;;;;;;;;GAWG;AAEH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,IAAI,GAAE,OAAO,CAAC,oBAAoB,CAAM,GACvC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAsDrB"}
@@ -16,8 +16,11 @@
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
18
  import { execFileSync } from "node:child_process";
19
+ import { createHash } from "node:crypto";
19
20
  import { existsSync, readFileSync } from "node:fs";
20
21
  import * as path from "node:path";
22
+ import { load as parseYAML } from "js-yaml";
23
+ import { isSymbolsManifestPath } from "../../utils/kb-paths.js";
21
24
  const defaultDeps = {
22
25
  execFileSync: (file, args, options) => execFileSync(file, args, options),
23
26
  existsSync,
@@ -62,11 +65,20 @@ export function findUntrackedDocumentMatches(workspaceRoot, missingIds, deps = {
62
65
  for (const relative of untracked) {
63
66
  if (remaining.size === 0)
64
67
  break;
65
- if (!relative.endsWith(".md"))
68
+ const normalized = relative.replaceAll("\\", "/");
69
+ const manifest = isSymbolsManifestPath(normalized);
70
+ if (!normalized.endsWith(".md") && !manifest)
66
71
  continue;
67
- const absolute = path.resolve(workspaceRoot, relative.replaceAll("\\", "/"));
72
+ const absolute = path.resolve(workspaceRoot, normalized);
68
73
  if (!resolved.existsSync(absolute))
69
74
  continue;
75
+ const workspaceRelative = path
76
+ .relative(workspaceRoot, absolute)
77
+ .replaceAll("\\", "/");
78
+ // A pending-source receipt makes an untracked file visible to sync, so
79
+ // the file cannot be why an id is missing.
80
+ if (existsSync(pendingReceiptFor(workspaceRoot, workspaceRelative)))
81
+ continue;
70
82
  let content;
71
83
  try {
72
84
  content = resolved.readFileSync(absolute, "utf8");
@@ -74,17 +86,35 @@ export function findUntrackedDocumentMatches(workspaceRoot, missingIds, deps = {
74
86
  catch {
75
87
  continue;
76
88
  }
77
- const id = frontmatterId(content);
78
- if (id !== null && remaining.has(id)) {
79
- const workspaceRelative = path
80
- .relative(workspaceRoot, absolute)
81
- .replaceAll("\\", "/");
82
- matches.set(id, workspaceRelative);
83
- remaining.delete(id);
89
+ const ids = manifest ? manifestIds(content) : [frontmatterId(content)];
90
+ for (const id of ids) {
91
+ if (id !== null && remaining.has(id)) {
92
+ matches.set(id, workspaceRelative);
93
+ remaining.delete(id);
94
+ }
84
95
  }
85
96
  }
86
97
  return matches;
87
98
  }
99
+ /** Where kb_upsert records the pending-source receipt of `relative`. */
100
+ function pendingReceiptFor(workspaceRoot, relative) {
101
+ return path.join(workspaceRoot, ".kb", "recovery", "pending-sources", `${createHash("sha256").update(relative).digest("hex")}.json`);
102
+ }
103
+ /** Symbol ids declared by an untracked symbols manifest. */
104
+ function manifestIds(content) {
105
+ try {
106
+ const parsed = parseYAML(content);
107
+ const symbols = Array.isArray(parsed?.symbols) ? parsed.symbols : [];
108
+ return symbols.flatMap((symbol) => symbol !== null &&
109
+ typeof symbol === "object" &&
110
+ typeof symbol.id === "string"
111
+ ? [symbol.id]
112
+ : []);
113
+ }
114
+ catch {
115
+ return [];
116
+ }
117
+ }
88
118
  /**
89
119
  * Extract `id:` from a markdown document's YAML frontmatter (the first
90
120
  * `---` block). Documents whose id never appears in the frontmatter region
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA6BjE,OAAO,EAEL,yBAAyB,EAE1B,MAAM,gDAAgD,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,6BAA6B,CAAC;AAyBrC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AA2BxE,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAmCD,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EACxB,4BAA4B,UAAQ,EACpC,4BAA4B,GAAE,4BAA4B,EAAO,GAChE,MAAM,EAAE,CAuGV;AAqDD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3E,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;IAC/D,yBAAyB,CAAC,EAAE,OAAO,yBAAyB,CAAC;CAC9D;AA6DD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvE;AAGD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,IAAI,GAChB,IAAI,CAMN;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,IAAI,CAIN;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAMP;AAED,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,UAAU,EAAE,EACzB,oBAAoB,EAAE,OAAO,EAC7B,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,IAAI,CAUN;AAGD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,EACN,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CA0pCrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA6BjE,OAAO,EAEL,yBAAyB,EAE1B,MAAM,gDAAgD,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,6BAA6B,CAAC;AAyBrC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AA4BxE,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAmCD,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EACxB,4BAA4B,UAAQ,EACpC,4BAA4B,GAAE,4BAA4B,EAAO,GAChE,MAAM,EAAE,CAuGV;AAqDD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3E,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;IAC/D,yBAAyB,CAAC,EAAE,OAAO,yBAAyB,CAAC;CAC9D;AA+FD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvE;AAGD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,IAAI,GAChB,IAAI,CAMN;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,IAAI,CAIN;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAMP;AAED,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,UAAU,EAAE,EACzB,oBAAoB,EAAE,OAAO,EAC7B,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,IAAI,CAUN;AAGD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,EACN,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CAipCrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -36,6 +36,7 @@ import { normalizeExtractionSources, processExtractions, } from "./sync/extracti
36
36
  import { refreshManifestCoordinates } from "./sync/manifest.js";
37
37
  import { persistEntities, persistRelationships, retractEntitiesById, retractEntitiesForSources, retractEntityRelationshipsById, retractRelationships, } from "./sync/persistence.js";
38
38
  import { atomicPublish, atomicPublishGeneration, cleanupStaging, createUniqueStagingPath, prepareStagingEnvironment, } from "./sync/staging.js";
39
+ import { findUntrackedDocumentMatches } from "./sync/untracked-targets.js";
39
40
  // Manual deletion of a written-but-unstaged source leaves a recovery receipt
40
41
  // behind; sync refuses to guess, so the error must name the way out.
41
42
  const PENDING_SOURCE_RECOVERY_HINT = " If the file was deleted on purpose, run 'kibi branch recover --apply' to rebuild the branch KB from the sources that remain.";
@@ -204,6 +205,29 @@ async function checkpointNoopSync(workspaceRoot, branch) {
204
205
  function compilerCacheHasEntityDelta(cache) {
205
206
  return (cache.entityHashes !== undefined && cache.sourceEntityIds !== undefined);
206
207
  }
208
+ /**
209
+ * Name every dangling relationship and its missing endpoint, and say when an
210
+ * endpoint is declared in a source sync cannot see (untracked by Git and
211
+ * without a pending-source receipt): staging that file is the fix.
212
+ */
213
+ // implements REQ-core-persistence
214
+ function reportDanglingRelationships(workspaceRoot, validationErrors) {
215
+ console.warn(`Warning: ${validationErrors.length} dangling relationship(s) found`);
216
+ const missing = new Set();
217
+ for (const { relationship, error } of validationErrors) {
218
+ const endpoint = error === "missing_from" ? relationship.from : relationship.to;
219
+ missing.add(endpoint);
220
+ console.warn(` - ${error}: ${relationship.type} ${relationship.from} -> ${relationship.to} (${endpoint} is not in this branch's sources)`);
221
+ }
222
+ const untracked = findUntrackedDocumentMatches(workspaceRoot, [...missing]);
223
+ const byFile = new Map();
224
+ for (const [id, file] of untracked) {
225
+ byFile.set(file, [...(byFile.get(file) ?? []), id]);
226
+ }
227
+ for (const [file, ids] of byFile) {
228
+ console.warn(` Note: ${ids.sort().join(", ")} ${ids.length === 1 ? "is" : "are"} declared in ${file}, which Git does not track and no pending-source receipt covers, so sync ignores it. Run \`git add ${file}\` (staging is enough) or rewrite the entity with kb_upsert, then sync again.`);
229
+ }
230
+ }
207
231
  function compilerCacheIsFresh(cache, workspaceRoot, sourceFiles, nowMs) {
208
232
  const sourceKeys = sourceFiles.map((file) => toCacheKey(workspaceRoot, file));
209
233
  if (Object.keys(cache.hashes).some((key) => !sourceKeys.includes(key))) {
@@ -852,7 +876,7 @@ export async function syncCommand(options = {}, runtime = {}) {
852
876
  ? []
853
877
  : validateRelationships(allRelationships, entityIds);
854
878
  if (validationErrors.length > 0) {
855
- console.warn(`Warning: ${validationErrors.length} dangling relationship(s) found`);
879
+ reportDanglingRelationships(workspaceRoot, validationErrors);
856
880
  }
857
881
  const danglingKeys = new Set(validationErrors.map(({ relationship }) => `${relationship.type}|${relationship.from}|${relationship.to}`));
858
882
  const shardDeltaByKey = new Map();
@@ -973,10 +997,7 @@ export async function syncCommand(options = {}, runtime = {}) {
973
997
  const { entityCount, kbModified: entitiesModified } = await persistEntities(prolog, results, entityIds);
974
998
  const validationErrors = validateRelationships(allRelationships, entityIds);
975
999
  if (validationErrors.length > 0) {
976
- console.warn(`Warning: ${validationErrors.length} dangling relationship(s) found`);
977
- for (const { relationship, error } of validationErrors) {
978
- console.warn(` - ${error}: ${relationship.type} ${relationship.from} -> ${relationship.to}`);
979
- }
1000
+ reportDanglingRelationships(workspaceRoot, validationErrors);
980
1001
  }
981
1002
  const danglingKeys = new Set(validationErrors.map(({ relationship: r }) => `${r.type}|${r.from}|${r.to}`));
982
1003
  const validRelationships = allRelationships.filter((r) => !danglingKeys.has(`${r.type}|${r.from}|${r.to}`));
package/dist/engine.d.ts CHANGED
@@ -8,6 +8,10 @@ export { EngineQueryLimitError, QUERY_LIMIT_EXCEEDED_CODE, queryLimitExceededOf,
8
8
  export type { EngineLimitExceeded, EngineQueryLimits, } from "./engine-limits.js";
9
9
  export declare const ENGINE_PROTOCOL_VERSION = 1;
10
10
  export declare const ENGINE_IDLE_TIMEOUT_MS: number;
11
+ /** Upper bound between two wall-clock idle checks of the engine daemon. */
12
+ export declare const ENGINE_IDLE_CHECK_INTERVAL_MS: number;
13
+ /** How long a stopping daemon waits for SWI to halt on stdin EOF. */
14
+ export declare const ENGINE_PROLOG_EXIT_GRACE_MS = 1000;
11
15
  /**
12
16
  * Package versions this engine build carries (KIBI_PACKAGE_VERSIONS when
13
17
  * set). The client sends them on every request and the daemon reports its
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -34,6 +34,10 @@ const READ_LIMITED_METHODS = new Set([
34
34
  ]);
35
35
  export const ENGINE_PROTOCOL_VERSION = 1;
36
36
  export const ENGINE_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
37
+ /** Upper bound between two wall-clock idle checks of the engine daemon. */
38
+ export const ENGINE_IDLE_CHECK_INTERVAL_MS = 30 * 1000;
39
+ /** How long a stopping daemon waits for SWI to halt on stdin EOF. */
40
+ export const ENGINE_PROLOG_EXIT_GRACE_MS = 1000;
37
41
  /**
38
42
  * Package versions this engine build carries (KIBI_PACKAGE_VERSIONS when
39
43
  * set). The client sends them on every request and the daemon reports its
@@ -1695,7 +1699,12 @@ export async function runEngineDaemon(requestedOptions) {
1695
1699
  writeFileSync(enginePidPath(options.workspaceRoot, options.branch), `${process.pid}\n`, { mode: 0o600 });
1696
1700
  const server = net.createServer();
1697
1701
  let activeClients = 0;
1698
- let idleTimer = null;
1702
+ // implements REQ-core-journaled-engine-persistence
1703
+ // Idle exit compares wall-clock time: a one-shot timer does not advance
1704
+ // while the host (a VM, a laptop) is suspended, so a daemon would outlive
1705
+ // its idle budget by the whole suspension.
1706
+ let lastActivityAt = Date.now();
1707
+ let idleWatch = null;
1699
1708
  let queue = Promise.resolve();
1700
1709
  let idleCompactionQueued = false;
1701
1710
  const queryCache = new Map();
@@ -1783,12 +1792,17 @@ export async function runEngineDaemon(requestedOptions) {
1783
1792
  idleCompactionQueued = false;
1784
1793
  });
1785
1794
  }
1786
- if (idleTimer)
1787
- clearTimeout(idleTimer);
1788
- idleTimer = setTimeout(() => {
1789
- if (activeClients === 0)
1795
+ lastActivityAt = Date.now();
1796
+ if (idleWatch)
1797
+ return;
1798
+ const idleMs = engineIdleTimeoutMs();
1799
+ idleWatch = setInterval(() => {
1800
+ if (!shuttingDown &&
1801
+ activeClients === 0 &&
1802
+ Date.now() - lastActivityAt >= idleMs)
1790
1803
  void shutdown();
1791
- }, engineIdleTimeoutMs());
1804
+ }, Math.min(idleMs, ENGINE_IDLE_CHECK_INTERVAL_MS));
1805
+ idleWatch.unref();
1792
1806
  };
1793
1807
  const handle = async (request, cancelledRequests) => {
1794
1808
  if (request.protocolVersion !== ENGINE_PROTOCOL_VERSION) {
@@ -2121,8 +2135,8 @@ export async function runEngineDaemon(requestedOptions) {
2121
2135
  shuttingDown = true;
2122
2136
  process.off("SIGTERM", requestSignalShutdown);
2123
2137
  process.off("SIGINT", requestSignalShutdown);
2124
- if (idleTimer)
2125
- clearTimeout(idleTimer);
2138
+ if (idleWatch)
2139
+ clearInterval(idleWatch);
2126
2140
  clearInterval(workspaceWatchdog);
2127
2141
  // Stop accepting clients before the first asynchronous durability step.
2128
2142
  // Keep the PID published until Prolog releases the branch-store lock.
@@ -2131,6 +2145,7 @@ export async function runEngineDaemon(requestedOptions) {
2131
2145
  const saved = session.needsRecycle()
2132
2146
  ? null
2133
2147
  : await prolog.query("kb_save").catch(() => null);
2148
+ let detached = false;
2134
2149
  if (saved?.success) {
2135
2150
  try {
2136
2151
  fsyncJournaledBranchStore(branchPath);
@@ -2139,8 +2154,22 @@ export async function runEngineDaemon(requestedOptions) {
2139
2154
  // Shutdown remains best effort. Request-time writes fail closed if
2140
2155
  // their durability barrier cannot complete.
2141
2156
  }
2142
- }
2143
- await prolog.terminate().catch(() => undefined);
2157
+ // implements REQ-core-journaled-engine-persistence
2158
+ // Release the store the way the one-shot path does: kb_detach removes
2159
+ // rdf/lock and the ownership journal. A SIGTERM'd SWI process never
2160
+ // runs its at_halt cleanup, so skipping this left a dead lock behind
2161
+ // on every stop.
2162
+ detached = await prolog
2163
+ .query("kb_detach")
2164
+ .then((result) => result.success)
2165
+ .catch(() => false);
2166
+ }
2167
+ // Once kb_detach released the store, nothing in at_halt is needed and the
2168
+ // child is signalled at once. Otherwise let SWI halt on stdin EOF (running
2169
+ // its at_halt cleanup) for a bounded moment; the wait ends on exit.
2170
+ await prolog
2171
+ .terminate({ graceMs: detached ? 0 : ENGINE_PROLOG_EXIT_GRACE_MS })
2172
+ .catch(() => undefined);
2144
2173
  for (const client of clients)
2145
2174
  client.destroy();
2146
2175
  // A close callback can remain pending on older Node releases when a
@@ -2189,6 +2218,7 @@ export async function runEngineDaemon(requestedOptions) {
2189
2218
  const bytes = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
2190
2219
  buffer = parseFrames(Buffer.concat([buffer, bytes]), (value) => {
2191
2220
  const request = value;
2221
+ lastActivityAt = Date.now();
2192
2222
  if (shuttingDown) {
2193
2223
  writeSocketFrame(socket, {
2194
2224
  id: request.id,
@@ -1 +1 @@
1
- {"version":3,"file":"predicate-applicability.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-applicability.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAqW1C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,MAAM,GACX,qBAAqB,CA2EvB"}
1
+ {"version":3,"file":"predicate-applicability.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-applicability.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,qBAAqB,OAAO,CAAC;AA8W1C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,MAAM,GACX,qBAAqB,CA2EvB"}
@@ -2,7 +2,10 @@ import { usageHintsForSchema, } from "./predicate-ranker.js";
2
2
  export const MIN_APPLICABILITY_SCORE = 0.62;
3
3
  export const STRONG_APPLICABILITY_SCORE = 0.8;
4
4
  export const WEAK_CANDIDATE_MARGIN = 0.06;
5
- const NORMATIVE_OR_VALIDITY_PATTERN = /\b(?:must|shall|should|required|requires?|may\s+only|only\s+.+?\s+(?:may|can)|must\s+not|shall\s+not|cannot|can't|allowed|denied|forbidden|prohibited|invalid|unresolved|reject(?:s|ed|ion)?|fail(?:s|ed|ure)?\s+(?:clearly|explicitly|with)|defaults?\s+to|states?\s+are|owned\s+by|initializes?\s+after|before|unless|when|if|(?:exception|exempt)\s+(?:to|from|when|if|unless))\b/i;
5
+ // A bare permission modal ("coaches can read", "users may export", "are
6
+ // permitted to") states a permission as much as "allowed" does, so it must
7
+ // reach the permission_rule intent rule instead of being rejected here.
8
+ const NORMATIVE_OR_VALIDITY_PATTERN = /\b(?:must|shall|should|required|requires?|may\s+only|only\s+.+?\s+(?:may|can)|(?:can|may)\s+(?:not\s+)?(?:only\s+)?\w+|(?:is|are)\s+(?:not\s+)?(?:allowed|permitted)\s+to|permitted|must\s+not|shall\s+not|cannot|can't|allowed|denied|forbidden|prohibited|invalid|unresolved|reject(?:s|ed|ion)?|fail(?:s|ed|ure)?\s+(?:clearly|explicitly|with)|defaults?\s+to|states?\s+are|owned\s+by|initializes?\s+after|before|unless|when|if|(?:exception|exempt)\s+(?:to|from|when|if|unless))\b/i;
6
9
  function expressesNormativeOrValidityIntent(text) {
7
10
  return /^\s*no\b/i.test(text) || NORMATIVE_OR_VALIDITY_PATTERN.test(text);
8
11
  }
@@ -95,8 +98,14 @@ const INTENT_RULES = {
95
98
  },
96
99
  permission_rule: {
97
100
  allOf: [
98
- [/only|may|can|allowed|denied|forbidden|must\s+not|cannot/i],
99
- [/delete|export|access|read|write|update|remove|manage|permission/i],
101
+ [/only|may|can|allowed|permitted|denied|forbidden|must\s+not|cannot/i],
102
+ [
103
+ /delete|export|access|read|write|update|remove|manage|permission/i,
104
+ // A common action verb counts only right after the permission modal
105
+ // ("must not publish", "may approve"), so a quota such as "uploads
106
+ // must not exceed 10 MB" does not read as a permission.
107
+ /\b(?:may|can|cannot|can't|must\s+(?:not|never)|never|(?:is|are)\s+(?:not\s+)?(?:allowed|permitted|forbidden)\s+to)\s+(?:only\s+)?(?:publish|unpublish|approve|assign|view|see|edit|modify|create|submit|share|invite|upload|download|comment|post|complete|archive|restore|grant|revoke|purchase|cancel|execute|invoke|configure|moderate|ban|join|book|reserve|transfer|close|reopen|merge)\b/i,
108
+ ],
100
109
  ],
101
110
  },
102
111
  resource_constraint: {
@@ -1 +1 @@
1
- {"version":3,"file":"predicate-catalog-4.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-catalog-4.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGrE,eAAO,MAAM,mBAAmB,EAAE,wBAAwB,EAqTzD,CAAC"}
1
+ {"version":3,"file":"predicate-catalog-4.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-catalog-4.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGrE,eAAO,MAAM,mBAAmB,EAAE,wBAAwB,EAyTzD,CAAC"}
@@ -203,10 +203,14 @@ export const PREDICATE_CATALOG_4 = [
203
203
  argument_names: ["actor", "action", "resource", "decision"],
204
204
  argument_types: ["actor", "action", "resource", "decision"],
205
205
  ...closedArguments({ decision: DECISION_VOCABULARY }),
206
+ // One decision per actor, action and resource: an allow and a deny for
207
+ // the same three contradict (kb.pl builtin_decision_predicate/5).
208
+ key_arguments: ["actor", "action", "resource"],
206
209
  keywords: [
207
210
  "may",
208
211
  "can",
209
212
  "allowed",
213
+ "permitted",
210
214
  "denied",
211
215
  "forbidden",
212
216
  "must not",
@@ -1 +1 @@
1
- {"version":3,"file":"predicate-loader.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAK3E,OAAO,KAAK,EACV,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAI9B,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAExE;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CACxE,wBAAwB,EACxB,UAAU,CACX,GAAG;IACF,WAAW,EAAE,mBAAmB,CAAC;CAClC,CA4BA;AAGD,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,sBAAsB,EAAE,OAAO,EAC/B,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAwBrC;AAGD,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,wBAAwB,EAAE,CAwD5B;AAGD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,mBAAmB,GAAG,SAAS,CAOjC;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAQpD"}
1
+ {"version":3,"file":"predicate-loader.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAK3E,OAAO,KAAK,EACV,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAI9B,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAExE;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CACxE,wBAAwB,EACxB,UAAU,CACX,GAAG;IACF,WAAW,EAAE,mBAAmB,CAAC;CAClC,CA6BA;AAGD,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,sBAAsB,EAAE,OAAO,EAC/B,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAwBrC;AAGD,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,wBAAwB,EAAE,CA0D5B;AAGD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,mBAAmB,GAAG,SAAS,CAOjC;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAQpD"}
@@ -23,6 +23,7 @@ export function schemaForCandidate(schema) {
23
23
  ...(schema.argument_aliases
24
24
  ? { argument_aliases: schema.argument_aliases }
25
25
  : {}),
26
+ ...(schema.key_arguments ? { key_arguments: schema.key_arguments } : {}),
26
27
  ...(schema.aliases ? { aliases: schema.aliases } : {}),
27
28
  ...(schema.paraphrase_templates
28
29
  ? { paraphrase_templates: schema.paraphrase_templates }
@@ -64,6 +65,7 @@ export function predicateSchemaFromEntity(entity) {
64
65
  return [];
65
66
  const usageHints = usageHintsFromEntity(entity);
66
67
  const argumentDescriptions = stringArray(entity.argument_descriptions);
68
+ const keyArguments = stringArray(entity.key_arguments);
67
69
  const vocabulary = predicateVocabularyFromEntity(entity);
68
70
  return [
69
71
  {
@@ -93,6 +95,7 @@ export function predicateSchemaFromEntity(entity) {
93
95
  ])),
94
96
  }
95
97
  : {}),
98
+ ...(keyArguments.length > 0 ? { key_arguments: keyArguments } : {}),
96
99
  keywords: [
97
100
  predicateName,
98
101
  ...stringArray(entity.aliases),
@@ -51,7 +51,7 @@ export function scoreExactPredicates3(schema, text) {
51
51
  return 0;
52
52
  }
53
53
  if (schema.predicate_name === "permission_rule") {
54
- if (/^(?:only\s+)?[a-z][a-z\s_-]*\s+(?:may|can|is\s+allowed\s+to|must\s+not|cannot|can't|is\s+forbidden\s+to)\s+.+?\.?$/i.test(text)) {
54
+ if (/^(?:only\s+)?[a-z][a-z\s_-]*\s+(?:may|can|(?:is|are)\s+(?:not\s+)?(?:allowed|permitted|forbidden)\s+to|must\s+not|cannot|can't)\s+.+?\.?$/i.test(text)) {
55
55
  return 0.98;
56
56
  }
57
57
  return 0;
@@ -16,6 +16,11 @@ export interface PredicateSchemaCandidate {
16
16
  argument_constants?: Record<string, string[]>;
17
17
  /** Legacy spellings keyed by argument name, each mapped to a constant. */
18
18
  argument_aliases?: Record<string, Record<string, string>>;
19
+ /**
20
+ * Argument names that determine the remaining arguments (a functional
21
+ * dependency). Two facts that agree on them describe the same case.
22
+ */
23
+ key_arguments?: string[];
19
24
  keywords: string[];
20
25
  /** Human-language aliases and controlled paraphrase templates used for deterministic retrieval. */
21
26
  aliases?: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"predicate-types.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"predicate-types.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"predicate-utils.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-utils.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQlD;AAGD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,MAAM,GAAG,SAAS,CAGpB;AAGD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,MAAM,CAIR;AAGD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAM5D;AAGD,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM1C;AAGD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAO9D;AAED;;;;;;GAMG;AAEH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,WAAW,CAAC,EAAE,QAAQ,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,CAAC,GACD,MAAM,CAeR;AAGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASjD;AAGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/C;AAGD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjD;AAGD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAGD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAOT;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAGD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtD;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAclD;AAGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9C;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9C;AAGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C"}
1
+ {"version":3,"file":"predicate-utils.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-utils.ts"],"names":[],"mappings":"AAMA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQlD;AAGD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,MAAM,GAAG,SAAS,CAGpB;AAGD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,MAAM,CAIR;AAGD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAM5D;AAGD,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM1C;AAGD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAO9D;AAED;;;;;;GAMG;AAEH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,WAAW,CAAC,EAAE,QAAQ,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,CAAC,GACD,MAAM,CAeR;AAGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASjD;AAGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/C;AAGD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAGD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAGD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAOT;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAGD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtD;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAclD;AAGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9C;AAGD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9C;AAGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C"}
@@ -1,4 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { singularizeToken } from "../semantic-advisor/shared.js";
2
3
  const DEFAULT_MIN_SCORE = 0.35;
3
4
  // implements REQ-mcp-suggest-predicates
4
5
  export function normalizeText(text) {
@@ -114,9 +115,7 @@ export function normalizePredicateToken(value) {
114
115
  }
115
116
  // implements REQ-mcp-suggest-predicates
116
117
  export function singularize(value) {
117
- if (["changes", "status", "results"].includes(value))
118
- return value;
119
- return value.endsWith("s") && value.length > 3 ? value.slice(0, -1) : value;
118
+ return singularizeToken(value, ["changes", "status", "results"]);
120
119
  }
121
120
  // implements REQ-mcp-suggest-predicates
122
121
  export function normalizeSubjectKey(value) {