kibi-cli 2.26.3 → 2.28.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 (109) 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 +17 -2
  5. package/dist/commands/doctor.d.ts.map +1 -1
  6. package/dist/commands/doctor.js +2 -1
  7. package/dist/commands/migrate.d.ts.map +1 -1
  8. package/dist/commands/migrate.js +24 -0
  9. package/dist/commands/sync/persistence.d.ts +10 -0
  10. package/dist/commands/sync/persistence.d.ts.map +1 -1
  11. package/dist/commands/sync/persistence.js +24 -0
  12. package/dist/commands/sync.d.ts.map +1 -1
  13. package/dist/commands/sync.js +5 -1
  14. package/dist/diagnostics.d.ts +6 -0
  15. package/dist/diagnostics.d.ts.map +1 -1
  16. package/dist/diagnostics.js +25 -9
  17. package/dist/intent-search.d.ts +2 -0
  18. package/dist/intent-search.d.ts.map +1 -1
  19. package/dist/intent-search.js +5 -0
  20. package/dist/operations/bootstrap/activation.d.ts +6 -0
  21. package/dist/operations/bootstrap/activation.d.ts.map +1 -1
  22. package/dist/operations/bootstrap/activation.js +22 -0
  23. package/dist/operations/bootstrap/claim-restatement.d.ts +2 -0
  24. package/dist/operations/bootstrap/claim-restatement.d.ts.map +1 -1
  25. package/dist/operations/bootstrap/conflict-review.d.ts +24 -0
  26. package/dist/operations/bootstrap/conflict-review.d.ts.map +1 -0
  27. package/dist/operations/bootstrap/conflict-review.js +92 -0
  28. package/dist/operations/bootstrap/generate.d.ts.map +1 -1
  29. package/dist/operations/bootstrap/generate.js +18 -5
  30. package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
  31. package/dist/operations/bootstrap/guidance-actions.js +4 -1
  32. package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
  33. package/dist/operations/bootstrap/intent-claims.js +1 -0
  34. package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
  35. package/dist/operations/bootstrap/presentation.js +6 -2
  36. package/dist/operations/bootstrap/types.d.ts +7 -0
  37. package/dist/operations/bootstrap/types.d.ts.map +1 -1
  38. package/dist/operations/migration/entity-type.d.ts +35 -0
  39. package/dist/operations/migration/entity-type.d.ts.map +1 -0
  40. package/dist/operations/migration/entity-type.js +89 -0
  41. package/dist/operations/migration/schema6.d.ts.map +1 -1
  42. package/dist/operations/migration/schema6.js +32 -0
  43. package/dist/operations/mutation/symbol-granularity.d.ts +7 -1
  44. package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
  45. package/dist/operations/mutation/symbol-granularity.js +46 -8
  46. package/dist/operations/mutation/upsert.d.ts +9 -1
  47. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  48. package/dist/operations/mutation/upsert.js +46 -9
  49. package/dist/operations/mutation/validation.d.ts.map +1 -1
  50. package/dist/operations/mutation/validation.js +21 -0
  51. package/dist/operations/planning/compile-intent.d.ts +16 -0
  52. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  53. package/dist/operations/planning/compile-intent.js +118 -5
  54. package/dist/operations/planning/conflict-review.d.ts +69 -0
  55. package/dist/operations/planning/conflict-review.d.ts.map +1 -0
  56. package/dist/operations/planning/conflict-review.js +133 -0
  57. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +8 -0
  58. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
  59. package/dist/operations/semantic-advisor/ingestion-boundary.js +43 -2
  60. package/dist/public/impact/analyzer.d.ts.map +1 -1
  61. package/dist/public/impact/analyzer.js +26 -2
  62. package/dist/public/impact/requirement-statements.d.ts +29 -0
  63. package/dist/public/impact/requirement-statements.d.ts.map +1 -0
  64. package/dist/public/impact/requirement-statements.js +127 -0
  65. package/dist/public/operations/catalog.d.ts +26 -2
  66. package/dist/public/operations/catalog.d.ts.map +1 -1
  67. package/dist/public/operations/check-format-shared.d.ts +1 -1
  68. package/dist/public/operations/check-format-shared.d.ts.map +1 -1
  69. package/dist/public/operations/check-format-shared.js +19 -4
  70. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  71. package/dist/public/operations/discovery-executors.js +20 -13
  72. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  73. package/dist/public/operations/migration-plan.js +14 -4
  74. package/dist/public/operations/result-envelope.d.ts +2 -0
  75. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  76. package/dist/public/operations/result-envelope.js +21 -9
  77. package/dist/public/operations/specs/check.d.ts +1 -1
  78. package/dist/public/operations/specs/check.js +1 -1
  79. package/dist/public/operations/specs/planning.d.ts +25 -1
  80. package/dist/public/operations/specs/planning.d.ts.map +1 -1
  81. package/dist/public/operations/specs/planning.js +16 -1
  82. package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
  83. package/dist/public/skills/kibi-usage/SKILL.md +11 -1
  84. package/dist/public/symbol-granularity.d.ts +5 -0
  85. package/dist/public/symbol-granularity.d.ts.map +1 -1
  86. package/dist/public/symbol-granularity.js +12 -3
  87. package/dist/traceability/staged-consistency.d.ts +1 -1
  88. package/dist/traceability/staged-consistency.d.ts.map +1 -1
  89. package/dist/traceability/staged-consistency.js +2 -2
  90. package/dist/traceability/staged-diagnostics.d.ts +1 -1
  91. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  92. package/dist/traceability/staged-entity-context.d.ts +18 -0
  93. package/dist/traceability/staged-entity-context.d.ts.map +1 -0
  94. package/dist/traceability/staged-entity-context.js +66 -0
  95. package/dist/utils/config.d.ts +8 -0
  96. package/dist/utils/config.d.ts.map +1 -1
  97. package/dist/utils/config.js +10 -0
  98. package/package.json +2 -2
  99. package/src/public/impact/analyzer.ts +38 -2
  100. package/src/public/impact/requirement-statements.ts +171 -0
  101. package/src/public/operations/check-format-shared.ts +27 -4
  102. package/src/public/operations/discovery-executors.ts +20 -13
  103. package/src/public/operations/migration-plan.ts +24 -6
  104. package/src/public/operations/result-envelope.ts +18 -4
  105. package/src/public/operations/specs/check.ts +1 -1
  106. package/src/public/operations/specs/planning.ts +17 -1
  107. package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
  108. package/src/public/skills/kibi-usage/SKILL.md +11 -1
  109. package/src/public/symbol-granularity.ts +13 -5
