kibi-cli 2.6.0 → 2.7.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 (131) hide show
  1. package/dist/cli-operation-metadata.d.ts +1 -1
  2. package/dist/cli-operation-metadata.js +1 -1
  3. package/dist/commands/check.d.ts.map +1 -1
  4. package/dist/commands/check.js +15 -0
  5. package/dist/commands/init-helpers.js +1 -1
  6. package/dist/commands/migrate.d.ts.map +1 -1
  7. package/dist/commands/migrate.js +43 -0
  8. package/dist/entity-body-context.d.ts +132 -0
  9. package/dist/entity-body-context.d.ts.map +1 -0
  10. package/dist/entity-body-context.js +382 -0
  11. package/dist/extractors/markdown.d.ts +13 -0
  12. package/dist/extractors/markdown.d.ts.map +1 -1
  13. package/dist/extractors/markdown.js +19 -2
  14. package/dist/intent-search.d.ts.map +1 -1
  15. package/dist/intent-search.js +4 -4
  16. package/dist/operations/bootstrap/candidate-helpers.d.ts +18 -0
  17. package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
  18. package/dist/operations/bootstrap/candidate-helpers.js +35 -0
  19. package/dist/operations/bootstrap/candidates.d.ts.map +1 -1
  20. package/dist/operations/bootstrap/candidates.js +4 -2
  21. package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
  22. package/dist/operations/bootstrap/intent-claims.js +59 -4
  23. package/dist/operations/bootstrap/markdown-candidates.d.ts.map +1 -1
  24. package/dist/operations/bootstrap/markdown-candidates.js +7 -3
  25. package/dist/operations/bootstrap/presentation.js +1 -1
  26. package/dist/operations/migration/entity-body-context.d.ts +57 -0
  27. package/dist/operations/migration/entity-body-context.d.ts.map +1 -0
  28. package/dist/operations/migration/entity-body-context.js +261 -0
  29. package/dist/operations/migration/polarity-values.d.ts.map +1 -1
  30. package/dist/operations/migration/polarity-values.js +5 -2
  31. package/dist/operations/migration/schema6.d.ts +2 -0
  32. package/dist/operations/migration/schema6.d.ts.map +1 -1
  33. package/dist/operations/migration/schema6.js +69 -0
  34. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
  35. package/dist/operations/modeling/logic-modeling.js +3 -1
  36. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  37. package/dist/operations/modeling/model-requirement.js +7 -9
  38. package/dist/operations/mutation/context-warning.d.ts +13 -0
  39. package/dist/operations/mutation/context-warning.d.ts.map +1 -0
  40. package/dist/operations/mutation/context-warning.js +59 -0
  41. package/dist/operations/mutation/origin.d.ts +2 -1
  42. package/dist/operations/mutation/origin.d.ts.map +1 -1
  43. package/dist/operations/mutation/origin.js +7 -18
  44. package/dist/operations/mutation/requirement-semantics.d.ts +16 -0
  45. package/dist/operations/mutation/requirement-semantics.d.ts.map +1 -0
  46. package/dist/operations/mutation/requirement-semantics.js +64 -0
  47. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  48. package/dist/operations/mutation/source-authoring.js +10 -0
  49. package/dist/operations/mutation/stored-entity.d.ts +20 -0
  50. package/dist/operations/mutation/stored-entity.d.ts.map +1 -0
  51. package/dist/operations/mutation/stored-entity.js +51 -0
  52. package/dist/operations/mutation/upsert.d.ts +3 -2
  53. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  54. package/dist/operations/mutation/upsert.js +19 -10
  55. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  56. package/dist/operations/mutation/validate-upsert.js +6 -1
  57. package/dist/operations/planning/compile-intent.d.ts +9 -0
  58. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  59. package/dist/operations/planning/compile-intent.js +49 -2
  60. package/dist/operations/semantic-advisor/analyze-prose.d.ts +3 -2
  61. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  62. package/dist/operations/semantic-advisor/analyze-prose.js +3 -41
  63. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
  64. package/dist/operations/semantic-advisor/ingestion-boundary.js +10 -1
  65. package/dist/operations/semantic-advisor/proposition-role.d.ts +6 -0
  66. package/dist/operations/semantic-advisor/proposition-role.d.ts.map +1 -0
  67. package/dist/operations/semantic-advisor/proposition-role.js +76 -0
  68. package/dist/public/operations/catalog.d.ts +33 -6
  69. package/dist/public/operations/catalog.d.ts.map +1 -1
  70. package/dist/public/operations/check-executor.d.ts.map +1 -1
  71. package/dist/public/operations/check-executor.js +3 -0
  72. package/dist/public/operations/entity-context.d.ts +51 -0
  73. package/dist/public/operations/entity-context.d.ts.map +1 -0
  74. package/dist/public/operations/entity-context.js +235 -0
  75. package/dist/public/operations/origin-review.d.ts +1 -1
  76. package/dist/public/operations/origin-review.js +2 -2
  77. package/dist/public/operations/specs/bootstrap.d.ts +14 -2
  78. package/dist/public/operations/specs/bootstrap.d.ts.map +1 -1
  79. package/dist/public/operations/specs/bootstrap.js +8 -2
  80. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  81. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  82. package/dist/public/operations/specs/check-rules.generated.js +3 -1
  83. package/dist/public/operations/specs/check.d.ts +1 -1
  84. package/dist/public/operations/specs/mutation-schemas.d.ts +1 -1
  85. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  86. package/dist/public/operations/specs/mutation-schemas.js +10 -2
  87. package/dist/public/operations/specs/planning.d.ts +15 -0
  88. package/dist/public/operations/specs/planning.d.ts.map +1 -1
  89. package/dist/public/operations/specs/planning.js +15 -0
  90. package/dist/public/operations/specs/upsert.d.ts +3 -3
  91. package/dist/public/operations/specs/upsert.js +2 -2
  92. package/dist/public/schemas/entity.d.ts.map +1 -1
  93. package/dist/public/schemas/entity.js +7 -1
  94. package/dist/public/skills/kibi-bootstrap/SKILL.md +3 -3
  95. package/dist/public/skills/kibi-bootstrap/resources/bootstrap.md +5 -1
  96. package/dist/public/skills/kibi-usage/SKILL.md +56 -3
  97. package/dist/public/skills/kibi-usage/resources/source-authoring.md +5 -1
  98. package/dist/schemas/entity.schema.json +14 -1
  99. package/dist/search-ranking.d.ts.map +1 -1
  100. package/dist/search-ranking.js +7 -4
  101. package/dist/traceability/staged-consistency.d.ts +25 -0
  102. package/dist/traceability/staged-consistency.d.ts.map +1 -0
  103. package/dist/traceability/staged-consistency.js +92 -0
  104. package/dist/traceability/temp-kb.d.ts.map +1 -1
  105. package/dist/traceability/temp-kb.js +5 -0
  106. package/dist/utils/kb-manifest.d.ts +5 -0
  107. package/dist/utils/kb-manifest.d.ts.map +1 -1
  108. package/dist/utils/kb-manifest.js +6 -0
  109. package/dist/utils/rule-registry.generated.d.ts +11 -0
  110. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  111. package/dist/utils/rule-registry.generated.js +13 -0
  112. package/dist/utils/schema-version.d.ts +1 -1
  113. package/dist/utils/schema-version.d.ts.map +1 -1
  114. package/dist/utils/schema-version.js +3 -2
  115. package/package.json +2 -2
  116. package/schema/manifest.json +5 -0
  117. package/schema/validation.pl +14 -2
  118. package/src/public/operations/check-executor.ts +6 -0
  119. package/src/public/operations/entity-context.ts +304 -0
  120. package/src/public/operations/origin-review.ts +2 -2
  121. package/src/public/operations/specs/bootstrap.ts +9 -2
  122. package/src/public/operations/specs/check-rules.generated.ts +3 -1
  123. package/src/public/operations/specs/mutation-schemas.ts +10 -2
  124. package/src/public/operations/specs/planning.ts +18 -0
  125. package/src/public/operations/specs/upsert.ts +2 -2
  126. package/src/public/schemas/entity.ts +7 -1
  127. package/src/public/skills/kibi-bootstrap/SKILL.md +3 -3
  128. package/src/public/skills/kibi-bootstrap/resources/bootstrap.md +5 -1
  129. package/src/public/skills/kibi-usage/SKILL.md +56 -3
  130. package/src/public/skills/kibi-usage/resources/source-authoring.md +5 -1
  131. package/src/schemas/entity.schema.json +14 -1
