kibi-cli 2.22.0 → 2.23.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 (142) hide show
  1. package/dist/cli-register-foundation.d.ts.map +1 -1
  2. package/dist/cli-register-foundation.js +1 -0
  3. package/dist/commands/check.d.ts.map +1 -1
  4. package/dist/commands/check.js +51 -3
  5. package/dist/commands/doctor.d.ts.map +1 -1
  6. package/dist/commands/doctor.js +40 -0
  7. package/dist/commands/init-helpers.d.ts +2 -1
  8. package/dist/commands/init-helpers.d.ts.map +1 -1
  9. package/dist/commands/init-helpers.js +3 -0
  10. package/dist/commands/migrate.d.ts +47 -0
  11. package/dist/commands/migrate.d.ts.map +1 -1
  12. package/dist/commands/migrate.js +82 -15
  13. package/dist/commands/sync.d.ts.map +1 -1
  14. package/dist/commands/sync.js +15 -1
  15. package/dist/extractors/markdown.d.ts.map +1 -1
  16. package/dist/extractors/markdown.js +37 -35
  17. package/dist/intent-search.d.ts.map +1 -1
  18. package/dist/intent-search.js +32 -4
  19. package/dist/operations/bootstrap/activation.d.ts +7 -1
  20. package/dist/operations/bootstrap/activation.d.ts.map +1 -1
  21. package/dist/operations/bootstrap/activation.js +27 -2
  22. package/dist/operations/bootstrap/generate.d.ts.map +1 -1
  23. package/dist/operations/bootstrap/generate.js +56 -16
  24. package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
  25. package/dist/operations/bootstrap/guidance-actions.js +14 -2
  26. package/dist/operations/bootstrap/guidance.d.ts.map +1 -1
  27. package/dist/operations/bootstrap/guidance.js +6 -2
  28. package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
  29. package/dist/operations/bootstrap/presentation.js +75 -9
  30. package/dist/operations/bootstrap/types.d.ts +6 -0
  31. package/dist/operations/bootstrap/types.d.ts.map +1 -1
  32. package/dist/operations/migration/kb-sources.d.ts +8 -5
  33. package/dist/operations/migration/kb-sources.d.ts.map +1 -1
  34. package/dist/operations/migration/kb-sources.js +50 -14
  35. package/dist/operations/migration/schema6.d.ts.map +1 -1
  36. package/dist/operations/migration/schema6.js +11 -2
  37. package/dist/operations/migration/source-paths.d.ts +18 -1
  38. package/dist/operations/migration/source-paths.d.ts.map +1 -1
  39. package/dist/operations/migration/source-paths.js +111 -16
  40. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  41. package/dist/operations/modeling/suggest-predicates.js +22 -7
  42. package/dist/operations/mutation/requirement-semantics.d.ts +16 -0
  43. package/dist/operations/mutation/requirement-semantics.d.ts.map +1 -1
  44. package/dist/operations/mutation/requirement-semantics.js +50 -0
  45. package/dist/operations/mutation/strict-fact.js +1 -1
  46. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  47. package/dist/operations/mutation/upsert.js +2 -1
  48. package/dist/operations/mutation/validation.d.ts.map +1 -1
  49. package/dist/operations/mutation/validation.js +43 -1
  50. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  51. package/dist/operations/planning/apply-plan.js +38 -9
  52. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  53. package/dist/operations/semantic-advisor/analyze-prose.js +49 -17
  54. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
  55. package/dist/operations/semantic-advisor/ingestion-boundary.js +25 -1
  56. package/dist/operations/semantic-advisor/stored-ledger-drift.d.ts +19 -0
  57. package/dist/operations/semantic-advisor/stored-ledger-drift.d.ts.map +1 -0
  58. package/dist/operations/semantic-advisor/stored-ledger-drift.js +78 -0
  59. package/dist/public/impact/analyzer.d.ts.map +1 -1
  60. package/dist/public/impact/analyzer.js +7 -1
  61. package/dist/public/impact/diagnostics.d.ts.map +1 -1
  62. package/dist/public/impact/diagnostics.js +16 -3
  63. package/dist/public/impact/types.d.ts +2 -0
  64. package/dist/public/impact/types.d.ts.map +1 -1
  65. package/dist/public/operations/catalog.d.ts +7 -2
  66. package/dist/public/operations/catalog.d.ts.map +1 -1
  67. package/dist/public/operations/check-executor.d.ts.map +1 -1
  68. package/dist/public/operations/check-executor.js +10 -3
  69. package/dist/public/operations/check-helpers.d.ts +10 -0
  70. package/dist/public/operations/check-helpers.d.ts.map +1 -1
  71. package/dist/public/operations/check-helpers.js +54 -0
  72. package/dist/public/operations/contracts.d.ts.map +1 -1
  73. package/dist/public/operations/contracts.js +1 -0
  74. package/dist/public/operations/decision-firmness.d.ts +3 -1
  75. package/dist/public/operations/decision-firmness.d.ts.map +1 -1
  76. package/dist/public/operations/decision-firmness.js +13 -3
  77. package/dist/public/operations/discovery-executors.d.ts +18 -0
  78. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  79. package/dist/public/operations/discovery-executors.js +77 -3
  80. package/dist/public/operations/migration-plan.d.ts +13 -0
  81. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  82. package/dist/public/operations/migration-plan.js +29 -1
  83. package/dist/public/operations/schema6-check-actions.d.ts +4 -0
  84. package/dist/public/operations/schema6-check-actions.d.ts.map +1 -1
  85. package/dist/public/operations/schema6-check-actions.js +39 -2
  86. package/dist/public/operations/source-path-dangling.d.ts +1 -1
  87. package/dist/public/operations/source-path-dangling.d.ts.map +1 -1
  88. package/dist/public/operations/source-path-dangling.js +11 -2
  89. package/dist/public/operations/specs/composite.d.ts +1 -1
  90. package/dist/public/operations/specs/discovery.d.ts +5 -0
  91. package/dist/public/operations/specs/discovery.d.ts.map +1 -1
  92. package/dist/public/operations/specs/discovery.js +5 -0
  93. package/dist/public/operations/specs/planning.d.ts +1 -1
  94. package/dist/public/operations/specs/planning.js +1 -1
  95. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  96. package/dist/public/operations/specs/reporting.js +6 -4
  97. package/dist/public/operations/specs/semantic.d.ts +1 -1
  98. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  99. package/dist/public/operations/specs/semantic.js +30 -3
  100. package/dist/public/skills/kibi-bootstrap/SKILL.md +3 -2
  101. package/dist/public/skills/kibi-usage/SKILL.md +13 -5
  102. package/dist/public/skills/kibi-usage/resources/workflows.md +3 -1
  103. package/dist/search-answer.d.ts +14 -0
  104. package/dist/search-answer.d.ts.map +1 -1
  105. package/dist/search-answer.js +42 -4
  106. package/dist/traceability/git-change-snapshot.d.ts +46 -0
  107. package/dist/traceability/git-change-snapshot.d.ts.map +1 -1
  108. package/dist/traceability/git-change-snapshot.js +187 -3
  109. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  110. package/dist/traceability/staged-diagnostics.js +5 -6
  111. package/dist/traceability/staged-inventory-drift.d.ts +24 -0
  112. package/dist/traceability/staged-inventory-drift.d.ts.map +1 -0
  113. package/dist/traceability/staged-inventory-drift.js +84 -0
  114. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  115. package/dist/traceability/staged-symbols-manifest.js +1 -2
  116. package/dist/utils/content-freshness.d.ts +9 -0
  117. package/dist/utils/content-freshness.d.ts.map +1 -1
  118. package/dist/utils/content-freshness.js +33 -0
  119. package/dist/utils/merge-driver-setup.d.ts +10 -0
  120. package/dist/utils/merge-driver-setup.d.ts.map +1 -0
  121. package/dist/utils/merge-driver-setup.js +69 -0
  122. package/dist/utils/rule-registry.generated.d.ts +1 -1
  123. package/dist/utils/rule-registry.generated.js +1 -1
  124. package/package.json +2 -2
  125. package/src/public/impact/analyzer.ts +13 -1
  126. package/src/public/impact/diagnostics.ts +20 -3
  127. package/src/public/impact/types.ts +2 -0
  128. package/src/public/operations/check-executor.ts +16 -4
  129. package/src/public/operations/check-helpers.ts +65 -0
  130. package/src/public/operations/contracts.ts +1 -0
  131. package/src/public/operations/decision-firmness.ts +18 -2
  132. package/src/public/operations/discovery-executors.ts +113 -3
  133. package/src/public/operations/migration-plan.ts +47 -1
  134. package/src/public/operations/schema6-check-actions.ts +43 -2
  135. package/src/public/operations/source-path-dangling.ts +12 -2
  136. package/src/public/operations/specs/discovery.ts +6 -0
  137. package/src/public/operations/specs/planning.ts +1 -1
  138. package/src/public/operations/specs/reporting.ts +6 -4
  139. package/src/public/operations/specs/semantic.ts +41 -4
  140. package/src/public/skills/kibi-bootstrap/SKILL.md +3 -2
  141. package/src/public/skills/kibi-usage/SKILL.md +13 -5
  142. package/src/public/skills/kibi-usage/resources/workflows.md +3 -1
