kibi-cli 2.35.1 → 2.38.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 (154) hide show
  1. package/dist/cli-operation-metadata.d.ts +1 -1
  2. package/dist/cli-operation-metadata.js +1 -1
  3. package/dist/cli-register-foundation.d.ts.map +1 -1
  4. package/dist/cli-register-foundation.js +2 -1
  5. package/dist/cli-register-maintenance.d.ts.map +1 -1
  6. package/dist/cli-register-maintenance.js +5 -0
  7. package/dist/cli-validate.d.ts.map +1 -1
  8. package/dist/cli-validate.js +21 -2
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +16 -1
  11. package/dist/commands/aggregated-checks.d.ts.map +1 -1
  12. package/dist/commands/aggregated-checks.js +89 -16
  13. package/dist/commands/doctor.d.ts.map +1 -1
  14. package/dist/commands/doctor.js +56 -35
  15. package/dist/commands/github-init.d.ts.map +1 -1
  16. package/dist/commands/github-init.js +4 -2
  17. package/dist/commands/hook-managers.d.ts +43 -0
  18. package/dist/commands/hook-managers.d.ts.map +1 -0
  19. package/dist/commands/hook-managers.js +426 -0
  20. package/dist/commands/init.d.ts +1 -0
  21. package/dist/commands/init.d.ts.map +1 -1
  22. package/dist/commands/init.js +40 -5
  23. package/dist/commands/sync/persistence.d.ts.map +1 -1
  24. package/dist/commands/sync/persistence.js +43 -1
  25. package/dist/commands/telemetry.d.ts +7 -0
  26. package/dist/commands/telemetry.d.ts.map +1 -0
  27. package/dist/commands/telemetry.js +23 -0
  28. package/dist/decision-firmness.d.ts.map +1 -1
  29. package/dist/decision-firmness.js +11 -14
  30. package/dist/engine-limits.d.ts.map +1 -1
  31. package/dist/engine-limits.js +8 -10
  32. package/dist/entity-body-context.d.ts.map +1 -1
  33. package/dist/entity-body-context.js +39 -36
  34. package/dist/extractors/symbol-coordinates.d.ts.map +1 -1
  35. package/dist/extractors/symbol-coordinates.js +23 -4
  36. package/dist/firm-decision-edit.d.ts.map +1 -1
  37. package/dist/firm-decision-edit.js +1 -3
  38. package/dist/intent-search.d.ts +5 -1
  39. package/dist/intent-search.d.ts.map +1 -1
  40. package/dist/intent-search.js +118 -33
  41. package/dist/logic/ir.d.ts.map +1 -1
  42. package/dist/logic/ir.js +82 -108
  43. package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
  44. package/dist/operations/bootstrap/guidance-actions.js +2 -1
  45. package/dist/operations/bootstrap/plugin-offers.d.ts +11 -2
  46. package/dist/operations/bootstrap/plugin-offers.d.ts.map +1 -1
  47. package/dist/operations/bootstrap/plugin-offers.js +48 -9
  48. package/dist/operations/proof/claim-bindings.d.ts.map +1 -1
  49. package/dist/operations/proof/claim-bindings.js +1 -0
  50. package/dist/operations/proof/code-certificates.d.ts +2 -0
  51. package/dist/operations/proof/code-certificates.d.ts.map +1 -1
  52. package/dist/operations/proof/code-certificates.js +34 -14
  53. package/dist/operations/proof/code-models.d.ts.map +1 -1
  54. package/dist/operations/proof/code-models.js +19 -5
  55. package/dist/operations/proof/code-runner.d.ts +16 -0
  56. package/dist/operations/proof/code-runner.d.ts.map +1 -1
  57. package/dist/operations/proof/code-runner.js +42 -6
  58. package/dist/plugins/compose-search-hints.d.ts +29 -0
  59. package/dist/plugins/compose-search-hints.d.ts.map +1 -0
  60. package/dist/plugins/compose-search-hints.js +94 -0
  61. package/dist/plugins/external-allowlist.d.ts +7 -0
  62. package/dist/plugins/external-allowlist.d.ts.map +1 -1
  63. package/dist/plugins/external-allowlist.js +11 -0
  64. package/dist/plugins/registry.d.ts +8 -1
  65. package/dist/plugins/registry.d.ts.map +1 -1
  66. package/dist/plugins/registry.js +22 -3
  67. package/dist/prolog/codec.d.ts.map +1 -1
  68. package/dist/prolog/codec.js +10 -20
  69. package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
  70. package/dist/public/impact/coverage-depth-quality.js +32 -16
  71. package/dist/public/impact/full-kb-quality.d.ts +6 -0
  72. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  73. package/dist/public/impact/full-kb-quality.js +8 -3
  74. package/dist/public/impact/requirement-quality.d.ts.map +1 -1
  75. package/dist/public/impact/requirement-quality.js +56 -29
  76. package/dist/public/operations/catalog.d.ts +13 -3
  77. package/dist/public/operations/catalog.d.ts.map +1 -1
  78. package/dist/public/operations/check-executor.d.ts +6 -0
  79. package/dist/public/operations/check-executor.d.ts.map +1 -1
  80. package/dist/public/operations/check-executor.js +34 -2
  81. package/dist/public/operations/discovery-executors.d.ts +5 -1
  82. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  83. package/dist/public/operations/discovery-executors.js +65 -4
  84. package/dist/public/operations/evidence-floor.d.ts +8 -1
  85. package/dist/public/operations/evidence-floor.d.ts.map +1 -1
  86. package/dist/public/operations/evidence-floor.js +3 -4
  87. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  88. package/dist/public/operations/migration-plan.js +41 -10
  89. package/dist/public/operations/node-ports.d.ts.map +1 -1
  90. package/dist/public/operations/node-ports.js +3 -1
  91. package/dist/public/operations/source-analysis-cache.d.ts +22 -0
  92. package/dist/public/operations/source-analysis-cache.d.ts.map +1 -0
  93. package/dist/public/operations/source-analysis-cache.js +157 -0
  94. package/dist/public/operations/specs/discovery.d.ts +7 -2
  95. package/dist/public/operations/specs/discovery.d.ts.map +1 -1
  96. package/dist/public/operations/specs/discovery.js +7 -2
  97. package/dist/public/operations/specs/mutation-schemas.d.ts +6 -1
  98. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  99. package/dist/public/operations/specs/upsert.d.ts +6 -1
  100. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  101. package/dist/public/operations/symbol-granularity-check.d.ts +3 -1
  102. package/dist/public/operations/symbol-granularity-check.d.ts.map +1 -1
  103. package/dist/public/operations/symbol-granularity-check.js +21 -7
  104. package/dist/public/proof-protocol.d.ts +6 -1
  105. package/dist/public/proof-protocol.d.ts.map +1 -1
  106. package/dist/public/proof-protocol.js +12 -3
  107. package/dist/public/proof-sources.d.ts +2 -0
  108. package/dist/public/proof-sources.d.ts.map +1 -1
  109. package/dist/public/proof-sources.js +32 -6
  110. package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
  111. package/dist/public/skills/kibi-usage/SKILL.md +42 -3
  112. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +34 -0
  113. package/dist/public/skills/kibi-usage/resources/proof.md +13 -5
  114. package/dist/public/skills/kibi-usage/resources/workflows.md +10 -0
  115. package/dist/relationships/shards.d.ts +2 -0
  116. package/dist/relationships/shards.d.ts.map +1 -1
  117. package/dist/relationships/shards.js +25 -1
  118. package/dist/schemas/entity.schema.json +6 -1
  119. package/dist/search-answer.js +1 -1
  120. package/dist/search-hints.d.ts +58 -0
  121. package/dist/search-hints.d.ts.map +1 -0
  122. package/dist/search-hints.js +187 -0
  123. package/dist/search-ranking.d.ts +7 -0
  124. package/dist/search-ranking.d.ts.map +1 -1
  125. package/dist/search-ranking.js +54 -56
  126. package/dist/search-token-cache.d.ts +30 -0
  127. package/dist/search-token-cache.d.ts.map +1 -0
  128. package/dist/search-token-cache.js +86 -0
  129. package/dist/usage-telemetry.d.ts +11 -0
  130. package/dist/usage-telemetry.d.ts.map +1 -0
  131. package/dist/usage-telemetry.js +47 -0
  132. package/dist/utils/branch-resolver.d.ts.map +1 -1
  133. package/dist/utils/branch-resolver.js +1 -0
  134. package/package.json +5 -4
  135. package/src/public/impact/coverage-depth-quality.ts +59 -21
  136. package/src/public/impact/full-kb-quality.ts +15 -1
  137. package/src/public/impact/requirement-quality.ts +95 -38
  138. package/src/public/operations/check-executor.ts +41 -1
  139. package/src/public/operations/discovery-executors.ts +92 -4
  140. package/src/public/operations/evidence-floor.ts +15 -3
  141. package/src/public/operations/migration-plan.ts +41 -9
  142. package/src/public/operations/node-ports.ts +3 -1
  143. package/src/public/operations/source-analysis-cache.ts +196 -0
  144. package/src/public/operations/specs/discovery.ts +8 -2
  145. package/src/public/operations/symbol-granularity-check.ts +25 -5
  146. package/src/public/proof-protocol-types.d.ts +1 -1
  147. package/src/public/proof-protocol.ts +18 -4
  148. package/src/public/proof-sources.ts +37 -6
  149. package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
  150. package/src/public/skills/kibi-usage/SKILL.md +42 -3
  151. package/src/public/skills/kibi-usage/resources/fact-lanes.md +34 -0
  152. package/src/public/skills/kibi-usage/resources/proof.md +13 -5
  153. package/src/public/skills/kibi-usage/resources/workflows.md +10 -0
  154. package/src/schemas/entity.schema.json +6 -1