@@ -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.3.1
5
+ version: 2.4.0
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -154,11 +154,43 @@ execute each required repair action in order, and never retry the original
154
154
  operation. Record effect failures, followed actions, and unsafe retries in
155
155
  diagnostic telemetry.
156
156
 
157
+ ## Entity body contract
158
+
159
+ The body is where context lives; front matter is the checked meaning.
160
+ `kb_check` rule `entity-context-missing` blocks a current `req`, `scenario`,
161
+ `test`, `adr` or observation/meta `fact` whose body carries no context: at
162
+ least 12 words that are not a restatement of the title (for a requirement, also
163
+ not of `semantic_text`). Symbols, flags, events and every other fact kind are
164
+ exempt. `kb_upsert` returns the same finding as a warning, including on dryRun.
165
+
166
+ - `req`: the statement, then `## Context` (why, who asked, constraints) and
167
+ `## Source` (blockquoted excerpt plus reference). Only text under context
168
+ headings (Context, Rationale, Why, Background, Source, Notes, Evidence)
169
+ counts for a requirement, and it never changes the checked meaning:
170
+ `semantic_text` is written explicitly and context sections are excluded.
171
+ - `scenario`: Given/When/Then prose plus the assumptions it depends on.
172
+ - `test`: what it asserts, how (fixture, entry point), what would make it a
173
+ false pass.
174
+ - `fact` (`observation`/`meta`): what was seen, where, when, how confirmed.
175
+ - Never invent a reason the requester did not give. Write "Reason not stated"
176
+ and the source instead.
177
+ - The tag `review:context-missing` is reserved for entities the schema 8
178
+ migration (`kibi migrate`) acknowledged and recorded in the manifest; it is
179
+ counted by the advisory `entity-context-acknowledged`. Never add it yourself:
180
+ on any other entity it is still a violation. Write who asked, the source and
181
+ "Reason not stated" in the Context section instead.
182
+ - `kb_plan_compile_intent` requires `context` when the plan creates a
183
+ requirement, and accepts `sourceExcerpt` and `sourceReference`. On update it
184
+ rewrites the statement and keeps the existing context sections unless you
185
+ supply new `context` or source.
186
+
157
187
  ## Source-first mutation
