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.
- package/dist/cli-operation-metadata.d.ts +1 -1
- package/dist/cli-operation-metadata.js +1 -1
- package/dist/cli-register-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +2 -1
- package/dist/cli-register-maintenance.d.ts.map +1 -1
- package/dist/cli-register-maintenance.js +5 -0
- package/dist/cli-validate.d.ts.map +1 -1
- package/dist/cli-validate.js +21 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +16 -1
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +89 -16
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +56 -35
- package/dist/commands/github-init.d.ts.map +1 -1
- package/dist/commands/github-init.js +4 -2
- package/dist/commands/hook-managers.d.ts +43 -0
- package/dist/commands/hook-managers.d.ts.map +1 -0
- package/dist/commands/hook-managers.js +426 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +40 -5
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +43 -1
- package/dist/commands/telemetry.d.ts +7 -0
- package/dist/commands/telemetry.d.ts.map +1 -0
- package/dist/commands/telemetry.js +23 -0
- package/dist/decision-firmness.d.ts.map +1 -1
- package/dist/decision-firmness.js +11 -14
- package/dist/engine-limits.d.ts.map +1 -1
- package/dist/engine-limits.js +8 -10
- package/dist/entity-body-context.d.ts.map +1 -1
- package/dist/entity-body-context.js +39 -36
- package/dist/extractors/symbol-coordinates.d.ts.map +1 -1
- package/dist/extractors/symbol-coordinates.js +23 -4
- package/dist/firm-decision-edit.d.ts.map +1 -1
- package/dist/firm-decision-edit.js +1 -3
- package/dist/intent-search.d.ts +5 -1
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +118 -33
- package/dist/logic/ir.d.ts.map +1 -1
- package/dist/logic/ir.js +82 -108
- package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
- package/dist/operations/bootstrap/guidance-actions.js +2 -1
- package/dist/operations/bootstrap/plugin-offers.d.ts +11 -2
- package/dist/operations/bootstrap/plugin-offers.d.ts.map +1 -1
- package/dist/operations/bootstrap/plugin-offers.js +48 -9
- package/dist/operations/proof/claim-bindings.d.ts.map +1 -1
- package/dist/operations/proof/claim-bindings.js +1 -0
- package/dist/operations/proof/code-certificates.d.ts +2 -0
- package/dist/operations/proof/code-certificates.d.ts.map +1 -1
- package/dist/operations/proof/code-certificates.js +34 -14
- package/dist/operations/proof/code-models.d.ts.map +1 -1
- package/dist/operations/proof/code-models.js +19 -5
- package/dist/operations/proof/code-runner.d.ts +16 -0
- package/dist/operations/proof/code-runner.d.ts.map +1 -1
- package/dist/operations/proof/code-runner.js +42 -6
- package/dist/plugins/compose-search-hints.d.ts +29 -0
- package/dist/plugins/compose-search-hints.d.ts.map +1 -0
- package/dist/plugins/compose-search-hints.js +94 -0
- package/dist/plugins/external-allowlist.d.ts +7 -0
- package/dist/plugins/external-allowlist.d.ts.map +1 -1
- package/dist/plugins/external-allowlist.js +11 -0
- package/dist/plugins/registry.d.ts +8 -1
- package/dist/plugins/registry.d.ts.map +1 -1
- package/dist/plugins/registry.js +22 -3
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +10 -20
- package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
- package/dist/public/impact/coverage-depth-quality.js +32 -16
- package/dist/public/impact/full-kb-quality.d.ts +6 -0
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +8 -3
- package/dist/public/impact/requirement-quality.d.ts.map +1 -1
- package/dist/public/impact/requirement-quality.js +56 -29
- package/dist/public/operations/catalog.d.ts +13 -3
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts +6 -0
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +34 -2
- package/dist/public/operations/discovery-executors.d.ts +5 -1
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +65 -4
- package/dist/public/operations/evidence-floor.d.ts +8 -1
- package/dist/public/operations/evidence-floor.d.ts.map +1 -1
- package/dist/public/operations/evidence-floor.js +3 -4
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +41 -10
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +3 -1
- package/dist/public/operations/source-analysis-cache.d.ts +22 -0
- package/dist/public/operations/source-analysis-cache.d.ts.map +1 -0
- package/dist/public/operations/source-analysis-cache.js +157 -0
- package/dist/public/operations/specs/discovery.d.ts +7 -2
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +7 -2
- package/dist/public/operations/specs/mutation-schemas.d.ts +6 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/upsert.d.ts +6 -1
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/symbol-granularity-check.d.ts +3 -1
- package/dist/public/operations/symbol-granularity-check.d.ts.map +1 -1
- package/dist/public/operations/symbol-granularity-check.js +21 -7
- package/dist/public/proof-protocol.d.ts +6 -1
- package/dist/public/proof-protocol.d.ts.map +1 -1
- package/dist/public/proof-protocol.js +12 -3
- package/dist/public/proof-sources.d.ts +2 -0
- package/dist/public/proof-sources.d.ts.map +1 -1
- package/dist/public/proof-sources.js +32 -6
- package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/dist/public/skills/kibi-usage/SKILL.md +42 -3
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +34 -0
- package/dist/public/skills/kibi-usage/resources/proof.md +13 -5
- package/dist/public/skills/kibi-usage/resources/workflows.md +10 -0
- package/dist/relationships/shards.d.ts +2 -0
- package/dist/relationships/shards.d.ts.map +1 -1
- package/dist/relationships/shards.js +25 -1
- package/dist/schemas/entity.schema.json +6 -1
- package/dist/search-answer.js +1 -1
- package/dist/search-hints.d.ts +58 -0
- package/dist/search-hints.d.ts.map +1 -0
- package/dist/search-hints.js +187 -0
- package/dist/search-ranking.d.ts +7 -0
- package/dist/search-ranking.d.ts.map +1 -1
- package/dist/search-ranking.js +54 -56
- package/dist/search-token-cache.d.ts +30 -0
- package/dist/search-token-cache.d.ts.map +1 -0
- package/dist/search-token-cache.js +86 -0
- package/dist/usage-telemetry.d.ts +11 -0
- package/dist/usage-telemetry.d.ts.map +1 -0
- package/dist/usage-telemetry.js +47 -0
- package/dist/utils/branch-resolver.d.ts.map +1 -1
- package/dist/utils/branch-resolver.js +1 -0
- package/package.json +5 -4
- package/src/public/impact/coverage-depth-quality.ts +59 -21
- package/src/public/impact/full-kb-quality.ts +15 -1
- package/src/public/impact/requirement-quality.ts +95 -38
- package/src/public/operations/check-executor.ts +41 -1
- package/src/public/operations/discovery-executors.ts +92 -4
- package/src/public/operations/evidence-floor.ts +15 -3
- package/src/public/operations/migration-plan.ts +41 -9
- package/src/public/operations/node-ports.ts +3 -1
- package/src/public/operations/source-analysis-cache.ts +196 -0
- package/src/public/operations/specs/discovery.ts +8 -2
- package/src/public/operations/symbol-granularity-check.ts +25 -5
- package/src/public/proof-protocol-types.d.ts +1 -1
- package/src/public/proof-protocol.ts +18 -4
- package/src/public/proof-sources.ts +37 -6
- package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/src/public/skills/kibi-usage/SKILL.md +42 -3
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +34 -0
- package/src/public/skills/kibi-usage/resources/proof.md +13 -5
- package/src/public/skills/kibi-usage/resources/workflows.md +10 -0
- 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,
|
|
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,
|
|
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;
|
|
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"}
|
package/dist/cli-validate.js
CHANGED
|
@@ -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
|
|
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;
|
|
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
|
|
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":"
|
|
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
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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":"
|
|
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"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -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
|
|
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 (
|
|
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":"AAgCA,eAAO,MAAM,8BAA8B,sCACN,CAAC;AACtC,eAAO,MAAM,6BAA6B,qCAAqC,CAAC;AAChF,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,cAAc,4BAA4B,CAAC;AACxD,eAAO,MAAM,oBAAoB,qFACmD,CAAC;AACrF,eAAO,MAAM,iBAAiB,UAAU,CAAC;AACzC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAM7C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AACvE,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,WAAW,GACX,SAAS,GACT,sBAAsB,CAAC;AAC3B,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,WAAW,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;IAC3C,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9B,CAAC,CAAC;AAGH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,kBAAkB,GACvB,MAAM,CAER;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAS3E;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CA+BrE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,
|
|
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
|
|
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"}
|