@@ -125,6 +125,8 @@ function extraFailedEffects(declared, data) {
125
125
  ];
126
126
  });
127
127
  }
128
+ /** The envelope error code of a kb_upsert dry run on an invalid payload. */
129
+ export const UPSERT_DRY_RUN_INVALID = "UPSERT_DRY_RUN_INVALID";
128
130
  export function resultVersion(spec) {
129
131
  return spec.resultVersion ?? `kibi.${spec.name}.v1`;
130
132
  }
@@ -141,29 +143,39 @@ export function toKibiResult(spec, data, options = {}) {
141
143
  // an error, not a success that needs reconciliation.
142
144
  const migrationRefused = row?.version === "kibi.migration-apply-result.v1" &&
143
145
  row.outcome === "refused";
146
+ // implements REQ-kibi-symbol-link-guidance
147
+ // A kb_upsert dry run that finds the payload invalid reports what the
148
+ // write would do: refuse it. Its data still carries the errors.
149
+ const dryRunInvalid = row?.dryRun === true && row.valid === false;
144
150
  let status = options.status;
145
151
  if (!status) {
146
152
  status = "success";
147
153
  if (row?.status === "committed_with_repairs")
148
154
  status = "committed_with_repairs";
149
- if (row?.status === "rejected" || migrationRefused)
155
+ if (row?.status === "rejected" || migrationRefused || dryRunInvalid)
150
156
  status = "error";
151
157
  }
152
- const terminalError = row?.status === "rejected"
158
+ const terminalError = dryRunInvalid
153
159
  ? {
154
- code: "BOOTSTRAP_PLAN_REJECTED",
155
- message: "Bootstrap stopped at a deterministic failure. Inspect actionResults for committed actions and re-plan from the current state.",
160
+ code: UPSERT_DRY_RUN_INVALID,
161
+ message: `Dry run: kb_upsert would refuse this payload; nothing was written. ${Array.isArray(row.errors) ? row.errors.map(String).join("; ") : ""}`.trim(),
156
162
  retryable: false,
157
163
  }
158
- : migrationRefused
164
+ : row?.status === "rejected"
159
165
  ? {
160
- code: MIGRATION_PLAN_REFUSED,
161
- message: `Migration plan refused; nothing was changed. ${refusalDetail(row)}`.trim(),
166
+ code: "BOOTSTRAP_PLAN_REJECTED",
167
+ message: "Bootstrap stopped at a deterministic failure. Inspect actionResults for committed actions and re-plan from the current state.",
162
168
  retryable: false,
163
169
  }
164
- : undefined;
170
+ : migrationRefused
171
+ ? {
172
+ code: MIGRATION_PLAN_REFUSED,
173
+ message: `Migration plan refused; nothing was changed. ${refusalDetail(row)}`.trim(),
174
+ retryable: false,
175
+ }
176
+ : undefined;
165
177
  const resultError = options.error ?? terminalError;
166
- const outcome = effectOutcome(status, migrationRefused && options.attempted === undefined
178
+ const outcome = effectOutcome(status, (migrationRefused || dryRunInvalid) && options.attempted === undefined
167
179
  ? { ...options, attempted: false }
168
180
  : options);
169
181
  return {
@@ -31,7 +31,7 @@ export declare const checkSpec: {
31
31
  };
32
32
  readonly includeImpactDiagnostics: {
33
33
  readonly type: "boolean";
34
- readonly description: "When true, include changed-file impact diagnostics such as symbol_granularity_violation, symbol_semantic_review_needed and source_file_unowned in structured output.";
34
+ readonly description: "When true, include changed-file impact diagnostics such as symbol_granularity_violation, symbol_semantic_review_needed, source_file_unowned and requirement_statement_unverified (each current requirement the changed code implements, with its statement and firmness, since the check never compares code with a statement) in structured output.";
35
35
  };
36
36
  readonly maxDiagnostics: {
37
37
  readonly type: "integer";
@@ -30,7 +30,7 @@ export const checkSpec = {
30
30
  },
31
31
  includeImpactDiagnostics: {
32
32
  type: "boolean",
33
- description: "When true, include changed-file impact diagnostics such as symbol_granularity_violation, symbol_semantic_review_needed and source_file_unowned in structured output.",
33
+ description: "When true, include changed-file impact diagnostics such as symbol_granularity_violation, symbol_semantic_review_needed, source_file_unowned and requirement_statement_unverified (each current requirement the changed code implements, with its statement and firmness, since the check never compares code with a statement) in structured output.",
34
34
  },
35
35
  maxDiagnostics: {
36
36
  type: "integer",
@@ -8,7 +8,7 @@ export { executeCompileIntent } from "../../../operations/planning/compile-inten
8
8
  export declare const compileIntentSpec: {
9
9
  readonly name: "kb_compile_intent";
10
10
  readonly cliName: "compile-intent";
11
- readonly description: "Compile complete change intent into a deterministic, snapshot-bound read-only plan. Reuses intent-aware discovery and semantic modeling, accounts for every proposition, reports contradiction witnesses, proposes traceability links, and emits dependency-ordered kb_upsert-style steps only for resolved typed claims. No mutation side effects.";
11
+ readonly description: "Compile complete change intent into a deterministic, snapshot-bound read-only plan. Reuses intent-aware discovery and semantic modeling, accounts for every proposition, reports contradiction witnesses, proposes traceability links, and emits dependency-ordered kb_upsert-style steps only for resolved typed claims. contradictionAnalysis.outcome is no_conflict only when the check could decide: an unmodeled proposition or a related current requirement without logic leaves it unresolved with reasons and reviewCandidates to compare and judge through conflictReviews. No mutation side effects.";
12
12
  readonly businessInputSchema: {
13
13
  readonly type: "object";
14
14
  readonly required: readonly ["intent", "mode"];
@@ -234,6 +234,30 @@ export declare const compileIntentSpec: {
234
234
  };
235
235
  readonly description: "Explicit decisions for deterministic traceability proposals. Pending proposals never enter steps.";
236
236
  };
237
+ readonly conflictReviews: {
238
+ readonly type: "array";
239
+ readonly maxItems: 20;
240
+ readonly items: {
241
+ readonly type: "object";
242
+ readonly required: readonly ["requirementId", "verdict"];
243
+ readonly additionalProperties: false;
244
+ readonly properties: {
245
+ readonly requirementId: {
246
+ readonly type: "string";
247
+ readonly minLength: 1;
248
+ };
249
+ readonly verdict: {
250
+ readonly type: "string";
251
+ readonly enum: readonly ["conflict", "no_conflict"];
252
+ };
253
+ readonly note: {
254
+ readonly type: "string";
255
+ readonly maxLength: 2000;
256
+ };
257
+ };
258
+ };
259
+ readonly description: "Your verdict on each contradictionAnalysis.reviewCandidates entry of a previous compile: whether the intent contradicts that current requirement, which Kibi could not compare logically. A conflict verdict blocks the plan; a no_conflict verdict clears that candidate. A verdict may also name a current requirement discovery did not rank.";
260
+ };
237
261
  };
238
262
  };
239
263
  readonly requiresProlog: true;
@@ -1 +1 @@
1
- {"version":3,"file":"planning.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/planning.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,gBAAgB,EACjB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAGL,oBAAoB,EACrB,MAAM,gDAAgD,CAAC;AAGxD,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,oBAAoB,GACrB,MAAM,gDAAgD,CAAC;AACxD,YAAY,EACV,aAAa,EACb,eAAe,GAChB,MAAM,4CAA4C,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AAGtF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4KsC,CAAC;AAGrE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DwC,CAAC"}
1
+ {"version":3,"file":"planning.d.ts","sourceRoot":"","sources":["../../../../src/public/operations/specs/planning.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,gBAAgB,EACjB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAGL,oBAAoB,EACrB,MAAM,gDAAgD,CAAC;AAGxD,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,oBAAoB,GACrB,MAAM,gDAAgD,CAAC;AACxD,YAAY,EACV,aAAa,EACb,eAAe,GAChB,MAAM,4CAA4C,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gDAAgD,CAAC;AAGtF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4LsC,CAAC;AAGrE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DwC,CAAC"}
@@ -6,7 +6,7 @@ export { executeCompileIntent } from "../../../operations/planning/compile-inten
6
6
  export const compileIntentSpec = {
7
7
  name: "kb_compile_intent",
8
8
  cliName: "compile-intent",
9
- description: "Compile complete change intent into a deterministic, snapshot-bound read-only plan. Reuses intent-aware discovery and semantic modeling, accounts for every proposition, reports contradiction witnesses, proposes traceability links, and emits dependency-ordered kb_upsert-style steps only for resolved typed claims. No mutation side effects.",
9
+ description: "Compile complete change intent into a deterministic, snapshot-bound read-only plan. Reuses intent-aware discovery and semantic modeling, accounts for every proposition, reports contradiction witnesses, proposes traceability links, and emits dependency-ordered kb_upsert-style steps only for resolved typed claims. contradictionAnalysis.outcome is no_conflict only when the check could decide: an unmodeled proposition or a related current requirement without logic leaves it unresolved with reasons and reviewCandidates to compare and judge through conflictReviews. No mutation side effects.",
10
10
  businessInputSchema: {
11
11
  type: "object",
12
12
  required: ["intent", "mode"],
@@ -154,6 +154,21 @@ export const compileIntentSpec = {
154
154
  },
155
155
  description: "Explicit decisions for deterministic traceability proposals. Pending proposals never enter steps.",
156
156
  },
157
+ conflictReviews: {
158
+ type: "array",
159
+ maxItems: 20,
160
+ items: {
161
+ type: "object",
162
+ required: ["requirementId", "verdict"],
163
+ additionalProperties: false,
164
+ properties: {
165
+ requirementId: { type: "string", minLength: 1 },
166
+ verdict: { type: "string", enum: ["conflict", "no_conflict"] },
167
+ note: { type: "string", maxLength: 2000 },
168
+ },
169
+ },
170
+ description: "Your verdict on each contradictionAnalysis.reviewCandidates entry of a previous compile: whether the intent contradicts that current requirement, which Kibi could not compare logically. A conflict verdict blocks the plan; a no_conflict verdict clears that candidate. A verdict may also name a current requirement discovery did not rank.",
171
+ },
157
172
  },
158
173
  },
159
174
  requiresProlog: true,
@@ -2,7 +2,7 @@
2
2
  id: kibi-bootstrap
3
3
  name: kibi-bootstrap
4
4
  description: "Use for any Kibi bootstrap or onboarding task: seeding a new or thin knowledge base; reviewing a bootstrap or onboarding plan, preview, or evidence; judging approval readiness or coverage; diagnosing a blocked, partial, or failed bootstrap or its repair; applying an approved bootstrap plan; or asking the human which knowledge sources hold intent. Covers kb_status first, source interview, cited intent claims, read-only kb_plan_bootstrap preview, explicit approval, exact-plan kb_apply_plan, and repair-safe close-out."
5
- version: 3.14.0
5
+ version: 3.16.0
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -37,7 +37,7 @@ Seed branch-local Kibi knowledge from cited product intent, without creating a p
37
37
  3. **Declare** `bootstrapContext`: `projectSummary`; `knowledgeSources` (id, kind, title, locator, authority, optional connector, optional `component`); `intentClaims` (statement, sourceId, reference, `excerpt` required for `intent` and `observation` claims and optional for `open_question`, optional `kind`, default `intent`, optional `component` overriding the source's, optional `rationale` with the reason the source or the human gave, never invented); `conflicts` (`claimReferences` naming two or more declared claims by sourceId and reference, plus a one-sentence `note`). Only intent claims can become requirements, and they are recorded as the people's rules: `origin.kind: import` with `sourceId:reference` as `origin.ref`, and `firmness: firm`, so a later agent asks before changing one (normative lines from repository Markdown get the same, citing `path#Lline`). Observations, open questions (tagged `review:open-question`) and conflicts (tagged `review:conflict`) become cited observation facts. Generated subject keys take the shape `component.aspect`: name the component each source or claim is about (for example `recorder`; set `component` on the knowledge source, or on a claim to override it; repository Markdown takes its file or directory name), because an intent claim whose subject is neither one word nor already dotted, with no component, is reported in the plan diagnostics and left as an authoring follow-up instead of a malformed key. The aspect is the claim's subject, or its constrained property when the subject is the component itself. An aspect over four words or 40 characters is shortened to a noun phrase (words before `when`, `while`, `for`, `and`, ...; `support_inbox.update_in_real_time_when_a_new_ticket_is_assigned...` becomes `support_inbox.update_in_real_time`) and reported as `subject-key-shortened:` with both keys; two different subjects that shorten alike get a third segment (`editor.discard_a_draft.leaving`) and a `subject-key-disambiguated:` diagnostic; claims about one subject share one subject fact, and a `subject-key-shared:` diagnostic names the key and its sources. Show these diagnostics to the human with the plan so they can rename a key before approval. Kibi never contacts these sources. It binds your declaration into the plan hash.
38
38
  4. **Preview** with `kb_plan_bootstrap` (or `plan-bootstrap --input`), read-only. On `needs_context`, ask only its bounded questions (four at most), then preview again. When `pluginOffers` is non-empty (for example `kibi-plugin-ui` because UI component files exist), ask the human once whether to enable each offered plugin, naming its evidence files. On yes, install it as a dev dependency and add it to `package.json` `kibi.plugins` with the offered capability in `augment` mode; on no, add its name to `kibi.declinedPlugins` so it is not offered again. Either way the human decides; never enable a plugin unasked. For `kibi-plugin-ui`, step 11 also captures the UI pattern inventory (see `kibi-usage` `resources/ui-requirements.md`).
39
39
  5. **Narrow with filters, not caps.** Read the `tldr` and the `Suppressed candidates by reason` diagnostic before individual rows. If the output is too large or mostly tooling or metadata, re-preview with `entityTypes` or declared `sourceOfTruthPaths`. Generic Markdown is off by default once you declare intent claims; set `includeGenericMarkdown: true` only for repository docs the human named. Keep confirmed intent claims: they are never capped and never use `maxCandidates`, which is the separate budget for candidates Kibi discovers (symbols, tests, repository docs). Raise it only when discovered candidates you need are `over_limit`, and never for provenance stubs: a provider entry with no claim (`Source module: …`, repository metadata, layout roots) is planned last as a `meta` fact tagged `bootstrap:provenance-stub`, `discoverySummary.provenanceStubs` counts them apart from `candidatesWithClaims`, and the `over_limit` diagnostic says how many suppressed candidates are stubs; they add no knowledge, so a plan that is mostly stubs needs `entityTypes` or declared sources, not a higher cap. Read the per-source `Knowledge source …` diagnostics: each splits the claims not planned by reason (suppressed by the activation mode, a `suppressedCandidates` row, a `sourceOnlySignals` follow-up). Report them per source and restate them before approval, or carry them to step 11 with their citation.
40
- 6. **Request approval.** Show the complete `structuredContent.plan`, the full hash (never abbreviated), which candidates cite which sources, what was omitted, the open questions and declared conflicts it records for the human to decide, and any claim that contradicts code. If you find an undeclared contradiction now, add it to `conflicts` and preview again rather than resolving it. With no answer, stop as "awaiting approval." If declined, replan and ask again with the new hash.
40
+ 6. **Request approval.** Show the complete `structuredContent.plan`, the full hash (never abbreviated), which candidates cite which sources, what was omitted, the open questions and declared conflicts it records for the human to decide, and any claim that contradicts code. If you find an undeclared contradiction now, add it to `conflicts` and preview again rather than resolving it. A `conflict-review:` diagnostic (and `review_against:<id>` evidence on the candidate) names current requirements Kibi could not check a planned claim against because they have no logic: compare each pair yourself and show any contradiction to the human with the plan; they decide whether to drop the claim or keep it and supersede the requirement after apply. A claim left for authoring gets the same diagnostic (and `review_against:<id>` evidence on its follow-up): when you compile it with `kb_compile_intent` in step 11, compare it with the named requirements and send your verdicts in `conflictReviews`. With no answer, stop as "awaiting approval." If declined, replan and ask again with the new hash.
41
41
  7. **Pre-apply check.** The plan you send must equal the returned plan: every top-level field, including `suppressedCandidates`, `diagnostics`, `candidates`, `actions`, and `expected`, with every array the same length and order. Never rebuild it from preview fields. If the host cannot pass the exact object, stop and say so.
42
42
  8. **Apply once** with `kb_apply_plan`, the exact plan, and `approvedPlanHash`. The operation owns dependency ordering, source-first writes, sequential mutation, and recovery journaling. A plan with hundreds of actions can run for minutes: pass a `progressToken` (Kibi sends progress after each action) with a client that resets its timeout on progress, or pass `async: true` and poll `kb_job_status` when the host has it. If the apply is cut off, call `kb_apply_plan` with only the `recoveryJournalId` from `kb_status` or the error; it resumes an action interrupted mid-write and reclaims a lock left by a dead process. Never edit or delete `.kb/recovery` files; if recovery is refused, stop and report it.
43
43
  9. **Read back** with `kb_query` and `kb_search` to confirm writes and citations.
@@ -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.19.0
5
+ version: 2.20.0
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -410,6 +410,16 @@ Conditional clauses ("only when", "only if", "must not ... unless") compile
410
410
  into typed `forbid` rules linked by `requires_rule`, not property facts; one
411
411
  `kb_model` or `kb_compile_intent` cannot translate stays an `ontology_gap`.
412
412
 
413
+ `kb_compile_intent` reports `contradictionAnalysis.outcome: no_conflict` only
414
+ when it could check: Prolog compares only requirements with logic links. When
415
+ the intent is unmodeled or a related current requirement is prose only, the
416
+ outcome is `unresolved` with `reasons` and up to five `reviewCandidates`. Never
417
+ read `unresolved` as consistent. Compare the intent with each candidate's
418
+ `statement`, then compile again with `conflictReviews`
419
+ (`{requirementId, verdict: "conflict" | "no_conflict", note}`). On a conflict
420
+ the plan is `blocked`: ask the human which rule holds (a firm requirement is
421
+ theirs), then supersede or change it, or change the intent.
422
+
413
423
  ## Semantic and proof guardrails
414
424
 
415
425
  Prolog proves only encoded facts. Keep ambiguity, ontology gaps, incomplete
@@ -16,6 +16,11 @@ export declare function isAllowedGranularityReason(value: unknown): value is Gra
16
16
  export declare function isCoarseGranularityReason(value: unknown): value is CoarseGranularityReason;
17
17
  export declare function getSymbolRole(candidate: GranularSymbolCandidate): SymbolRole;
18
18
  export declare function isBehavioralSymbol(candidate: GranularSymbolCandidate): boolean;
19
+ /**
20
+ * The behavioral candidates' names, the place a coarse link should move to:
21
+ * functions, methods and accessors first, then properties (behavioral in the
22
+ * schema, but usually plain fields), each group sorted by name.
23
+ */
19
24
  export declare function getBehavioralSymbolNames(candidates: GranularSymbolCandidate[]): string[];
20
25
  /**
21
26
  * The candidates that are narrower than a manifest symbol: members of it
@@ -1 +1 @@
1
- {"version":3,"file":"symbol-granularity.d.ts","sourceRoot":"","sources":["../../src/public/symbol-granularity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,cAAc,EACd,YAAY,EACZ,KAAK,UAAU,EACf,+BAA+B,EAC/B,KAAK,4BAA4B,EAClC,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,cAAc,EACd,YAAY,EACZ,+BAA+B,GAChC,CAAC;AACF,YAAY,EACV,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,4BAA4B,GAC7B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,OAAO,GACP,QAAQ,GACR,UAAU,GACV,UAAU,GACV,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAYD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAE5D;AAED,eAAO,MAAM,uBAAuB,wBAAkB,CAAC;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAIhE;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,4BAA4B,CAIvC;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,iBAAiB,CAE5B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,uBAAuB,CAElC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,uBAAuB,GAAG,UAAU,CAI5E;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,uBAAuB,GACjC,OAAO,CAET;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAMV;AAED;;;;GAIG;AAEH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACxD,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,SAAS,CAAC,EAAE,EACxB,aAAa,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACzC,CAAC,EAAE,CASL;AAED;;;;;GAKG;AAEH,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,SAAS,uBAAuB,EAAE,GAChD,MAAM,EAAE,CAIV;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAQV"}
1
+ {"version":3,"file":"symbol-granularity.d.ts","sourceRoot":"","sources":["../../src/public/symbol-granularity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,cAAc,EACd,YAAY,EACZ,KAAK,UAAU,EACf,+BAA+B,EAC/B,KAAK,4BAA4B,EAClC,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EACL,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,wCAAwC,EACxC,gCAAgC,EAChC,cAAc,EACd,YAAY,EACZ,+BAA+B,GAChC,CAAC;AACF,YAAY,EACV,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,4BAA4B,GAC7B,MAAM,mCAAmC,CAAC;AAE3C,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,OAAO,GACP,QAAQ,GACR,UAAU,GACV,UAAU,GACV,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE1C,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAYD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAE5D;AAED,eAAO,MAAM,uBAAuB,wBAAkB,CAAC;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAIhE;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,4BAA4B,CAIvC;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,iBAAiB,CAE5B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,uBAAuB,CAElC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,uBAAuB,GAAG,UAAU,CAI5E;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,uBAAuB,GACjC,OAAO,CAET;AAED;;;;GAIG;AAEH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAQV;AAED;;;;GAIG;AAEH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACxD,kBAAkB,EAAE,MAAM,EAC1B,UAAU,EAAE,SAAS,CAAC,EAAE,EACxB,aAAa,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACzC,CAAC,EAAE,CASL;AAED;;;;;GAKG;AAEH,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,SAAS,uBAAuB,EAAE,GAChD,MAAM,EAAE,CAIV;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,uBAAuB,EAAE,GACpC,MAAM,EAAE,CAQV"}
@@ -32,10 +32,19 @@ export function getSymbolRole(candidate) {
32
32
  export function isBehavioralSymbol(candidate) {
33
33
  return getSymbolRole(candidate) === "behavioral";
34
34
  }
35
+ /**
36
+ * The behavioral candidates' names, the place a coarse link should move to:
37
+ * functions, methods and accessors first, then properties (behavioral in the
38
+ * schema, but usually plain fields), each group sorted by name.
39
+ */
40
+ // implements REQ-kibi-symbol-link-guidance
35
41
  export function getBehavioralSymbolNames(candidates) {
36
- return [
37
- ...new Set(candidates.filter(isBehavioralSymbol).map((candidate) => candidate.name)),
38
- ].sort();
42
+ const behavioral = candidates.filter(isBehavioralSymbol);
43
+ const names = (properties) => behavioral
44
+ .filter((candidate) => (candidate.kind === "property") === properties)
45
+ .map((candidate) => candidate.name)
46
+ .sort();
47
+ return [...new Set([...names(false), ...names(true)])];
39
48
  }
40
49
  /**
41
50
  * The candidates that are narrower than a manifest symbol: members of it
@@ -20,6 +20,6 @@ export declare function stagesKnowledge(paths: readonly string[]): boolean;
20
20
  */
21
21
  export declare function collectIntroducedConsistencyViolations(snapshot: SnapshotReader, headKnowledge: ExtractionResult[]): Promise<Violation[]>;
22
22
  /** Text lines for introduced consistency violations, in `kibi check` form. */
23
- export declare function formatConsistencyViolations(violations: readonly Violation[]): string[];
23
+ export declare function formatConsistencyViolations(violations: readonly Violation[], kind?: string): string[];
24
24
  export {};
25
25
  //# sourceMappingURL=staged-consistency.d.ts.map
@@ -1 +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"}
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,EAChC,IAAI,SAAgB,GACnB,MAAM,EAAE,CAWV"}
@@ -77,9 +77,9 @@ export async function collectIntroducedConsistencyViolations(snapshot, headKnowl
77
77
  }
78
78
  /** Text lines for introduced consistency violations, in `kibi check` form. */
79
79
  // implements REQ-cli-staged-consistency
80
- export function formatConsistencyViolations(violations) {
80
+ export function formatConsistencyViolations(violations, kind = "consistency") {
81
81
  const lines = [
82
- `Found ${violations.length} consistency violation(s) introduced by the staged changes:`,
82
+ `Found ${violations.length} ${kind} violation(s) introduced by the staged changes:`,
83
83
  "",
84
84
  ];
85
85
  for (const violation of violations) {
@@ -1,6 +1,6 @@
1
1
  import type { QualityDiagnostic } from "../public/impact/types.js";
2
2
  import { type KibiImpactEvidence } from "./evidence-model.js";
3
- export type KibiImpactDiagnosticId = "kibi_impact_evidence_missing" | "symbols_manifest_stale" | "symbol_granularity_violation" | "symbol_semantic_review_needed" | "source_file_unowned" | "multi_requirement_symbol_review" | "duplicate_symbol_coordinate_review" | "component_mixed_purpose_review" | "broad_requirement_review" | "requirement_status_review" | "strict_fact_modeling_review" | "logical_coverage_review" | "kibi_impact_override_missing_rationale" | "entity_id_style_review";
3
+ export type KibiImpactDiagnosticId = "kibi_impact_evidence_missing" | "symbols_manifest_stale" | "symbol_granularity_violation" | "symbol_semantic_review_needed" | "source_file_unowned" | "requirement_statement_unverified" | "multi_requirement_symbol_review" | "duplicate_symbol_coordinate_review" | "component_mixed_purpose_review" | "broad_requirement_review" | "requirement_status_review" | "strict_fact_modeling_review" | "logical_coverage_review" | "kibi_impact_override_missing_rationale" | "entity_id_style_review";
4
4
  export interface KibiImpactDiagnostic extends QualityDiagnostic {
5
5
  /** Stable staged-enforcement diagnostic identifier. */
6
6
  id: KibiImpactDiagnosticId;
@@ -1 +1 @@
1
- {"version":3,"file":"staged-diagnostics.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAGL,KAAK,kBAAkB,EAKxB,MAAM,qBAAqB,CAAC;AAQ7B,MAAM,MAAM,sBAAsB,GAC9B,8BAA8B,GAC9B,wBAAwB,GACxB,8BAA8B,GAC9B,+BAA+B,GAC/B,qBAAqB,GACrB,iCAAiC,GACjC,oCAAoC,GACpC,gCAAgC,GAChC,0BAA0B,GAC1B,2BAA2B,GAC3B,6BAA6B,GAC7B,yBAAyB,GACzB,wCAAwC,GACxC,wBAAwB,CAAC;AAE7B,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,uDAAuD;IACvD,EAAE,EAAE,sBAAsB,CAAC;IAC3B,QAAQ,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACxC,iEAAiE;IACjE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,gDAAgD;IAChD,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAsID,wBAAgB,wCAAwC,CACtD,QAAQ,EAAE,kBAAkB,GAC3B,oBAAoB,CAoBtB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,kBAAkB,EAC5B,mBAAmB,GAAE,MAAmC,GACvD,oBAAoB,EAAE,CAiDxB"}
1
+ {"version":3,"file":"staged-diagnostics.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAGL,KAAK,kBAAkB,EAKxB,MAAM,qBAAqB,CAAC;AAQ7B,MAAM,MAAM,sBAAsB,GAC9B,8BAA8B,GAC9B,wBAAwB,GACxB,8BAA8B,GAC9B,+BAA+B,GAC/B,qBAAqB,GACrB,kCAAkC,GAClC,iCAAiC,GACjC,oCAAoC,GACpC,gCAAgC,GAChC,0BAA0B,GAC1B,2BAA2B,GAC3B,6BAA6B,GAC7B,yBAAyB,GACzB,wCAAwC,GACxC,wBAAwB,CAAC;AAE7B,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,uDAAuD;IACvD,EAAE,EAAE,sBAAsB,CAAC;IAC3B,QAAQ,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACxC,iEAAiE;IACjE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,gDAAgD;IAChD,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAsID,wBAAgB,wCAAwC,CACtD,QAAQ,EAAE,kBAAkB,GAC3B,oBAAoB,CAoBtB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,kBAAkB,EAC5B,mBAAmB,GAAE,MAAmC,GACvD,oBAAoB,EAAE,CAiDxB"}
@@ -0,0 +1,18 @@
1
+ import type { ExtractionResult } from "../extractors/markdown.js";
2
+ import type { Violation } from "../public/check-types.js";
3
+ type TreeReader = Readonly<{
4
+ baseTree: string;
5
+ headTree: string;
6
+ readGit(args: readonly string[]): Buffer;
7
+ }>;
8
+ /**
9
+ * entity-context-missing findings on the entity documents a commit stages,
10
+ * that the same documents did not have at the base tree. The rule reads only
11
+ * the entity file, so no projection is needed. A document whose entity
12
+ * already lacked context at the base (legacy debt, or one the migration
13
+ * acknowledged) does not block the commit; full `kibi check` still reports
14
+ * it.
15
+ */
16
+ export declare function collectIntroducedEntityContextViolations(snapshot: TreeReader, stagedPaths: readonly string[], headKnowledge: readonly ExtractionResult[]): Violation[];
17
+ export {};
18
+ //# sourceMappingURL=staged-entity-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staged-entity-context.d.ts","sourceRoot":"","sources":["../../src/traceability/staged-entity-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAO1D,KAAK,UAAU,GAAG,QAAQ,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC;CAC1C,CAAC,CAAC;AA8CH;;;;;;;GAOG;AAEH,wBAAgB,wCAAwC,CACtD,QAAQ,EAAE,UAAU,EACpB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,aAAa,EAAE,SAAS,gBAAgB,EAAE,GACzC,SAAS,EAAE,CA8Bb"}
@@ -0,0 +1,66 @@
1
+ import { CONTEXT_REQUIRED_TYPES } from "../entity-body-context.js";
2
+ import { ENTITY_CONTEXT_MISSING_RULE, evaluateEntityContext, readAuthoredEntity, } from "../public/operations/entity-context.js";
3
+ function readTreeFile(snapshot, tree, file) {
4
+ try {
5
+ return snapshot.readGit(["show", `${tree}:${file}`]).toString("utf8");
6
+ }
7
+ catch {
8
+ return null;
9
+ }
10
+ }
11
+ /**
12
+ * The ids the schema 8 body-context migration acknowledged, from the KB
13
+ * manifest of one tree: they stay exempt, so a migration commit passes.
14
+ */
15
+ // implements REQ-cli-staged-entity-context
16
+ function acknowledgedIds(snapshot, tree) {
17
+ const text = readTreeFile(snapshot, tree, ".kb/manifest.json");
18
+ if (text === null)
19
+ return new Set();
20
+ try {
21
+ const parsed = JSON.parse(text);
22
+ return new Set(Array.isArray(parsed.contextAcknowledged)
23
+ ? parsed.contextAcknowledged.filter((id) => typeof id === "string")
24
+ : []);
25
+ }
26
+ catch {
27
+ return new Set();
28
+ }
29
+ }
30
+ /** Ids another entity supersedes in the given compiled knowledge. */
31
+ // implements REQ-cli-staged-entity-context
32
+ function supersededIds(knowledge) {
33
+ const superseded = new Set();
34
+ for (const result of knowledge)
35
+ for (const relationship of result.relationships)
36
+ if (relationship.type === "supersedes")
37
+ superseded.add(relationship.to);
38
+ return superseded;
39
+ }
40
+ /**
41
+ * entity-context-missing findings on the entity documents a commit stages,
42
+ * that the same documents did not have at the base tree. The rule reads only
43
+ * the entity file, so no projection is needed. A document whose entity
44
+ * already lacked context at the base (legacy debt, or one the migration
45
+ * acknowledged) does not block the commit; full `kibi check` still reports
46
+ * it.
47
+ */
48
+ // implements REQ-cli-staged-entity-context
49
+ export function collectIntroducedEntityContextViolations(snapshot, stagedPaths, headKnowledge) {
50
+ const rules = new Set([ENTITY_CONTEXT_MISSING_RULE]);
51
+ const read = (tree) => stagedPaths.flatMap((file) => {
52
+ const content = readTreeFile(snapshot, tree, file);
53
+ const entity = content === null ? null : readAuthoredEntity(content, file);
54
+ return entity !== null &&
55
+ CONTEXT_REQUIRED_TYPES.includes(entity.type)
56
+ ? [entity]
57
+ : [];
58
+ });
59
+ const head = evaluateEntityContext(read(snapshot.headTree), supersededIds(headKnowledge), rules, acknowledgedIds(snapshot, snapshot.headTree));
60
+ if (head.length === 0)
61
+ return [];
62
+ // Without the base tree's supersessions the base reports at least what it
63
+ // had, so a finding the base already carried never blocks.
64
+ const base = new Set(evaluateEntityContext(read(snapshot.baseTree), new Set(), rules, acknowledgedIds(snapshot, snapshot.baseTree)).map((violation) => violation.entityId));
65
+ return head.filter((violation) => !base.has(violation.entityId));
66
+ }
@@ -35,6 +35,14 @@ export interface LegacyKbConfig {
35
35
  checks?: unknown;
36
36
  defaultBranch?: string;
37
37
  }
38
+ /**
39
+ * The first step on a workspace with a legacy `.kb/config.json` and no
40
+ * manifest. Doctor and kb_status both name it, so they never disagree on
41
+ * what to run first: `kibi init` would claim the latest schema and skip the
42
+ * legacy migration steps.
43
+ */
44
+ export declare const LEGACY_KB_MIGRATION_COMMAND = "kibi migrate --yes";
45
+ export declare const LEGACY_KB_MIGRATION_NOTE = "it creates the manifest from the legacy .kb/config.json; do not run kibi init first";
38
46
  /** Whether a legacy `.kb/config.json` exists at the workspace root. */
39
47
  export declare function legacyConfigExists(cwd: string): boolean;
40
48
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAoBA,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AAEvB;;;;;;GAMG;AAEH,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,EAAE,aAAsC,CAAC;AAE1E;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAsB,GAAG,aAAa,CAE3E;AAED,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,uBAAuB,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,gBAAgB,CAAC;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAcD,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,GAET;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAqE9C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,GAAG,SAAS,GACjC,aAAa,CAwBf"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAoBA,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,eAAe,CAAC;AAEvB;;;;;;GAMG;AAEH,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,EAAE,aAAsC,CAAC;AAE1E;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAsB,GAAG,aAAa,CAE3E;AAED,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,uBAAuB,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,gBAAgB,CAAC;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAcD;;;;;GAKG;AAEH,eAAO,MAAM,2BAA2B,uBAAuB,CAAC;AAEhE,eAAO,MAAM,wBAAwB,wFACkD,CAAC;AAExF,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,GAET;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAqE9C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,GAAG,SAAS,GACjC,aAAa,CAwBf"}
@@ -34,6 +34,16 @@ function pickLegacyPathValue(paths, key) {
34
34
  const value = paths[key];
35
35
  return typeof value === "string" ? value : undefined;
36
36
  }
37
+ /**
38
+ * The first step on a workspace with a legacy `.kb/config.json` and no
39
+ * manifest. Doctor and kb_status both name it, so they never disagree on
40
+ * what to run first: `kibi init` would claim the latest schema and skip the
41
+ * legacy migration steps.
42
+ */
43
+ // implements REQ-legacy-kb-first-step-migrate
44
+ export const LEGACY_KB_MIGRATION_COMMAND = "kibi migrate --yes";
45
+ // implements REQ-legacy-kb-first-step-migrate
46
+ export const LEGACY_KB_MIGRATION_NOTE = "it creates the manifest from the legacy .kb/config.json; do not run kibi init first";
37
47
  /** Whether a legacy `.kb/config.json` exists at the workspace root. */
38
48
  export function legacyConfigExists(cwd) {
39
49
  return existsSync(path.join(cwd, ".kb", "config.json"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cli",
3
- "version": "2.26.3",
3
+ "version": "2.28.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.22.2",
238
+ "kibi-core": "^0.22.3",
239
239
  "kibi-plugin-builtin": "^0.5.2",
240
240
  "kibi-plugin-sdk": "^0.5.0",
241
241
  "kibi-swipl": "^1.0.1",
@@ -20,6 +20,11 @@ import {
20
20
  createImpactManifestLookup,
21
21
  readImpactManifestResults,
22
22
  } from "./manifest.js";
23
+ import {
24
+ createRequirementStatementDiagnostics,
25
+ readWorkspaceRequirement,
26
+ workspaceFileChanged,
27
+ } from "./requirement-statements.js";
23
28
  import { normalizeSourceFile } from "./source-changes.js";
24
29
  import { collectSourceChanges, uniqueSorted } from "./source-changes.js";
25
30
  import {
@@ -34,6 +39,14 @@ import type {
34
39
  } from "./types.js";
35
40
  import { createUnownedFileDiagnostics } from "./unowned-files.js";
36
41
 
42
+ /** The workspace-relative document a requirement was read from. */
43
+ function requirementSourcePath(requirement: { id: string; source: string }) {
44
+ const source = requirement.source;
45
+ return source && !source.includes("://")
46
+ ? source.replace(/^\.\//, "")
47
+ : `.kb/requirements/${requirement.id}.md`;
48
+ }
49
+
37
50
  export async function analyzeChangedFileImpact(
38
51
  options: ChangedFileImpactOptions,
39
52
  ): Promise<ChangedFileImpactResult> {
@@ -88,12 +101,15 @@ export async function analyzeChangedFileImpact(
88
101
  .map((file) => file.path)
89
102
  : sourceChanges.map((change) => change.file),
90
103
  );
91
- const manifestResults = snapshot
104
+ const snapshotKnowledge = snapshot
92
105
  ? readSnapshotKnowledge(
93
106
  snapshot.readGit,
94
107
  snapshot.headTree,
95
108
  snapshot.readBlobs,
96
- ).filter((result) => result.entity.type === "symbol")
109
+ )
110
+ : undefined;
111
+ const manifestResults = snapshotKnowledge
112
+ ? snapshotKnowledge.filter((result) => result.entity.type === "symbol")
97
113
  : readImpactManifestResults(workspaceRoot);
98
114
  const manifestLookup = createImpactManifestLookup(manifestResults);
99
115
  const symbolsByFile = new Map<string, ExtractedSymbol[]>();
@@ -161,6 +177,26 @@ export async function analyzeChangedFileImpact(
161
177
  requestedFiles: [...filter],
162
178
  linkedSourceFiles,
163
179
  }),
180
+ // What the changed code is meant to do, quoted, before the
181
+ // structural findings: "no violations" never compared it.
182
+ ...createRequirementStatementDiagnostics({
183
+ workspaceRoot,
184
+ symbolsByFile,
185
+ readRequirement: (id) =>
186
+ snapshotKnowledge
187
+ ? snapshotKnowledge.find((result) => result.entity.id === id)
188
+ ?.entity
189
+ : readWorkspaceRequirement(workspaceRoot, id),
190
+ requirementChanged: (requirement) =>
191
+ snapshot
192
+ ? snapshot.inventory.some(
193
+ (file) => file.path === requirementSourcePath(requirement),
194
+ )
195
+ : workspaceFileChanged(
196
+ workspaceRoot,
197
+ requirementSourcePath(requirement),
198
+ ),
199
+ }),
164
200
  ...createSymbolGranularityDiagnostics({
165
201
  manifestResults: activeManifestResults,
166
202
  symbolsByFile,