158
188
 
159
189
  Use `document.path` when a new entity has no single configured writable target.
160
- Existing entities preserve body bytes when `document.body` is omitted; new
161
- requirements default their body to `semantic_text`. Relationship mutations
190
+ Existing entities preserve body bytes when `document.body` is omitted; a new
191
+ requirement without `document.body` gets `semantic_text` as its body, and
192
+ `kb_check` then blocks it with `entity-context-missing`, so always pass a
193
+ sectioned `document.body` (see Entity body contract). Relationship mutations
162
194
  patch canonical shards while preserving unrelated records. Authored entity
163
195
  deletion returns a hash-bound approval plan; requirements normally evolve via a
164
196
  new entity linked with `supersedes`; set the replaced requirement to
@@ -220,6 +252,27 @@ grounding: run `logic-coverage` so each key binds to one ground fact.
220
252
  Relationship direction is fixed, and every `from` in a relationship batch
221
253
  must equal the upserted entity ID.
222
254
 
255
+ Worked example. `recommendedAction: "provide_argument_bindings"` means a
256
+ schema fits but `unbound_arguments` lists roles Kibi could not read from the
257
+ prose. Bind them from the claim's own words and call again with the same
258
+ `text` and `requirementId`, plus `schemaId` and `argumentBindings` keyed by
259
+ `argument_names` (reuse `argument_constants` values when the schema has them):
260
+
261
+ ```json
262
+ {"mode":"predicates","text":"Only an annotation owner may delete an annotation.","requirementId":"REQ-annotation-delete-owner","schemaId":"FACT-SCHEMA-PERMISSION-RULE","argumentBindings":{"actor":"annotation_owner","action":"delete","resource":"annotation","decision":"allow"}}
263
+ ```
264
+
265
+ When the retry returns `apply_requires_predicate`, write its `applyPlan` fact,
266
+ then the `relationshipPlan` `requires_predicate` row. Record an ontology gap
267
+ only when no returned schema fits the claim, not because bindings were missing.
268
+ A review note is an observation that quotes its claim without `claim_key`:
269
+ `{"type":"fact","id":"FACT-review-<area>-<behavior>","properties":{"title":"Review: ...","status":"active","fact_kind":"observation","text_ref":"<sourceId>:<reference>","tags":["review:invalid-write"],"claim_text":"<the claim>"}}`.
270
+
271
+ To add `specified_by` (or another relationship) to an existing requirement,
272
+ upsert it with its stored `title`, a `status` and the relationship only; Kibi
273
+ keeps the stored proposition ledger when no `semantic_*` or `logic_claims`
274
+ field is sent and `title`/`text_ref` are unchanged.
275
+
223
276
  For conditional relational claims, after the initial `kb_model` predicates call and before any `kb_upsert`—including one needed for a missing schema—call read-only `kb_model` with `mode: "requirement"` to preview suitable scalar or typed-rule modeling. Treat the preview as advisory: do not apply an irrelevant result or create unrequested facts, and retain an approved ground-predicate plan when it captures the whole claim. Preserve supplied arity, ordered argument roles, polarity, bound values, and one claim key per actual assertion; never split arguments across clauses or schemas or alter values to force uniqueness.
224
277
 
225
278
  ## Symbol-First Traceability