@@ -234,23 +234,36 @@ function isVerificationScope(value) {
234
234
  function isVerificationPerspective(value) {
235
235
  return value === "internal" || value === "consumer";
236
236
  }
237
- function parseFrontmatter(content) {
237
+ /**
238
+ * Splits a document into its front matter block and body. Delimiters are
239
+ * whole lines of `---`; a `---` glued onto a value (`priority: must---`) or
240
+ * inside a value does not close the block.
241
+ */
242
+ function splitFrontmatter(content) {
238
243
  const trimmedStart = content.trimStart();
239
- if (!trimmedStart.startsWith("---")) {
240
- return { data: {}, content };
244
+ const opening = /^---[^\S\r\n]*(?:\r?\n|$)/.exec(trimmedStart);
245
+ if (!opening) {
246
+ return null;
241
247
  }
242
- const parts = trimmedStart.split("---");
243
- if (parts.length < 3) {
244
- return { data: {}, content };
248
+ const rest = trimmedStart.slice(opening[0].length);
249
+ const closing = /^---[^\S\r\n]*(?:\r?\n|$)/m.exec(rest);
250
+ if (!closing) {
251
+ return "unclosed";
245
252
  }
246
- const frontmatter = parts[1];
247
- if (frontmatter === undefined) {
253
+ return {
254
+ frontmatter: rest.slice(0, closing.index),
255
+ body: rest.slice(closing.index + closing[0].length),
256
+ };
257
+ }
258
+ function parseFrontmatter(content) {
259
+ const split = splitFrontmatter(content);
260
+ if (split === null || split === "unclosed") {
248
261
  return { data: {}, content };
249
262
  }
250
- const parsed = yamlLoad(frontmatter);
263
+ const parsed = yamlLoad(split.frontmatter);
251
264
  return {
252
265
  data: isObjectRecord(parsed) ? parsed : {},
253
- content: parts.slice(2).join("---"),
266
+ content: split.body,
254
267
  };
255
268
  }
256
269
  /**
@@ -280,14 +293,12 @@ export function requirementSemanticText(body) {
280
293
  return legacyRequirementSemanticText(withoutContextSections(body));
281
294
  }
282
295
  function hasLikelyUnquotedColonInTitle(content) {
283
- if (!content.trim().startsWith("---")) {
284
- return false;
285
- }
286
- const parts = content.split("---");
287
- if (parts.length < 2) {
288
- return false;
289
- }
290
- const frontmatter = parts[1];
296
+ const split = splitFrontmatter(content);
297
+ const frontmatter = split === null
298
+ ? undefined
299
+ : split === "unclosed"
300
+ ? content
301
+ : split.frontmatter;
291
302
  return frontmatter
292
303
  ? /^\s*title:\s*(?!["'])(?![>|])[^#\n]*:\s+\S.*$/m.test(frontmatter)
293
304
  : false;
@@ -343,16 +354,13 @@ data, entityType) {
343
354
  // implements REQ-007, REQ-004
344
355
  function extractFromMarkdownContent(content, filePath) {
345
356
  try {
346
- const { data, content: body } = parseFrontmatter(content);
347
- if (content.trim().startsWith("---")) {
348
- const parts = content.split("---");
349
- if (parts.length < 3) {
350
- throw new FrontmatterError("Missing closing --- delimiter", filePath, {
351
- classification: "Missing closing ---",
352
- hint: "Ensure the frontmatter is enclosed between two '---' delimiters.",
353
- });
354
- }
357
+ if (splitFrontmatter(content) === "unclosed") {
358
+ throw new FrontmatterError("Missing closing --- delimiter", filePath, {
359
+ classification: "Missing closing ---",
360
+ hint: "Ensure the frontmatter is enclosed between two '---' delimiter lines; a '---' appended to the last value does not close it.",
361
+ });
355
362
  }
363
+ const { data, content: body } = parseFrontmatter(content);
356
364
  const type = data.type || inferTypeFromPath(filePath);
357
365
  if (!type) {
358
366
  throw new FrontmatterError("Could not determine entity type from path or frontmatter", filePath, {
@@ -717,14 +725,8 @@ function extractFromMarkdownContent(content, filePath) {
717
725
  hint =
718
726
  'Wrap values containing colons in quotes (e.g., title: "Foo: Bar").';
719
727
  }
720
- else if (!content.trim().startsWith("---") ||
721
- content.split("---").length < 3) {
722
- if (content.trim().startsWith("---") &&
723
- content.split("---").length < 3) {
724
- classification = "Missing closing ---";
725
- hint =
726
- "Ensure the frontmatter is enclosed between two '---' delimiters.";
727
- }
728
+ else if (splitFrontmatter(content) === null) {
729
+ // No front matter block: keep the generic classification.
728
730
  }
729
731
  else if (message.includes("unexpected end of the stream") ||
730
732
  message.includes("flow collection") ||
@@ -1 +1 @@
1
- {"version":3,"file":"intent-search.d.ts","sourceRoot":"","sources":["../src/intent-search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"intent-search.d.ts","sourceRoot":"","sources":["../src/intent-search.ts"],"names":[],"mappings":"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"}
@@ -116,8 +116,35 @@ const AMBIGUOUS_MARGIN = 0.05;
116
116
  const MAX_CANDIDATES = 10_000;
117
117
  const MAX_GRAPH_SEEDS = 5;
118
118
  const MAX_GRAPH_EDGES = 2_000;
119
+ // A code identifier names its words without spaces ("canExport",
120
+ // "toggleViewMode"). An entity keeps it whole and also reads it word by
121
+ // word; a question reads it word by word only, so the identifier does not
122
+ // weigh twice. A question about a helper then meets the requirement that
123
+ // uses its words.
124
+ const CAMEL_IDENTIFIER = /[A-Za-z0-9]*[a-z0-9][A-Z][A-Za-z0-9]*/g;
125
+ function splitIdentifier(identifier) {
126
+ return identifier.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
127
+ }
128
+ function expandIdentifiers(value) {
129
+ return value.replace(CAMEL_IDENTIFIER, (identifier) => `${identifier} ${splitIdentifier(identifier)}`);
130
+ }
131
+ /**
132
+ * The question's topic text: identifiers expanded, and the paths it also
133
+ * passes as `sourceLocations` removed. Those paths already reach the
134
+ * search as source evidence; their words ("src", "services", "ts") are not
135
+ * the topic and would only dilute the words that are.
136
+ */
137
+ function topicText(query, locations = []) {
138
+ let topic = query;
139
+ for (const location of locations) {
140
+ const located = location.path.replace(/^\.\//, "");
141
+ if (located.length > 0)
142
+ topic = topic.split(located).join(" ");
143
+ }
144
+ return topic.replace(CAMEL_IDENTIFIER, splitIdentifier);
145
+ }
119
146
  function normalize(value) {
120
- return value
147
+ return expandIdentifiers(value)
121
148
  .trim()
122
149
  .toLowerCase()
123
150
  .replace(/[-_]+/g, " ")
@@ -406,13 +433,14 @@ async function readBodies(entities, workspaceRoot, cache) {
406
433
  }
407
434
  // implements REQ-kibi-intent-aware-source-discovery, REQ-bootstrap-provenance-stubs
408
435
  export async function rankIntentEntities(entities, options, workspaceRoot, graphEdges = [], bodyCache = new Map()) {
409
- const queryTokens = tokens(options.query);
436
+ const query = topicText(options.query, options.sourceLocations);
437
+ const queryTokens = tokens(query);
410
438
  const facets = facetValues(options.semanticFacets);
411
439
  const facetTokens = facets.flatMap((facet) => tokens(facet.value));
412
440
  const allTokens = Array.from(new Set([...queryTokens, ...facetTokens]));
413
441
  // Each clause of a compound question is also scored on its own, so the
414
442
  // words of one clause do not dilute a match on another.
415
- const clauseTokenSets = queryClauses(options.query).map((clause) => Array.from(new Set([...clause, ...facetTokens])));
443
+ const clauseTokenSets = queryClauses(query).map((clause) => Array.from(new Set([...clause, ...facetTokens])));
416
444
  const bodies = await readBodies(entities, workspaceRoot, bodyCache);
417
445
  const documentFrequency = buildDocumentFrequency(entities, bodies);
418
446
  const supersededIds = new Set(graphEdges
@@ -586,7 +614,7 @@ async function queryGraphEdges(prolog, seedIds) {
586
614
  }
587
615
  async function loadIntentCandidates(prolog, options) {
588
616
  const terms = [
589
- options.query,
617
+ topicText(options.query, options.sourceLocations),
590
618
  ...facetValues(options.semanticFacets).map((facet) => facet.value),
591
619
  ].filter((term, index, all) => term.trim() && all.indexOf(term) === index);
592
620
  const candidates = new Map();
@@ -1,5 +1,11 @@
1
1
  import type { OperationContext } from "../../public/operations/runtime-types.js";
2
- import type { ActivationPolicy } from "./types.js";
2
+ import type { ActivationPolicy, Candidate } from "./types.js";
3
3
  export declare function missingManifestActivation(vendored: boolean, projectSignal: boolean): ActivationPolicy;
4
+ /**
5
+ * On a seeded KB the plan may hold declared intent claims, already
6
+ * deduplicated against the existing KB. Such a plan is applicable like a thin
7
+ * bootstrap plan; a seeded plan holding anything else stays a handoff.
8
+ */
9
+ export declare function claimPlanActivation(policy: ActivationPolicy, candidates: readonly Candidate[]): ActivationPolicy;
4
10
  export declare function classifyActivation(context: OperationContext, files?: readonly string[]): Promise<ActivationPolicy>;
5
11
  //# sourceMappingURL=activation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/activation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAGjF,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAC;AAIpE,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,OAAO,EACjB,aAAa,EAAE,OAAO,GACrB,gBAAgB,CAIlB;AAmHD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,gBAAgB,EACzB,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAyE3B"}
1
+ {"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/activation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAGjF,OAAO,KAAK,EAAE,gBAAgB,EAAmB,SAAS,EAAE,MAAM,YAAY,CAAC;AAI/E,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,OAAO,EACjB,aAAa,EAAE,OAAO,GACrB,gBAAgB,CAIlB;AAkED;;;;GAIG;AAGH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,gBAAgB,EACxB,UAAU,EAAE,SAAS,SAAS,EAAE,GAC/B,gBAAgB,CAelB;AAyDD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,gBAAgB,EACzB,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAyE3B"}
@@ -16,6 +16,7 @@ function activationFor(state) {
16
16
  // Discovery remains useful for explaining the next step, but the
17
17
  // resulting plan is blocked until `kibi init` establishes the root.
18
18
  allowCandidateGeneration: true,
19
+ allowDeclaredClaims: true,
19
20
  reason: "Workspace has no attached root KB yet; run `kibi init` before planning bootstrap knowledge.",
20
21
  handoffMessage: "Kibi infrastructure is not initialized. Run `kibi init`, then ask the agent to bootstrap this repository.",
21
22
  };
@@ -25,6 +26,7 @@ function activationFor(state) {
25
26
  activationMode: "repair_bootstrap",
26
27
  applyBlocked: true,
27
28
  allowCandidateGeneration: true,
29
+ allowDeclaredClaims: true,
28
30
  reason: "Workspace root is only partially configured; run a repair bootstrap scan and keep apply blocked until the root is repaired.",
29
31
  };
30
32
  case "vendored_only":
@@ -33,6 +35,7 @@ function activationFor(state) {
33
35
  activationMode: "vendored_blocked",
34
36
  applyBlocked: true,
35
37
  allowCandidateGeneration: false,
38
+ allowDeclaredClaims: false,
36
39
  reason: "Workspace appears to contain vendored Kibi sources only; bootstrap generation is blocked in this posture.",
37
40
  handoffMessage: "Vendored Kibi posture detected. Move to the real project root before attempting bootstrap.",
38
41
  };
@@ -42,19 +45,41 @@ function activationFor(state) {
42
45
  activationMode: "attached_thin_bootstrap",
43
46
  applyBlocked: false,
44
47
  allowCandidateGeneration: true,
48
+ allowDeclaredClaims: true,
45
49
  reason: "Workspace has an attached but unseeded KB; deterministic bootstrap planning is eligible.",
46
50
  };
47
51
  case "root_active_seeded":
48
52
  return {
49
53
  activationState: state,
50
54
  activationMode: "attached_seeded_handoff",
55
+ // Blocked until the plan holds declared claims; see claimPlanActivation.
51
56
  applyBlocked: true,
52
57
  allowCandidateGeneration: false,
53
- reason: "Workspace already has an attached seeded KB; bootstrap synthesis is replaced by an explicit seeded handoff.",
54
- handoffMessage: "Attached seeded KB detected. Use existing KB context instead of generating bootstrap candidates.",
58
+ allowDeclaredClaims: true,
59
+ reason: "Workspace already has an attached seeded KB; discovered bootstrap candidates are replaced by an explicit seeded handoff, and only declared intent claims are planned against the existing KB.",
60
+ handoffMessage: "Attached seeded KB detected. Kibi does not generate discovered bootstrap candidates here: use kb_search and kb_query for existing KB context. Declare cited intentClaims in bootstrapContext to plan them against the existing KB, or compile each claim with kb_compile_intent.",
55
61
  };
56
62
  }
57
63
  }
64
+ /**
65
+ * On a seeded KB the plan may hold declared intent claims, already
66
+ * deduplicated against the existing KB. Such a plan is applicable like a thin
67
+ * bootstrap plan; a seeded plan holding anything else stays a handoff.
68
+ */
69
+ // implements REQ-bootstrap-discovered-candidate-budget
70
+ // covered_by TEST-KIBI-BOOTSTRAP-PLAN-APPLY
71
+ export function claimPlanActivation(policy, candidates) {
72
+ if (policy.activationState !== "root_active_seeded" ||
73
+ candidates.length === 0 ||
74
+ candidates.some((candidate) => candidate.sourceKind !== "intent_claim"))
75
+ return policy;
76
+ return {
77
+ ...policy,
78
+ applyBlocked: false,
79
+ reason: "Workspace already has an attached seeded KB; discovered bootstrap candidates are not generated, and the plan holds only declared intent claims that are not yet in the KB.",
80
+ handoffMessage: "Attached seeded KB detected. The plan holds only your declared intent claims, deduplicated against the existing KB: review it and call kb_apply_plan after explicit approval. Discovered candidates are not generated here; use kb_search and kb_query for existing knowledge, and compile any claim left in sourceOnlySignals with kb_compile_intent.",
81
+ };
82
+ }
58
83
  async function exists(context, target) {
59
84
  try {
60
85
  await context.fs?.stat(target);
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/generate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAcjF,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAGpB,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACzC,SAAS,gBAAgB,EAAE,CAI7B;AA+BD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,MAAM,GACd;IACD,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAClE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CAwJA;AA+JD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAkH9B"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/generate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAejF,OAAO,KAAK,EAGV,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAGpB,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACzC,SAAS,gBAAgB,EAAE,CAI7B;AA+BD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,MAAM,GACd;IACD,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAClE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CAwJA;AAkMD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAqI9B"}
@@ -4,6 +4,7 @@ import { loadEntityIds } from "../../public/operations/discovery-entities.js";
4
4
  import { executeStatus } from "../../public/operations/discovery-executors.js";
5
5
  import { readWorkspaceSnapshot } from "../../public/operations/workspace-snapshot.js";
6
6
  import { stagedLogicalGroundingError, } from "../semantic-advisor/ingestion-boundary.js";
7
+ import { claimPlanActivation } from "./activation.js";
7
8
  import { buildBootstrapCandidates, isProvenanceStubCandidate, } from "./candidates.js";
8
9
  import { discoverBootstrap } from "./discovery.js";
9
10
  import { buildIntentClaimCandidates } from "./intent-claims.js";
@@ -218,13 +219,40 @@ function stagedGroundingError(candidate, planned) {
218
219
  }
219
220
  return null;
220
221
  }
221
- async function existingEntityIds(context) {
222
- if (!context.prolog)
223
- return new Set();
222
+ /**
223
+ * One suppressedCandidates row per declared claim the activation mode does
224
+ * not plan, so the per-source accounting names the real reason.
225
+ */
226
+ // implements REQ-bootstrap-intent-claim-accounting
227
+ function activationSuppressedClaims(declared, activation) {
228
+ const sources = new Set((declared.knowledgeSources ?? []).map((source) => source.id));
229
+ return (declared.intentClaims ?? [])
230
+ .filter((claim) => sources.has(claim.sourceId))
231
+ .map((claim) => ({
232
+ candidateId: "",
233
+ reason: "suppressed_by_activation",
234
+ sourcePath: claim.reference,
235
+ entityType: (claim.kind ?? "intent") === "intent" ? "req" : "fact",
236
+ statement: claim.statement,
237
+ sourceId: claim.sourceId,
238
+ activationMode: activation.activationMode,
239
+ }));
240
+ }
241
+ /**
242
+ * IDs already in the KB, so declared claims and discovered candidates that
243
+ * exist are counted under entity_exists instead of being planned again. An
244
+ * attached root starts the lazy engine when the host supplied none (the CLI
245
+ * does so for status anyway); an unattached root never starts one.
246
+ */
247
+ // implements REQ-bootstrap-intent-claim-accounting
248
+ async function existingEntityIds(context, attached) {
224
249
  try {
250
+ const prolog = context.prolog ?? (attached ? await context.ensureProlog?.() : undefined);
251
+ if (!prolog)
252
+ return new Set();
225
253
  // Ids only: materializing every entity (receipt histories included)
226
254
  // just to build this set exceeds the bounded engine output.
227
- return new Set((await loadEntityIds(context.prolog)).filter(Boolean));
255
+ return new Set((await loadEntityIds(prolog)).filter(Boolean));
228
256
  }
229
257
  catch (error) {
230
258
  throw new Error(`Bootstrap binding could not read existing entity IDs: ${error instanceof Error ? error.message : String(error)}`);
@@ -317,13 +345,12 @@ export async function executePlanBootstrap(args, context) {
317
345
  const minConfidence = clamp(args.minConfidence ?? 0.8, 0.6, 0.95);
318
346
  const maxCandidates = clamp(Math.trunc(args.maxCandidates ?? 50), 1, 200);
319
347
  const entityBindingDiagnostics = [];
320
- const [discovery, existingIds] = await Promise.all([
321
- discoverBootstrap(context),
322
- existingEntityIds(context).catch((error) => {
323
- entityBindingDiagnostics.push(error.message);
324
- return new Set();
325
- }),
326
- ]);
348
+ const discovery = await discoverBootstrap(context);
349
+ const existingIds = await existingEntityIds(context, discovery.activation.activationState === "root_active_thin" ||
350
+ discovery.activation.activationState === "root_active_seeded").catch((error) => {
351
+ entityBindingDiagnostics.push(error.message);
352
+ return new Set();
353
+ });
327
354
  // Discovery runs before planning so its evidence paths can be bound into
328
355
  // the exact plan rather than leaving the reviewer to reconstruct them.
329
356
  const bound = await expectedSnapshots(context, discovery.evidence
@@ -341,13 +368,17 @@ export async function executePlanBootstrap(args, context) {
341
368
  diagnostics: [],
342
369
  };
343
370
  // Intent harvested from declared knowledge sources joins the repository
344
- // evidence under the same activation policy, filters, and selection.
345
- const claimed = discovery.activation.allowCandidateGeneration
371
+ // evidence under the same filters and selection. A seeded KB still plans
372
+ // declared claims (deduplicated against the existing KB); only discovered
373
+ // candidates stay off there.
374
+ const allowDeclaredClaims = discovery.activation.allowDeclaredClaims ??
375
+ discovery.activation.allowCandidateGeneration;
376
+ const claimed = allowDeclaredClaims
346
377
  ? buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys)
347
378
  : {
348
379
  candidates: [],
349
380
  sourceOnlySignals: [],
350
- suppressed: [],
381
+ suppressed: activationSuppressedClaims(declared, discovery.activation),
351
382
  diagnostics: [],
352
383
  };
353
384
  const filteredSignals = filterSourceOnlySignals([...built.sourceOnlySignals, ...claimed.sourceOnlySignals], args.entityTypes);
@@ -361,10 +392,19 @@ export async function executePlanBootstrap(args, context) {
361
392
  entityType: "",
362
393
  }));
363
394
  const { bindingDiagnostics, ...expected } = bound;
395
+ // A seeded plan holding only declared claims is applicable.
396
+ const activation = claimPlanActivation(discovery.activation, shared.candidates);
364
397
  return presentBootstrap({
365
398
  root: context.workspaceRoot,
366
- activation: discovery.activation,
367
- discoverySummary: discovery.summary,
399
+ activation,
400
+ discoverySummary: {
401
+ ...discovery.summary,
402
+ applyBlocked: activation.applyBlocked,
403
+ reason: activation.reason,
404
+ ...(activation.handoffMessage
405
+ ? { handoffMessage: activation.handoffMessage }
406
+ : {}),
407
+ },
368
408
  migrationWarning: discovery.migrationWarning,
369
409
  pluginOffers: discovery.pluginOffers,
370
410
  ...(args.bootstrapContext
@@ -1 +1 @@
1
- {"version":3,"file":"guidance-actions.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/guidance-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAkBpB,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,MAAM,GAAE,SAAS,WAAW,EAAO,GAClC,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAgF9C"}
1
+ {"version":3,"file":"guidance-actions.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/guidance-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAkBpB,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,MAAM,GAAE,SAAS,WAAW,EAAO,GAClC,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CA6F9C"}
@@ -52,6 +52,8 @@ export function buildActions(root, activation, declared, candidates, signals, of
52
52
  : "Use kb_coverage to review traceability and identify areas needing attention.",
53
53
  });
54
54
  }
55
+ const seeded = activation.activationMode === "attached_seeded_handoff";
56
+ const declaredClaims = declared.intentClaims?.length ?? 0;
55
57
  if (activation.applyBlocked)
56
58
  result.push({
57
59
  order: order++,
@@ -62,14 +64,24 @@ export function buildActions(root, activation, declared, candidates, signals, of
62
64
  result.push({
63
65
  order: order++,
64
66
  kind: "plan",
65
- description: `Review the ${candidates.length} safe candidate(s) in the hash-bound plan, then call kb_apply_plan after explicit approval.`,
67
+ description: seeded
68
+ ? `Review the ${candidates.length} candidate(s) planned from declared intent claims (discovered candidates are not generated on a seeded KB, and claims already in the KB are not planned again), then call kb_apply_plan after explicit approval.`
69
+ : `Review the ${candidates.length} safe candidate(s) in the hash-bound plan, then call kb_apply_plan after explicit approval.`,
66
70
  candidateIds: candidates.map((candidate) => candidate.candidateId),
67
71
  });
72
+ // On a seeded KB, declared claims the plan does not write go through the
73
+ // compile workflow, not a second bootstrap.
74
+ if (seeded && declaredClaims > 0 && candidates.length === 0)
75
+ result.push({
76
+ order: order++,
77
+ kind: "handoff",
78
+ description: "No declared intent claim could be planned. Claims already in the KB need nothing; compile each remaining claim with kb_compile_intent, citing its source and reference (see the Knowledge source diagnostics).",
79
+ });
68
80
  if (signals.length > 0)
69
81
  result.push({
70
82
  order: order++,
71
83
  kind: "handoff",
72
- description: `Author ${[...new Set(signals.map((signal) => signal.kind.toUpperCase()))].join("/")} entities manually from source-only evidence.`,
84
+ description: `Author ${[...new Set(signals.map((signal) => signal.kind.toUpperCase()))].join("/")} entities manually from source-only evidence${seeded ? "; compile declared claims left there with kb_compile_intent" : ""}.`,
73
85
  });
74
86
  for (const offer of offers)
75
87
  result.push({
@@ -1 +1 @@
1
- {"version":3,"file":"guidance.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/guidance.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAwFpB,wBAAgB,UAAU,CACxB,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,WAAW,EAAE,MAAM,GAClB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAiEnC;AAGD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C,GAAG;IACF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;CAChE,CA2BA"}
1
+ {"version":3,"file":"guidance.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/guidance.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AA+FpB,wBAAgB,UAAU,CACxB,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,WAAW,EAAE,MAAM,GAClB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAkEnC;AAGD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C,GAAG;IACF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;CAChE,CA2BA"}
@@ -51,7 +51,10 @@ function prompt(root, activation, declared, candidates, signals, warnings) {
51
51
  }
52
52
  else if (declared.verificationAnchors.length > 0)
53
53
  bullets.push(`- Verify after kb_check with ${summary(declared.verificationAnchors, 2)}.`);
54
- if (activation.activationMode === "attached_thin_handoff" ||
54
+ if (activation.activationMode === "attached_seeded_handoff" &&
55
+ !activation.applyBlocked)
56
+ bullets.push("- Seeded KB: only declared intent claims are planned; use kb_search or kb_query for existing knowledge.");
57
+ else if (activation.activationMode === "attached_thin_handoff" ||
55
58
  activation.activationMode === "attached_seeded_handoff")
56
59
  bullets.push("- Handoff: use kb_search, kb_query, or gap/coverage tools to work with existing KB.");
57
60
  if (warnings.length > 0)
@@ -78,7 +81,8 @@ export function confidence(activation, declared, candidates, signals, promptBloc
78
81
  repair_bootstrap: -0.05,
79
82
  attached_thin_bootstrap: 0.04,
80
83
  attached_thin_handoff: -0.12,
81
- attached_seeded_handoff: -0.18,
84
+ // A seeded plan of declared claims weighs like a thin bootstrap plan.
85
+ attached_seeded_handoff: activation.applyBlocked ? -0.18 : 0.04,
82
86
  vendored_blocked: -0.25,
83
87
  }[activation.activationMode];
84
88
  reasons.push(`${activation.activationMode} determined the bootstrap posture.`);
@@ -1 +1 @@
1
- {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/presentation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EACV,gBAAgB,EAGhB,gBAAgB,EAChB,wBAAwB,EAGxB,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AA6GpB,wBAAgB,yBAAyB,CACvC,KAAK,CAAC,EAAE,gBAAgB,GACvB,wBAAwB,CAe1B;AAgBD;;;GAGG;AAEH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,GACjD,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAYhE;AA0CD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,oBAAoB,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAC5E,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,wEAAwE;IACxE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjD,GAAG,mBAAmB,CAqOtB"}
1
+ {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/presentation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EACV,gBAAgB,EAGhB,gBAAgB,EAChB,wBAAwB,EAGxB,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AA6GpB,wBAAgB,yBAAyB,CACvC,KAAK,CAAC,EAAE,gBAAgB,GACvB,wBAAwB,CAe1B;AAgBD;;;GAGG;AAEH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,GACjD,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAYhE;AAoID,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,oBAAoB,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAC5E,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,wEAAwE;IACxE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjD,GAAG,mBAAmB,CAqOtB"}
@@ -136,9 +136,11 @@ export function suppressionCounts(rows) {
136
136
  .map(([reason, count]) => ({ reason, count }))
137
137
  .sort((left, right) => right.count - left.count || left.reason.localeCompare(right.reason));
138
138
  }
139
+ const EXISTING_REASONS = ["entity_exists"];
140
+ const FILTERED_REASONS = ["filtered_by_entity_type", "below_min_confidence"];
139
141
  /** Declared claims per knowledge source against what the plan writes. */
140
142
  // implements REQ-bootstrap-intent-claim-accounting
141
- function claimAccounting(declared, candidates, suppressed) {
143
+ function claimAccounting(declared, candidates, suppressed, signals) {
142
144
  return (declared.knowledgeSources ?? []).flatMap((source) => {
143
145
  const count = (declared.intentClaims ?? []).filter((claim) => claim.sourceId === source.id).length;
144
146
  if (count === 0)
@@ -146,14 +148,75 @@ function claimAccounting(declared, candidates, suppressed) {
146
148
  const prefix = `claim:${source.id}:`;
147
149
  const planned = candidates.filter((candidate) => candidate.sourceKind === "intent_claim" &&
148
150
  candidate.candidateId.startsWith(prefix)).length;
149
- const rows = (reasons) => suppressed.filter((row) => reasons.includes(String(row.reason)) &&
150
- String(row.candidateId).startsWith(prefix)).length;
151
- const existing = rows(["entity_exists"]);
151
+ // Rows cite their claim by candidate ID, or by sourceId when the claim
152
+ // never became a candidate (stale source, missing excerpt, activation).
153
+ const sourceRows = suppressed.filter((row) => String(row.candidateId ?? "").startsWith(prefix) ||
154
+ (!row.candidateId && row.sourceId === source.id));
155
+ const rows = (reasons) => sourceRows.filter((row) => reasons.includes(String(row.reason)));
156
+ const existing = rows(EXISTING_REASONS).length;
152
157
  // Claims the caller filtered out (entityTypes, minConfidence) are not lost.
153
- const filtered = rows(["filtered_by_entity_type", "below_min_confidence"]);
154
- return [{ source, declared: count, planned, existing, filtered }];
158
+ const filteredRows = rows(FILTERED_REASONS);
159
+ const filtered = filteredRows.length;
160
+ // The rest is not planned; each claim is attributed to one reason, in
161
+ // order, so the counts add up to what was declared.
162
+ let rest = Math.max(0, count - planned - existing - filtered);
163
+ const take = (value) => {
164
+ const taken = Math.min(rest, value);
165
+ rest -= taken;
166
+ return taken;
167
+ };
168
+ const byActivation = take(rows(["suppressed_by_activation"]).length);
169
+ const otherRows = sourceRows.filter((row) => ![
170
+ ...EXISTING_REASONS,
171
+ ...FILTERED_REASONS,
172
+ "suppressed_by_activation",
173
+ ].includes(String(row.reason)));
174
+ const suppressedCount = take(otherRows.length);
175
+ // A claim below minConfidence or invalid at write time also leaves a
176
+ // follow-up; it is already counted by its row.
177
+ const counted = new Set([...filteredRows, ...otherRows].map((row) => String(row.sourcePath)));
178
+ const sourceOnly = take(signals.filter((signal) => signal.evidence.some((line) => line.startsWith(`intent_claim:${source.id}:`)) && !counted.has(signal.sourcePath)).length);
179
+ return [
180
+ {
181
+ source,
182
+ declared: count,
183
+ planned,
184
+ existing,
185
+ filtered,
186
+ byActivation,
187
+ suppressed: suppressedCount,
188
+ sourceOnly,
189
+ unattributed: rest,
190
+ },
191
+ ];
155
192
  });
156
193
  }
194
+ /** One diagnostic line per source that names why claims were not planned. */
195
+ // implements REQ-bootstrap-intent-claim-accounting
196
+ function accountingLine(row, activation) {
197
+ const notPlanned = row.byActivation + row.suppressed + row.sourceOnly + row.unattributed;
198
+ const reasons = [
199
+ ...(row.byActivation > 0
200
+ ? [
201
+ `${row.byActivation} because bootstrap synthesis is suppressed in ${activation.activationMode}; compile them with kb_compile_intent`,
202
+ ]
203
+ : []),
204
+ ...(row.suppressed > 0
205
+ ? [`${row.suppressed} suppressed (rows in suppressedCandidates)`]
206
+ : []),
207
+ ...(row.sourceOnly > 0
208
+ ? [
209
+ `${row.sourceOnly} need authoring (sourceOnlySignals; compile them with kb_compile_intent)`,
210
+ ]
211
+ : []),
212
+ ...(row.unattributed > 0
213
+ ? [
214
+ `${row.unattributed} without a suppressedCandidates row or follow-up (see diagnostics)`,
215
+ ]
216
+ : []),
217
+ ];
218
+ return `Knowledge source ${row.source.id} (${row.source.authority}): ${row.declared} declared claim(s), ${row.planned} planned, ${row.existing} already in the KB, ${row.filtered} filtered out, ${notPlanned} not planned${reasons.length > 0 ? `: ${reasons.join("; ")}` : ""}.`;
219
+ }
157
220
  // implements REQ-KIBI-BOOTSTRAP-PLAN, REQ-bootstrap-discovered-candidate-budget, REQ-bootstrap-provenance-stubs
158
221
  export function presentBootstrap(input) {
159
222
  const declaredContext = normalizeBootstrapContext(input.bootstrapContext);
@@ -238,10 +301,13 @@ export function presentBootstrap(input) {
238
301
  candidateId: candidate.candidateId,
239
302
  };
240
303
  });
241
- const accounting = claimAccounting(declaredContext, input.candidates, input.suppressedCandidates);
304
+ const accounting = claimAccounting(declaredContext, input.candidates, input.suppressedCandidates, input.sourceOnlySignals);
242
305
  const droppedAuthoritative = accounting.filter((row) => row.source.authority === "authoritative" &&
243
306
  row.planned + row.existing + row.filtered === 0);
244
- const status = input.activation.activationState === "root_active_seeded"
307
+ const status =
308
+ // A seeded KB is a handoff unless its plan holds declared claims.
309
+ input.activation.activationState === "root_active_seeded" &&
310
+ input.activation.applyBlocked
245
311
  ? "handoff"
246
312
  : applyBlocked
247
313
  ? "blocked"
@@ -277,7 +343,7 @@ export function presentBootstrap(input) {
277
343
  `Suppressed candidates by reason: ${suppression.map((row) => `${row.reason} ${row.count}`).join(", ")} (rows in suppressedCandidates).`,
278
344
  ]
279
345
  : []),
280
- ...accounting.map((row) => `Knowledge source ${row.source.id} (${row.source.authority}): ${row.declared} declared claim(s), ${row.planned} planned, ${row.existing} already in the KB, ${row.filtered} filtered out, ${row.declared - row.planned - row.existing - row.filtered} not planned (see suppressedCandidates and source-only follow-ups).`),
346
+ ...accounting.map((row) => accountingLine(row, input.activation)),
281
347
  ];
282
348
  const planBody = {
283
349
  version: "kibi.bootstrap-plan.v1",
@@ -105,6 +105,12 @@ export type ActivationPolicy = {
105
105
  readonly activationMode: ActivationMode;
106
106
  readonly applyBlocked: boolean;
107
107
  readonly allowCandidateGeneration: boolean;
108
+ /**
109
+ * Whether declared intent claims from bootstrapContext are planned. A
110
+ * seeded KB turns off discovered candidates but still plans these claims.
111
+ * Defaults to allowCandidateGeneration when omitted.
112
+ */
113
+ readonly allowDeclaredClaims?: boolean;
108
114
  readonly reason: string;
109
115
  readonly handoffMessage?: string;
110
116
  };