@@ -27,7 +27,7 @@ export declare const CLI_OPERATION_METADATA: readonly [{
27
27
  }, {
28
28
  readonly name: "kb_search";
29
29
  readonly cliName: "search";
30
- readonly description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.";
30
+ readonly description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). A weak answer may add queryAnalysis.hints from a search-hints plugin: requirements the question may mean, to re-ask with. Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.";
31
31
  }, {
32
32
  readonly name: "kb_status";
33
33
  readonly cliName: "status";
@@ -30,7 +30,7 @@ export const CLI_OPERATION_METADATA = [
30
30
  {
31
31
  name: "kb_search",
32
32
  cliName: "search",
33
- description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.",
33
+ description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). A weak answer may add queryAnalysis.hints from a search-hints plugin: requirements the question may mean, to re-ask with. Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.",
34
34
  },
35
35
  {
36
36
  name: "kb_status",
@@ -1 +1 @@
1
- {"version":3,"file":"cli-register-foundation.d.ts","sourceRoot":"","sources":["../src/cli-register-foundation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6JjE"}
1
+ {"version":3,"file":"cli-register-foundation.d.ts","sourceRoot":"","sources":["../src/cli-register-foundation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiKjE"}
@@ -12,7 +12,8 @@ export function registerFoundationCommands(program) {
12
12
  .option("--no-hooks", "Do not install git hooks (hooks installed by default)")
13
13
  .option("--github", "Scaffold the GitHub Pages badge + requirement-health report workflow")
14
14
  .option("--badge-only", "With --github, publish only the badge (opt out of the full report)")
15
- .option("--print-hook <hook>", "Print a snippet that delegates an existing hook (pre-commit, post-checkout, post-merge, post-rewrite) to kibi, and write nothing")
15
+ .option("--print-hook <hook>", "Print a snippet that delegates an existing hook (pre-commit, post-checkout, post-merge, post-rewrite, or all) to kibi, and write nothing")
16
+ .option("--format <format>", "With --print-hook: shell (default), lefthook, husky or pre-commit")
16
17
  .action(withExitCode(async (options) => (await import("./commands/init.js")).initCommand(options)));
17
18
  program
18
19
  .command("migrate")
@@ -1 +1 @@
1
- {"version":3,"file":"cli-register-maintenance.d.ts","sourceRoot":"","sources":["../src/cli-register-maintenance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6KlE"}
1
+ {"version":3,"file":"cli-register-maintenance.d.ts","sourceRoot":"","sources":["../src/cli-register-maintenance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgMlE"}
@@ -68,6 +68,11 @@ export function registerMaintenanceCommands(program) {
68
68
  .option("--format <format>", "Output format: json|table", "table")
69
69
  .option("--limit <n>", "Limit rendered table rows", "50")
70
70
  .action(withExitCode(async (options) => (await import("./commands/usage-remediation.js")).usageRemediationCommand(options)));
71
+ program
72
+ .command("telemetry [action]")
73
+ .description("Show, enable or disable anonymous usage telemetry (status|enable|disable)")
74
+ .option("--format <format>", "Output format: json|text", "text")
75
+ .action(withExitCode(async (action, options) => (await import("./commands/telemetry.js")).telemetryCommand(action, options)));
71
76
  program
72
77
  .command("merge-driver")
73
78
  .description("Git merge driver: three-way merge .kb/symbols.yaml or a relationship shard by record id")
@@ -1 +1 @@
1
- {"version":3,"file":"cli-validate.d.ts","sourceRoot":"","sources":["../src/cli-validate.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAGpE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAGlE,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAC1C,GACD;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAiBlE,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,GACb,mBAAmB,CAgCrB;AAGD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,GACb,gBAAgB,CAKlB"}
1
+ {"version":3,"file":"cli-validate.d.ts","sourceRoot":"","sources":["../src/cli-validate.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAGpE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAGlE,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAC1C,GACD;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAsClE,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,GACb,mBAAmB,CA6BrB;AAGD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,GACb,gBAAgB,CAKlB"}
@@ -2,6 +2,26 @@ import Ajv from "ajv";
2
2
  function isObject(value) {
3
3
  return value !== null && typeof value === "object" && !Array.isArray(value);
4
4
  }
5
+ // One validator per operation schema. Building an Ajv instance compiles the
6
+ // JSON Schema meta-schema, and a CLI call validates its input more than once.
7
+ const inputValidator = new Ajv({ allErrors: true, strict: false });
8
+ const compiledInputSchemas = new WeakMap();
9
+ function compileInputSchema(schema) {
10
+ let validator = compiledInputSchemas.get(schema);
11
+ if (validator === undefined) {
12
+ const exact = { ...schema, additionalProperties: false };
13
+ try {
14
+ validator = inputValidator.compile(exact);
15
+ }
16
+ catch {
17
+ // A schema whose $id the shared instance already holds for another
18
+ // schema object compiles on an instance of its own.
19
+ validator = new Ajv({ allErrors: true, strict: false }).compile(exact);
20
+ }
21
+ compiledInputSchemas.set(schema, validator);
22
+ }
23
+ return validator;
24
+ }
5
25
  function formatValidationErrors(errors) {
6
26
  return errors.map((error) => {
7
27
  const location = error.instancePath.length > 0 ? error.instancePath : "/";
@@ -22,8 +42,7 @@ export function prepareOperationInput(input, schema) {
22
42
  };
23
43
  }
24
44
  const businessInput = Object.fromEntries(Object.entries(input).filter(([key]) => key !== "_diagnostic_telemetry"));
25
- const schemaWithExactTopLevel = { ...schema, additionalProperties: false };
26
- const validator = new Ajv({ allErrors: true, strict: false }).compile(schemaWithExactTopLevel);
45
+ const validator = compileInputSchema(schema);
27
46
  if (!validator(businessInput)) {
28
47
  return {
29
48
  valid: false,
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUrD;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,MAAM,GAChB,OAAO,CAIT;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM7D;AAGD,wBAAgB,YAAY,IAAI,OAAO,CAiBtC;AAGD,wBAAsB,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAqB3C;AAED,wBAAsB,kBAAkB,CACtC,YAAY,UAAoD,EAChE,KAAK,cAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAGf"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUrD;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,MAAM,GAChB,OAAO,CAIT;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM7D;AAGD,wBAAgB,YAAY,IAAI,OAAO,CAiBtC;AAGD,wBAAsB,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAkC3C;AAED,wBAAsB,kBAAkB,CACtC,YAAY,UAAoD,EAChE,KAAK,cAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAGf"}
package/dist/cli.js CHANGED
@@ -28,6 +28,7 @@ import { registerProofCommand } from "./cli-register-proof.js";
28
28
  import { registerReportingCommands } from "./cli-register-reporting.js";
29
29
  import { registerSkillsCommands } from "./cli-register-skills.js";
30
30
  import { bootstrapKibiEnvironment } from "./env/bootstrap.js";
31
+ import { finishCliTelemetry, trackCommandPath } from "./usage-telemetry.js";
31
32
  import { resolveWorkspaceCwd } from "./workspace-cwd.js";
32
33
  const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
33
34
  export function packageVersion(value) {
@@ -70,14 +71,28 @@ export async function main() {
70
71
  if (workspace.cwd !== process.cwd())
71
72
  process.chdir(workspace.cwd);
72
73
  bootstrapKibiEnvironment();
74
+ const startedAt = new Date();
75
+ const program = buildProgram();
76
+ const commandPath = trackCommandPath(program);
73
77
  let exitCode = process.exitCode ?? 0;
74
78
  try {
75
- await buildProgram().parseAsync(workspace.argv);
79
+ await program.parseAsync(workspace.argv);
76
80
  exitCode = process.exitCode ?? 0;
77
81
  }
78
82
  catch (error) {
79
83
  exitCode = exitCodeFromCliFailure(error);
80
84
  }
85
+ try {
86
+ await finishCliTelemetry({
87
+ commandPath: commandPath(),
88
+ packageVersion: packageVersion(packageJson),
89
+ startedAt,
90
+ exitCode: Number(exitCode),
91
+ });
92
+ }
93
+ catch {
94
+ // Telemetry is best effort and never changes the exit code.
95
+ }
81
96
  await Promise.all([process.stdout, process.stderr].map((stream) => stream.writableNeedDrain ? once(stream, "drain") : Promise.resolve()));
82
97
  process.exit(exitCode);
83
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"aggregated-checks.d.ts","sourceRoot":"","sources":["../../src/commands/aggregated-checks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiB5C;;;;;GAKG;AAEH,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAYR;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,EACpC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GACjC,OAAO,CAAC,SAAS,EAAE,CAAC,CA8DtB"}
1
+ {"version":3,"file":"aggregated-checks.d.ts","sourceRoot":"","sources":["../../src/commands/aggregated-checks.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiB5C;;;;;GAKG;AAEH,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAYR;AAsED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,EACpC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GACjC,OAAO,CAAC,SAAS,EAAE,CAAC,CAyEtB"}
@@ -1,3 +1,5 @@
1
+ import { mkdtempSync, readFileSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
1
3
  import path from "node:path";
2
4
  import { resolveKbPlPath } from "../prolog.js";
3
5
  import { escapeAtom, toPrologAtom } from "../prolog/codec.js";
@@ -25,6 +27,68 @@ export function ontologyQualityOverridesGoal(env = process.env) {
25
27
  ; true
26
28
  )`;
27
29
  }
30
+ /**
31
+ * A private file the engine writes the violations JSON to. A large KB's
32
+ * report can exceed the engine's bounded output capacity, so the answer
33
+ * carries only a transport marker and the JSON travels through this file.
34
+ * A temp folder that cannot be written gives no file, and the engine answers
35
+ * the JSON instead.
36
+ */
37
+ // implements REQ-003
38
+ function checkResultFile() {
39
+ let dir;
40
+ try {
41
+ dir = mkdtempSync(path.join(tmpdir(), "kibi-check-"));
42
+ }
43
+ catch {
44
+ return { path: undefined, dispose: () => { } };
45
+ }
46
+ return {
47
+ path: path.join(dir, "violations.json"),
48
+ // rationale: the directory always exists when disposed, so `force` (which
49
+ // only ignores a missing path) never changes the outcome.
50
+ // Stryker disable next-line BooleanLiteral
51
+ dispose: () => rmSync(dir, { recursive: true, force: true }),
52
+ };
53
+ }
54
+ /**
55
+ * The aggregated checks goal. With a result file it prefers the transport
56
+ * predicate, which falls back to an answer when the engine cannot write the
57
+ * file, then the older file predicates; without one (or with an engine whose
58
+ * core predates both) it asks for the JSON as an answer.
59
+ */
60
+ function aggregatedChecksQuery(checksPlPath, rulesAllowlist, resultPath) {
61
+ const target = resultPath === undefined ? "none" : toPrologAtom(resultPath);
62
+ const rules = rulesAllowlist
63
+ ? `[${[...rulesAllowlist].map(toPrologAtom).join(",")}]`
64
+ : undefined;
65
+ const transport = rules
66
+ ? `predicate_property(checks:check_selected_json_transport(_, _, _, _), _)
67
+ -> call(checks:check_selected_json_transport(${rules}, ${target}, Transport, JsonString))`
68
+ : `predicate_property(checks:check_all_json_transport(_, _, _, _), _)
69
+ -> call(checks:check_all_json_transport(${target}, false, Transport, JsonString))`;
70
+ const fileOnly = resultPath === undefined
71
+ ? ""
72
+ : rules
73
+ ? `predicate_property(checks:check_selected_json_file(_, _), _)
74
+ -> call(checks:check_selected_json_file(${rules}, ${target})), Transport = file
75
+ ; `
76
+ : `predicate_property(checks:check_all_json_file(_, _), _)
77
+ -> call(checks:check_all_json_file(${target}, false)), Transport = file
78
+ ; `;
79
+ const allAnswer = `predicate_property(checks:check_all_json_with_options(_, _), _)
80
+ -> call(checks:check_all_json_with_options(JsonString, false)), Transport = answer
81
+ ; call(checks:check_all_json(JsonString)), Transport = answer`;
82
+ const answer = rules
83
+ ? `predicate_property(checks:check_selected_json(_, _), _)
84
+ -> call(checks:check_selected_json(${rules}, JsonString)), Transport = answer
85
+ ; ${allAnswer}`
86
+ : allAnswer;
87
+ const goal = `( ${transport}
88
+ ; ${fileOnly}${answer}
89
+ )`;
90
+ return `(use_module('${escapeAtom(checksPlPath)}'), ${ontologyQualityOverridesGoal()}, ${goal})`;
91
+ }
28
92
  /**
29
93
  * Run all checks using the aggregated Prolog predicates.
30
94
  * This makes a single Prolog call and parses JSON output, significantly
@@ -36,27 +100,36 @@ export async function runAggregatedChecks(prolog, rulesAllowlist) {
36
100
  // implements REQ-003
37
101
  const violations = [];
38
102
  const checksPlPath = path.join(path.dirname(resolveKbPlPath()), "checks.pl");
39
- const checksPlPathEscaped = escapeAtom(checksPlPath);
40
- const fallbackQuery = `( predicate_property(checks:check_all_json_with_options(_, _), _)
41
- -> call(checks:check_all_json_with_options(JsonString, false))
42
- ; call(checks:check_all_json(JsonString))
43
- )`;
44
- const checksQuery = rulesAllowlist
45
- ? `( predicate_property(checks:check_selected_json(_, _), _)
46
- -> call(checks:check_selected_json([${[...rulesAllowlist]
47
- .map(toPrologAtom)
48
- .join(",")}], JsonString))
49
- ; ${fallbackQuery}
50
- )`
51
- : fallbackQuery;
52
- const query = `(use_module('${checksPlPathEscaped}'), ${ontologyQualityOverridesGoal()}, ${checksQuery})`;
53
- const result = await prolog.query(query);
103
+ const resultFile = checkResultFile();
104
+ let result;
105
+ let jsonString;
106
+ try {
107
+ result = await prolog.query(aggregatedChecksQuery(checksPlPath, rulesAllowlist, resultFile.path));
108
+ // rationale: the engine answers Transport "file" only after a successful
109
+ // query that was given a path, so neither guard changes which answers
110
+ // are read; they only narrow the path for the read.
111
+ // Stryker disable next-line ConditionalExpression,LogicalOperator
112
+ const mayRead = result.success && resultFile.path !== undefined;
113
+ if (mayRead && result.bindings.Transport === "file") {
114
+ try {
115
+ jsonString = readFileSync(resultFile.path, "utf8");
116
+ }
117
+ catch {
118
+ // The engine wrote a file this process cannot read (an engine with
119
+ // another view of the temp folder): ask for the JSON as an answer.
120
+ result = await prolog.query(aggregatedChecksQuery(checksPlPath, rulesAllowlist, undefined));
121
+ }
122
+ }
123
+ }
124
+ finally {
125
+ resultFile.dispose();
126
+ }
54
127
  if (!result.success) {
55
128
  throw new Error(`Aggregated checks query failed: ${result.error || "Unknown error"}`);
56
129
  }
57
130
  let violationsDict;
58
131
  try {
59
- const jsonString = result.bindings.JsonString;
132
+ jsonString ??= result.bindings.JsonString;
60
133
  if (!jsonString) {
61
134
  throw new Error("No JSON string in binding");
62
135
  }
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAyGA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAuH/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAgHA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAuH/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
@@ -32,6 +32,7 @@ import { resolveGitRepository, } from "../utils/git-repository-context.js";
32
32
  import { readKbManifestStatus } from "../utils/kb-manifest.js";
33
33
  import { manifestMergeDriverGaps, mergeDriverSetup, } from "../utils/merge-driver-setup.js";
34
34
  import { LATEST_KB_SCHEMA_VERSION } from "../utils/schema-version.js";
35
+ import { detectHookManager, hookManagerCommands, missingKibiHookCommands, } from "./hook-managers.js";
35
36
  import { KIBI_HOOK_BEGIN, hasManagedHooks, outdatedManagedHooks, } from "./init-helpers.js";
36
37
  import { planLegacyStorageMigration } from "./legacy-storage-migration.js";
37
38
  /**
@@ -837,6 +838,47 @@ function hooksPathSuffix() {
837
838
  : "";
838
839
  return ` (core.hooksPath=${context.hooksPathConfig}${origin})`;
839
840
  }
841
+ /**
842
+ * The hook manager (lefthook, husky, pre-commit) that owns this repository's
843
+ * hooks. Its hook files are generated runners, so the commands they run are
844
+ * read from the manager's configuration instead of the files Git executes.
845
+ */
846
+ // implements REQ-git-hook-manager-integration
847
+ function doctorHookManager() {
848
+ const context = doctorRepositoryContext();
849
+ if (!context)
850
+ return null;
851
+ return detectHookManager(context.worktreeRoot, context.effectiveHooksDir, context.hooksPathConfig);
852
+ }
853
+ // implements REQ-git-hook-manager-integration
854
+ function checkHookManagerDelegation(manager, hooks, consequence) {
855
+ const worktreeRoot = doctorRepositoryContext()?.worktreeRoot ?? process.cwd();
856
+ const owner = `Managed by ${manager.name} (${manager.configPath})`;
857
+ const coverage = hooks.map((hook) => ({
858
+ hook,
859
+ missing: missingKibiHookCommands(hook, hookManagerCommands(manager.name, worktreeRoot, hook) ?? []),
860
+ }));
861
+ const gaps = coverage.filter((entry) => entry.missing.length > 0);
862
+ if (gaps.length === 0) {
863
+ const runs = coverage
864
+ .map(({ hook }) => `${hook} runs ${missingKibiHookCommands(hook, [])
865
+ .map((label) => `'${label}'`)
866
+ .join(" and ")}`)
867
+ .join("; ");
868
+ return { passed: true, message: `${owner}; ${runs}` };
869
+ }
870
+ // The manager may reach Kibi through a task runner or script that is not
871
+ // part of its configuration, so an invisible command is a warning only.
872
+ const described = gaps
873
+ .map(({ hook, missing }) => `${hook} does not visibly run ${missing.map((label) => `'${label}'`).join(" and ")}`)
874
+ .join("; ");
875
+ return {
876
+ passed: true,
877
+ warning: true,
878
+ message: `${owner}; ${described}. Kibi reads only the ${manager.name} configuration, not the task runners or scripts it calls; unless they run these commands, ${consequence}`,
879
+ remediation: `Add Kibi's commands to ${manager.configPath}. Print them with: kibi init --print-hook ${gaps.length === 1 ? (gaps[0]?.hook ?? "all") : "all"} --format ${manager.name}`,
880
+ };
881
+ }
840
882
  /**
841
883
  * Kibi-managed hook sections must match what this CLI installs. A section
842
884
  * written by an older CLI keeps running while silently lacking newer gates
@@ -870,6 +912,10 @@ function checkManagedHookSections() {
870
912
  return { passed: true, message: "Current for this Kibi CLI" };
871
913
  }
872
914
  function checkGitHooks() {
915
+ const manager = doctorHookManager();
916
+ if (manager) {
917
+ return checkHookManagerDelegation(manager, ["post-checkout", "post-merge"], "a new branch is not compiled on checkout or after a merge");
918
+ }
873
919
  const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
874
920
  const postMergePath = path.join(effectiveHooksDir(), "post-merge");
875
921
  const preCommitPath = path.join(effectiveHooksDir(), "pre-commit");
@@ -919,42 +965,9 @@ function checkGitHooks() {
919
965
  remediation: "Run: kibi init",
920
966
  };
921
967
  }
922
- /**
923
- * Individual shell commands of a hook script, ignoring comments. Lines are
924
- * split on command separators so `a && b` counts as two commands.
925
- */
926
- // implements REQ-git-hook-effective-install
927
- function hookCommands(content) {
928
- return content
929
- .split("\n")
930
- .filter((line) => !line.trimStart().startsWith("#"))
931
- .flatMap((line) => line.split(/&&|\|\||;|\|/))
932
- .map((command) => command.trim())
933
- .filter((command) => command.length > 0);
934
- }
935
- // Matches `kibi <sub>`, `npx kibi <sub>`, `node_modules/.bin/kibi <sub>` and
936
- // the template's `"$KIBI_BIN" <sub>`.
937
- // implements REQ-git-hook-effective-install
938
- function invokesKibi(command, subcommand) {
939
- return new RegExp(`(?:\\bkibi|\\bKIBI_BIN)["'}]*\\s+${subcommand}(?=\\s|$)`).test(command);
940
- }
941
- /** The pre-commit gate the managed template runs, as a custom hook must. */
942
- const PRE_COMMIT_DELEGATIONS = [
943
- {
944
- label: "kibi check-generated --staged --changed-only",
945
- matches: (command) => invokesKibi(command, "check-generated") &&
946
- /\s--staged(?=\s|$)/.test(command) &&
947
- /\s--changed-only(?=\s|$)/.test(command),
948
- },
949
- {
950
- label: "kibi check --staged",
951
- matches: (command) => invokesKibi(command, "check") && /\s--staged(?=\s|$)/.test(command),
952
- },
953
- ];
954
968
  // implements REQ-git-hook-effective-install
955
969
  function checkCustomPreCommitHook(content, executable) {
956
- const commands = hookCommands(content);
957
- const missing = PRE_COMMIT_DELEGATIONS.filter((delegation) => !commands.some(delegation.matches)).map((delegation) => `'${delegation.label}'`);
970
+ const missing = missingKibiHookCommands("pre-commit", [content]).map((label) => `'${label}'`);
958
971
  if (missing.length > 0) {
959
972
  // An unmarked file that still carries the old template header is a Kibi
960
973
  // hook from before managed sections; removing it lets init reinstall it.
@@ -980,6 +993,10 @@ function checkCustomPreCommitHook(content, executable) {
980
993
  };
981
994
  }
982
995
  function checkPreCommitHook() {
996
+ const manager = doctorHookManager();
997
+ if (manager) {
998
+ return checkHookManagerDelegation(manager, ["pre-commit"], "commits skip Kibi enforcement");
999
+ }
983
1000
  const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
984
1001
  const postMergePath = path.join(effectiveHooksDir(), "post-merge");
985
1002
  const preCommitPath = path.join(effectiveHooksDir(), "pre-commit");
@@ -1063,6 +1080,10 @@ function checkPreCommitHook() {
1063
1080
  }
1064
1081
  }
1065
1082
  function checkPostRewriteHook() {
1083
+ const manager = doctorHookManager();
1084
+ if (manager) {
1085
+ return checkHookManagerDelegation(manager, ["post-rewrite"], "a rebased branch keeps a stale KB until the next 'kibi sync'");
1086
+ }
1066
1087
  const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
1067
1088
  const postMergePath = path.join(effectiveHooksDir(), "post-merge");
1068
1089
  const postRewritePath = path.join(effectiveHooksDir(), "post-rewrite");
@@ -1091,7 +1112,7 @@ function checkPostRewriteHook() {
1091
1112
  // A custom hook (no kibi-managed section) is never edited by init.
1092
1113
  // implements REQ-git-hook-effective-install
1093
1114
  if (!content.includes(KIBI_HOOK_BEGIN)) {
1094
- if (!hookCommands(content).some((cmd) => invokesKibi(cmd, "sync"))) {
1115
+ if (missingKibiHookCommands("post-rewrite", [content]).length > 0) {
1095
1116
  return {
1096
1117
  passed: false,
1097
1118
  message: `Custom post-rewrite hook (no kibi-managed section) does not run 'kibi sync'${hooksPathSuffix()}`,
@@ -1 +1 @@
1
- {"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"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"}
@@ -74,9 +74,11 @@ export function parseGitHubRemote(url) {
74
74
  return undefined;
75
75
  }
76
76
  export function githubPagesUrls(repo) {
77
+ // The *.github.io host is case-insensitive, but the project-site path is
78
+ // case-sensitive, so the repository segment keeps its exact case.
77
79
  const owner = repo.owner.toLowerCase();
78
- const name = repo.repo.toLowerCase();
79
- const isUserSite = name === `${owner}.github.io`;
80
+ const name = repo.repo;
81
+ const isUserSite = name.toLowerCase() === `${owner}.github.io`;
80
82
  const origin = isUserSite
81
83
  ? `https://${owner}.github.io/`
82
84
  : `https://${owner}.github.io/${name}/`;
@@ -0,0 +1,43 @@
1
+ import { type ManagedHookName } from "./init-helpers.js";
2
+ /** Git hook managers whose configuration Kibi can print and read. */
3
+ export declare const HOOK_MANAGER_NAMES: readonly ["lefthook", "husky", "pre-commit"];
4
+ export type HookManagerName = (typeof HOOK_MANAGER_NAMES)[number];
5
+ /** Formats `kibi init --print-hook` can emit. */
6
+ export declare const HOOK_SNIPPET_FORMATS: readonly ["shell", "lefthook", "husky", "pre-commit"];
7
+ export type HookSnippetFormat = (typeof HOOK_SNIPPET_FORMATS)[number];
8
+ export interface DetectedHookManager {
9
+ name: HookManagerName;
10
+ /** Repository-relative file or directory that holds the hook definitions. */
11
+ configPath: string;
12
+ }
13
+ /**
14
+ * The hook manager that owns this repository's Git hooks, if any. Installed
15
+ * hook files are the strongest evidence (they show what Git runs today), then
16
+ * a core.hooksPath pointing into `.husky`, then a manager configuration file
17
+ * that has not been installed yet.
18
+ */
19
+ export declare function detectHookManager(worktreeRoot: string, effectiveHooksDir: string, hooksPathConfig?: string | null): DetectedHookManager | null;
20
+ /**
21
+ * The commands a hook manager runs for one Git hook, read from its
22
+ * configuration, or null when the manager does not define that hook (or its
23
+ * configuration cannot be read).
24
+ */
25
+ export declare function hookManagerCommands(manager: HookManagerName, worktreeRoot: string, hook: ManagedHookName): string[] | null;
26
+ /** Labels of the Kibi commands a hook definition never visibly runs. */
27
+ export declare function missingKibiHookCommands(hook: ManagedHookName, scripts: readonly string[]): string[];
28
+ /**
29
+ * Configuration that wires the given hooks to the commands Kibi's managed
30
+ * templates run, in a hook manager's own format. `shell` and `husky` print
31
+ * the hook-script snippets of `kibi init --print-hook`.
32
+ */
33
+ export declare function hookManagerSnippet(format: HookSnippetFormat, hooks: readonly ManagedHookName[]): string;
34
+ export interface HookManagerCoverage {
35
+ hook: ManagedHookName;
36
+ /** Kibi commands the manager's definition of this hook does not visibly run. */
37
+ missing: string[];
38
+ /** Whether the manager defines the hook at all. */
39
+ configured: boolean;
40
+ }
41
+ /** What each Kibi-managed hook looks like in the manager's configuration. */
42
+ export declare function hookManagerCoverage(manager: HookManagerName, worktreeRoot: string): HookManagerCoverage[];
43
+ //# sourceMappingURL=hook-managers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-managers.d.ts","sourceRoot":"","sources":["../../src/commands/hook-managers.ts"],"names":[],"mappings":"AAqBA,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,mBAAmB,CAAC;AAE3B,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,8CAA+C,CAAC;AAE/E,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,iDAAiD;AACjD,eAAO,MAAM,oBAAoB,uDAA4C,CAAC;AAE9E,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;CACpB;AAqGD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,EACzB,eAAe,GAAE,MAAM,GAAG,IAAW,GACpC,mBAAmB,GAAG,IAAI,CAwB5B;AAmID;;;;GAIG;AAEH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,eAAe,GACpB,MAAM,EAAE,GAAG,IAAI,CAWjB;AAkED,wEAAwE;AAExE,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,MAAM,EAAE,CAKV;AAsFD;;;;GAIG;AAEH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,SAAS,eAAe,EAAE,GAChC,MAAM,CAiBR;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,gFAAgF;IAChF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mDAAmD;IACnD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,6EAA6E;AAE7E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,MAAM,GACnB,mBAAmB,EAAE,CASvB"}