@@ -7,7 +7,11 @@ commits them; ordinary Git workflows remain responsible for review and merge.
7
7
 
8
8
  `kb_upsert` accepts `document.path` and `document.body`. Existing entities use
9
9
  their authored source by default and preserve body bytes when `body` is omitted.
10
- New requirements use `semantic_text` as their body. If a new entity has zero or
10
+ A new requirement without `body` uses `semantic_text` as its body, which
11
+ `entity-context-missing` blocks; pass a sectioned body (statement, `## Context`,
12
+ `## Source`) and the written `semantic_text` stays the checked meaning, since
13
+ context sections are excluded from it. Source-first requirement writes pin
14
+ `semantic_text` in front matter. If a new entity has zero or
11
15
  multiple configured writable targets, provide an explicit workspace-relative
12
16
  `document.path`; absolute, traversal, and symlink escapes are rejected.
13
17
 
@@ -1684,7 +1684,20 @@
1684
1684
  {
1685
1685
  "required": [
1686
1686
  "claim_text"
1687
- ]
1687
+ ],
1688
+ "not": {
1689
+ "properties": {
1690
+ "fact_kind": {
1691
+ "enum": [
1692
+ "observation",
1693
+ "meta"
1694
+ ]
1695
+ }
1696
+ },
1697
+ "required": [
1698
+ "fact_kind"
1699
+ ]
1700
+ }
1688
1701
  }
1689
1702
  ]
1690
1703
  },
@@ -1 +1 @@
1
- {"version":3,"file":"search-ranking.d.ts","sourceRoot":"","sources":["../src/search-ranking.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgDD,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACnC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC,CA8BxB;AAsGD,wBAAsB,gBAAgB,CAEpC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB;AAuJD,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CAQpB"}
1
+ {"version":3,"file":"search-ranking.d.ts","sourceRoot":"","sources":["../src/search-ranking.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgDD,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EACnC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC,CA8BxB;AAsGD,wBAAsB,gBAAgB,CAEpC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB;AA0JD,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CAQpB"}
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import { bodySnippetLine } from "./entity-body-context.js";
3
4
  const SEARCH_STOP_WORDS = new Set([
4
5
  "to",
5
6
  "in",
@@ -115,14 +116,14 @@ async function rankEntity(entity, queryContext, workspaceRoot) {
115
116
  if (isPhraseSearchMatch(bodyForms, queryContext.phrase)) {
116
117
  score += 15;
117
118
  reasons.push("markdown body match");
118
- snippet = buildSnippet(bodyText, queryContext.phrase);
119
+ snippet = buildSnippet(bodyText, queryContext.phrase, entity);
119
120
  }
120
121
  else {
121
122
  const bodyTokenMatches = countTokenMatches(bodyForms, queryContext.signalTokens);
122
123
  if (bodyTokenMatches > 0) {
123
124
  score += bodyTokenMatches * 3;
124
125
  reasons.push("markdown body token coverage");
125
- snippet = buildSnippet(bodyText, queryContext.phrase);
126
+ snippet = buildSnippet(bodyText, queryContext.phrase, entity);
126
127
  }
127
128
  }
128
129
  }
@@ -257,12 +258,14 @@ function getInlineBodyText(entity) {
257
258
  return null;
258
259
  }
259
260
  // implements REQ-mcp-search-discovery
260
- function buildSnippet(bodyText, queryForms) {
261
+ function buildSnippet(bodyText, queryForms, entity) {
261
262
  const lines = bodyText
262
263
  .split(/\r?\n/)
263
264
  .map((line) => line.trim())
264
265
  .filter(Boolean);
265
- const matchedLine = lines.find((line) => isPhraseSearchMatch(buildSearchTextForms(line), queryForms)) ?? lines[0];
266
+ // The line that matches the query wins; otherwise the context prose, then
267
+ // the first line.
268
+ const matchedLine = lines.find((line) => isPhraseSearchMatch(buildSearchTextForms(line), queryForms)) ?? bodySnippetLine(String(entity.type ?? ""), bodyText, entity);
266
269
  return snippetFromMatchedLine(matchedLine);
267
270
  }
268
271
  export function snippetFromMatchedLine(matchedLine) {
@@ -0,0 +1,25 @@
1
+ import type { ExtractionResult } from "../extractors/markdown.js";
2
+ import type { Violation } from "../public/check-types.js";
3
+ type SnapshotReader = Readonly<{
4
+ baseTree: string;
5
+ headTree: string;
6
+ readGit(args: readonly string[]): Buffer;
7
+ readBlobs(oids: readonly string[]): ReadonlyMap<string, Buffer>;
8
+ }>;
9
+ /**
10
+ * True when the staged change set touches entity documents or relationship
11
+ * shards, the only knowledge these rules read. A symbols manifest change
12
+ * alone cannot change their outcome.
13
+ */
14
+ export declare function stagesKnowledge(paths: readonly string[]): boolean;
15
+ /**
16
+ * Consistency violations the staged tree has and the base tree does not.
17
+ * A violation already present at the base commit does not block an
18
+ * unrelated commit; full `kibi check` still reports it. The base tree is
19
+ * only analyzed when the staged tree has violations.
20
+ */
21
+ export declare function collectIntroducedConsistencyViolations(snapshot: SnapshotReader, headKnowledge: ExtractionResult[]): Promise<Violation[]>;
22
+ /** Text lines for introduced consistency violations, in `kibi check` form. */
23
+ export declare function formatConsistencyViolations(violations: readonly Violation[]): string[];
24
+ export {};
25
+ //# sourceMappingURL=staged-consistency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staged-consistency.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-consistency.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAsB1D,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC;IACzC,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjE,CAAC,CAAC;AAEH;;;;GAIG;AAEH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAMjE;AAkDD;;;;;GAKG;AAEH,wBAAsB,sCAAsC,CAC1D,QAAQ,EAAE,cAAc,EACxB,aAAa,EAAE,gBAAgB,EAAE,GAChC,OAAO,CAAC,SAAS,EAAE,CAAC,CAYtB;AAED,8EAA8E;AAE9E,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,SAAS,SAAS,EAAE,GAC/B,MAAM,EAAE,CAWV"}
@@ -0,0 +1,92 @@
1
+ import { runAggregatedChecks } from "../commands/aggregated-checks.js";
2
+ import { isEntityLanePath } from "../utils/kb-paths.js";
3
+ import { readSnapshotKnowledge } from "./snapshot-knowledge.js";
4
+ import { cleanupTempKb, createTempKb, projectStagedEntities, } from "./temp-kb.js";
5
+ /**
6
+ * Canonical rules that decide whether the staged knowledge is consistent:
7
+ * requirement contradictions, success scenarios a current requirement
8
+ * forbids, and exceptions that name claims they cannot waive. They read only
9
+ * authored knowledge, so the staged tree alone decides them.
10
+ */
11
+ // implements REQ-cli-staged-consistency
12
+ const STAGED_CONSISTENCY_RULES = [
13
+ "domain-contradictions",
14
+ "scenario-feasibility",
15
+ "exception-claim-keys",
16
+ ];
17
+ /**
18
+ * True when the staged change set touches entity documents or relationship
19
+ * shards, the only knowledge these rules read. A symbols manifest change
20
+ * alone cannot change their outcome.
21
+ */
22
+ // implements REQ-cli-staged-consistency
23
+ export function stagesKnowledge(paths) {
24
+ return paths.some((file) => (isEntityLanePath(file) && file.endsWith(".md")) ||
25
+ (file.startsWith(".kb/relationships/") && /\.ya?ml$/.test(file)));
26
+ }
27
+ // implements REQ-cli-staged-consistency
28
+ function violationKey(violation) {
29
+ return JSON.stringify([
30
+ violation.rule,
31
+ violation.entityId,
32
+ violation.description,
33
+ ]);
34
+ }
35
+ /**
36
+ * The knowledge these rules read: every entity except code symbols, and the
37
+ * relationships between them. Symbols and their edges are most of a large
38
+ * KB and would dominate the projection time of a pre-commit hook.
39
+ */
40
+ // implements REQ-cli-staged-consistency
41
+ function withoutSymbols(knowledge) {
42
+ const ids = new Set(knowledge
43
+ .filter(({ entity }) => entity.type !== "symbol")
44
+ .map(({ entity }) => entity.id));
45
+ return knowledge
46
+ .filter(({ entity }) => ids.has(entity.id))
47
+ .map((result) => ({
48
+ ...result,
49
+ relationships: result.relationships.filter((relationship) => ids.has(relationship.from) && ids.has(relationship.to)),
50
+ }));
51
+ }
52
+ // implements REQ-cli-staged-consistency
53
+ async function consistencyViolations(knowledge) {
54
+ const ctx = await createTempKb();
55
+ try {
56
+ await projectStagedEntities(ctx.prolog, withoutSymbols(knowledge));
57
+ return await runAggregatedChecks(ctx.prolog, new Set(STAGED_CONSISTENCY_RULES));
58
+ }
59
+ finally {
60
+ await cleanupTempKb(ctx.tempDir);
61
+ }
62
+ }
63
+ /**
64
+ * Consistency violations the staged tree has and the base tree does not.
65
+ * A violation already present at the base commit does not block an
66
+ * unrelated commit; full `kibi check` still reports it. The base tree is
67
+ * only analyzed when the staged tree has violations.
68
+ */
69
+ // implements REQ-cli-staged-consistency
70
+ export async function collectIntroducedConsistencyViolations(snapshot, headKnowledge) {
71
+ const head = await consistencyViolations(headKnowledge);
72
+ if (head.length === 0)
73
+ return [];
74
+ const base = await consistencyViolations(readSnapshotKnowledge(snapshot.readGit, snapshot.baseTree, snapshot.readBlobs));
75
+ const existing = new Set(base.map(violationKey));
76
+ return head.filter((violation) => !existing.has(violationKey(violation)));
77
+ }
78
+ /** Text lines for introduced consistency violations, in `kibi check` form. */
79
+ // implements REQ-cli-staged-consistency
80
+ export function formatConsistencyViolations(violations) {
81
+ const lines = [
82
+ `Found ${violations.length} consistency violation(s) introduced by the staged changes:`,
83
+ "",
84
+ ];
85
+ for (const violation of violations) {
86
+ lines.push(`[${violation.rule}] ${violation.entityId}`);
87
+ if (violation.source)
88
+ lines.push(` Source: ${violation.source}`);
89
+ lines.push(` ${violation.description}`, "");
90
+ }
91
+ return lines;
92
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAMA,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAET;AACD,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CASvC;AAQD;;;GAGG;AACH,wBAAgB,iBAAiB,CAE/B,OAAO,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,KAAK,aAAa,GACpE,IAAI,CAEN;AAyRD,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAe1B,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED,wBAAsB,YAAY,CAChC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA+CxB;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
1
+ {"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAMA,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAET;AACD,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CASvC;AAQD;;;GAGG;AACH,wBAAgB,iBAAiB,CAE/B,OAAO,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,KAAK,aAAa,GACpE,IAAI,CAEN;AA8RD,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAe1B,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED,wBAAsB,YAAY,CAChC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA+CxB;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
@@ -194,6 +194,11 @@ function buildEntityAssertionGoal(entity, sourceFile) {
194
194
  if (entity.type === "req" && entity.exempts_claims) {
195
195
  props.push(`exempts_claims=[${entity.exempts_claims.map(toPrologAtom).join(",")}]`);
196
196
  }
197
+ // implements REQ-cli-staged-consistency
198
+ // Scenario feasibility reads the intended outcome.
199
+ if (entity.type === "scenario" && entity.expects !== undefined) {
200
+ props.push(`expects=${toPrologAtom(entity.expects)}`);
201
+ }
197
202
  if (entity.origin !== undefined) {
198
203
  props.push(`origin=${toPrologString(JSON.stringify(entity.origin))}`);
199
204
  }
@@ -15,6 +15,11 @@ export interface KbManifest {
15
15
  schemaVersion: number;
16
16
  /** Retroactive semantic-advisor backfill review state. */
17
17
  semanticAdvisorBackfill: SemanticAdvisorBackfill;
18
+ /**
19
+ * Entity ids the schema 8 migration acknowledged as lacking body context.
20
+ * Only these ids may carry `review:context-missing` without a violation.
21
+ */
22
+ contextAcknowledged?: string[];
18
23
  }
19
24
  export declare function defaultKbManifest(): KbManifest;
20
25
  export type KbManifestStatus = {
@@ -1 +1 @@
1
- {"version":3,"file":"kb-manifest.d.ts","sourceRoot":"","sources":["../../src/utils/kb-manifest.ts"],"names":[],"mappings":"AA8BA;;;;;;;GAOG;AAEH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,MAAM,uBAAuB,GAC/B,SAAS,GACT,WAAW,GACX,gBAAgB,CAAC;AAErB,MAAM,WAAW,UAAU;IACzB,uEAAuE;IACvE,eAAe,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,uBAAuB,EAAE,uBAAuB,CAAC;CAClD;AAED,wBAAgB,iBAAiB,IAAI,UAAU,CAM9C;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAClE;IACE,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,QAAQ,EAAE,IAAI,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA+CN,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,gBAAgB,CAyD5E;AAED,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGvE;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,CAEzE;AASD,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,UAAU,GACnB,MAAM,CAIR"}
1
+ {"version":3,"file":"kb-manifest.d.ts","sourceRoot":"","sources":["../../src/utils/kb-manifest.ts"],"names":[],"mappings":"AA8BA;;;;;;;GAOG;AAEH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,MAAM,uBAAuB,GAC/B,SAAS,GACT,WAAW,GACX,gBAAgB,CAAC;AAErB,MAAM,WAAW,UAAU;IACzB,uEAAuE;IACvE,eAAe,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,uBAAuB,EAAE,uBAAuB,CAAC;IACjD;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,wBAAgB,iBAAiB,IAAI,UAAU,CAM9C;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAClE;IACE,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,QAAQ,EAAE,IAAI,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAuDN,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,gBAAgB,CAyD5E;AAED,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGvE;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU,CAEzE;AASD,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,UAAU,GACnB,MAAM,CAIR"}
@@ -70,10 +70,16 @@ function validateManifest(parsed) {
70
70
  backfill !== "not_applicable") {
71
71
  return null;
72
72
  }
73
+ const acknowledged = parsed.contextAcknowledged;
73
74
  return {
74
75
  manifestVersion,
75
76
  schemaVersion,
76
77
  semanticAdvisorBackfill: backfill,
78
+ ...(Array.isArray(acknowledged)
79
+ ? {
80
+ contextAcknowledged: acknowledged.filter((id) => typeof id === "string"),
81
+ }
82
+ : {}),
77
83
  };
78
84
  }
79
85
  export function readKbManifestStatus(workspaceRoot) {
@@ -207,5 +207,16 @@ export declare const GENERATED_RULES: readonly [{
207
207
  readonly description: "Predicate facts match a predicate_schema (project-local, or the built-in catalog in the default namespace) and use its declared argument constants";
208
208
  readonly enforcementClass: "advisory";
209
209
  readonly category: "integrity";
210
+ }, {
211
+ readonly name: "entity-context-missing";
212
+ readonly description: "A current requirement, scenario, test, ADR or observation/meta fact must carry body context: at least 12 words of prose (requirements: under a Context, Rationale, Why, Background, Source, Notes or Evidence heading) that do not restate the title or semantic_text; entities tagged review:context-missing are acknowledged legacy and exempt";
213
+ readonly enforcementClass: "canonical";
214
+ readonly category: "integrity";
215
+ }, {
216
+ readonly name: "entity-context-acknowledged";
217
+ readonly description: "Informational: how many current entities carry the review:context-missing tag, so the legacy context backlog stays visible; one summary finding per check";
218
+ readonly enforcementClass: "advisory";
219
+ readonly category: "lifecycle";
220
+ readonly diagnosticSeverity: "info";
210
221
  }];
211
222
  //# sourceMappingURL=rule-registry.generated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rule-registry.generated.d.ts","sourceRoot":"","sources":["../../src/utils/rule-registry.generated.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiSlB,CAAC"}
1
+ {"version":3,"file":"rule-registry.generated.d.ts","sourceRoot":"","sources":["../../src/utils/rule-registry.generated.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgTlB,CAAC"}
@@ -258,4 +258,17 @@ export const GENERATED_RULES = [
258
258
  enforcementClass: "advisory",
259
259
  category: "integrity",
260
260
  },
261
+ {
262
+ name: "entity-context-missing",
263
+ description: "A current requirement, scenario, test, ADR or observation/meta fact must carry body context: at least 12 words of prose (requirements: under a Context, Rationale, Why, Background, Source, Notes or Evidence heading) that do not restate the title or semantic_text; entities tagged review:context-missing are acknowledged legacy and exempt",
264
+ enforcementClass: "canonical",
265
+ category: "integrity",
266
+ },
267
+ {
268
+ name: "entity-context-acknowledged",
269
+ description: "Informational: how many current entities carry the review:context-missing tag, so the legacy context backlog stays visible; one summary finding per check",
270
+ enforcementClass: "advisory",
271
+ category: "lifecycle",
272
+ diagnosticSeverity: "info",
273
+ },
261
274
  ];
@@ -1,4 +1,4 @@
1
- export declare const LATEST_KB_SCHEMA_VERSION = 7;
1
+ export declare const LATEST_KB_SCHEMA_VERSION = 8;
2
2
  export interface SchemaVersionStatus {
3
3
  status: "missing" | "invalid" | "older" | "current" | "newer";
4
4
  currentVersion: number | null;
@@ -1 +1 @@
1
- {"version":3,"file":"schema-version.d.ts","sourceRoot":"","sources":["../../src/utils/schema-version.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IAC9D,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,GACrD,IAAI,GACJ,SAAS,CAAC;AAGd,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAChD,MAAM,GAAG,IAAI,CAgBf;AAGD,wBAAgB,sBAAsB,CACpC,MAAM,CAAC,EAAE,mBAAmB,GAC3B,mBAAmB,CAgDrB"}
1
+ {"version":3,"file":"schema-version.d.ts","sourceRoot":"","sources":["../../src/utils/schema-version.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IAC9D,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,GACrD,IAAI,GACJ,SAAS,CAAC;AAGd,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAChD,MAAM,GAAG,IAAI,CAgBf;AAGD,wBAAgB,sBAAsB,CACpC,MAAM,CAAC,EAAE,mBAAmB,GAC3B,mBAAmB,CAgDrB"}
@@ -16,8 +16,9 @@
16
16
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
18
  // implements REQ-003
19
- // Schema 7 requires strict fact shapes and encodes legacy polarity values.
20
- export const LATEST_KB_SCHEMA_VERSION = 7;
19
+ // Schema 8 requires body context on current entities and pins requirement
20
+ // semantic_text so context sections never change a requirement's meaning.
21
+ export const LATEST_KB_SCHEMA_VERSION = 8;
21
22
  // implements REQ-003
22
23
  export function normalizeSchemaVersion(schemaVersion) {
23
24
  if (schemaVersion === undefined || schemaVersion === null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cli",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "type": "module",
5
5
  "description": "Kibi CLI for knowledge base management",
6
6
  "engines": {
@@ -235,7 +235,7 @@
235
235
  "fast-glob": "^3.2.12",
236
236
  "gray-matter": "^4.0.3",
237
237
  "js-yaml": "^4.1.0",
238
- "kibi-core": "^0.15.1",
238
+ "kibi-core": "^0.16.0",
239
239
  "kibi-plugin-builtin": "^0.4.2",
240
240
  "kibi-plugin-sdk": "^0.4.1",
241
241
  "kibi-swipl": "^1.0.1",
@@ -21,6 +21,11 @@
21
21
  "type": "string",
22
22
  "enum": ["pending", "completed", "not_applicable"],
23
23
  "description": "Retroactive semantic-advisor backfill review state"
24
+ },
25
+ "contextAcknowledged": {
26
+ "type": "array",
27
+ "items": { "type": "string" },
28
+ "description": "Entity ids the schema 8 migration acknowledged as lacking body context; only these may carry review:context-missing without an entity-context-missing violation"
24
29
  }
25
30
  }
26
31
  }
@@ -225,15 +225,27 @@ valid_strict_polarity_in_props(Props) :-
225
225
  valid_predicate_polarity_in_props(Props) :-
226
226
  ( memberchk(polarity=P, Props) -> valid_predicate_polarity(P) ; true ).
227
227
 
228
- % claim_key and claim_text form one auditable provenance pair.
228
+ % claim_key and claim_text form one auditable provenance pair. An observation
229
+ % or meta fact is a non-grounding review note: it may quote the claim it is
230
+ % about in claim_text without claiming that claim's key.
229
231
  valid_claim_provenance(Props) :-
230
232
  ( memberchk(claim_key=Key, Props)
231
233
  -> memberchk(claim_text=Text, Props),
232
234
  nonempty_claim_value(Key),
233
235
  nonempty_claim_value(Text)
234
- ; \+ memberchk(claim_text=_, Props)
236
+ ; memberchk(claim_text=Text, Props)
237
+ -> review_note_fact(Props),
238
+ nonempty_claim_value(Text)
239
+ ; true
235
240
  ).
236
241
 
242
+ review_note_fact(Props) :-
243
+ memberchk(fact_kind=RawKind, Props),
244
+ ( atom(RawKind) -> Kind = RawKind
245
+ ; string(RawKind) -> atom_string(Kind, RawKind)
246
+ ),
247
+ memberchk(Kind, [observation, meta]).
248
+
237
249
  nonempty_claim_value(Value) :- string(Value), Value \= "", !.
238
250
  nonempty_claim_value(Value) :- atom(Value), Value \= '', !.
239
251
 
@@ -34,6 +34,7 @@ import {
34
34
  stagedEntityIdStyleDiagnostics,
35
35
  } from "./check-helpers.js";
36
36
  import { executeStatus } from "./discovery-executors.js";
37
+ import { collectEntityContextViolations } from "./entity-context.js";
37
38
  import {
38
39
  buildActionsFromCheck,
39
40
  buildMigrationPlan,
@@ -224,6 +225,10 @@ export async function executeCheck(
224
225
  rulesAllowlist,
225
226
  workspaceRoot,
226
227
  );
228
+ const entityContextFindings = collectEntityContextViolations(
229
+ rulesAllowlist,
230
+ workspaceRoot,
231
+ );
227
232
  const partitioned = partitionCheckFindings([
228
233
  ...aggregatedFindings,
229
234
  ...queryPlanViolations,
@@ -231,6 +236,7 @@ export async function executeCheck(
231
236
  ...sourcePathFindings,
232
237
  ...predicateConformanceFindings,
233
238
  ...originReviewFindings,
239
+ ...entityContextFindings,
234
240
  ]);
235
241
  const violations: Violation[] = partitioned.violations;
236
242