@kb-labs/commit-cli 0.5.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 (118) hide show
  1. package/README.md +120 -0
  2. package/dist/cli/commands/apply.d.ts +22 -0
  3. package/dist/cli/commands/apply.js +132 -0
  4. package/dist/cli/commands/apply.js.map +1 -0
  5. package/dist/cli/commands/flags.d.ts +99 -0
  6. package/dist/cli/commands/flags.js +73 -0
  7. package/dist/cli/commands/flags.js.map +1 -0
  8. package/dist/cli/commands/generate.d.ts +45 -0
  9. package/dist/cli/commands/generate.js +149 -0
  10. package/dist/cli/commands/generate.js.map +1 -0
  11. package/dist/cli/commands/index.d.ts +1 -0
  12. package/dist/cli/commands/index.js +73 -0
  13. package/dist/cli/commands/index.js.map +1 -0
  14. package/dist/cli/commands/open.d.ts +50 -0
  15. package/dist/cli/commands/open.js +80 -0
  16. package/dist/cli/commands/open.js.map +1 -0
  17. package/dist/cli/commands/push.d.ts +18 -0
  18. package/dist/cli/commands/push.js +71 -0
  19. package/dist/cli/commands/push.js.map +1 -0
  20. package/dist/cli/commands/reset.d.ts +15 -0
  21. package/dist/cli/commands/reset.js +52 -0
  22. package/dist/cli/commands/reset.js.map +1 -0
  23. package/dist/cli/commands/run.d.ts +51 -0
  24. package/dist/cli/commands/run.js +190 -0
  25. package/dist/cli/commands/run.js.map +1 -0
  26. package/dist/index.d.ts +5 -0
  27. package/dist/index.js +916 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/lifecycle/setup.d.ts +53 -0
  30. package/dist/lifecycle/setup.js +96 -0
  31. package/dist/lifecycle/setup.js.map +1 -0
  32. package/dist/manifest.d.ts +207 -0
  33. package/dist/manifest.js +833 -0
  34. package/dist/manifest.js.map +1 -0
  35. package/dist/rest/handlers/actions-handler.d.ts +16 -0
  36. package/dist/rest/handlers/actions-handler.js +15 -0
  37. package/dist/rest/handlers/actions-handler.js.map +1 -0
  38. package/dist/rest/handlers/apply-handler.d.ts +26 -0
  39. package/dist/rest/handlers/apply-handler.js +115 -0
  40. package/dist/rest/handlers/apply-handler.js.map +1 -0
  41. package/dist/rest/handlers/diff-handler.d.ts +20 -0
  42. package/dist/rest/handlers/diff-handler.js +64 -0
  43. package/dist/rest/handlers/diff-handler.js.map +1 -0
  44. package/dist/rest/handlers/files-handler.d.ts +16 -0
  45. package/dist/rest/handlers/files-handler.js +143 -0
  46. package/dist/rest/handlers/files-handler.js.map +1 -0
  47. package/dist/rest/handlers/generate-handler.d.ts +66 -0
  48. package/dist/rest/handlers/generate-handler.js +97 -0
  49. package/dist/rest/handlers/generate-handler.js.map +1 -0
  50. package/dist/rest/handlers/git-status-handler.d.ts +13 -0
  51. package/dist/rest/handlers/git-status-handler.js +58 -0
  52. package/dist/rest/handlers/git-status-handler.js.map +1 -0
  53. package/dist/rest/handlers/patch-plan-handler.d.ts +23 -0
  54. package/dist/rest/handlers/patch-plan-handler.js +50 -0
  55. package/dist/rest/handlers/patch-plan-handler.js.map +1 -0
  56. package/dist/rest/handlers/plan-handler.d.ts +50 -0
  57. package/dist/rest/handlers/plan-handler.js +32 -0
  58. package/dist/rest/handlers/plan-handler.js.map +1 -0
  59. package/dist/rest/handlers/push-handler.d.ts +25 -0
  60. package/dist/rest/handlers/push-handler.js +75 -0
  61. package/dist/rest/handlers/push-handler.js.map +1 -0
  62. package/dist/rest/handlers/regenerate-handler.d.ts +37 -0
  63. package/dist/rest/handlers/regenerate-handler.js +124 -0
  64. package/dist/rest/handlers/regenerate-handler.js.map +1 -0
  65. package/dist/rest/handlers/reset-handler.d.ts +17 -0
  66. package/dist/rest/handlers/reset-handler.js +30 -0
  67. package/dist/rest/handlers/reset-handler.js.map +1 -0
  68. package/dist/rest/handlers/scope-resolver.d.ts +15 -0
  69. package/dist/rest/handlers/scope-resolver.js +12 -0
  70. package/dist/rest/handlers/scope-resolver.js.map +1 -0
  71. package/dist/rest/handlers/scopes-handler.d.ts +12 -0
  72. package/dist/rest/handlers/scopes-handler.js +24 -0
  73. package/dist/rest/handlers/scopes-handler.js.map +1 -0
  74. package/dist/rest/handlers/status-handler.d.ts +27 -0
  75. package/dist/rest/handlers/status-handler.js +91 -0
  76. package/dist/rest/handlers/status-handler.js.map +1 -0
  77. package/dist/rest/handlers/summarize-handler.d.ts +21 -0
  78. package/dist/rest/handlers/summarize-handler.js +106 -0
  79. package/dist/rest/handlers/summarize-handler.js.map +1 -0
  80. package/dist/widgets/220.js +446 -0
  81. package/dist/widgets/220.js.map +1 -0
  82. package/dist/widgets/331.js +2 -0
  83. package/dist/widgets/331.js.map +1 -0
  84. package/dist/widgets/403.js +2 -0
  85. package/dist/widgets/403.js.map +1 -0
  86. package/dist/widgets/406.js +35 -0
  87. package/dist/widgets/406.js.map +1 -0
  88. package/dist/widgets/455.js +2 -0
  89. package/dist/widgets/455.js.map +1 -0
  90. package/dist/widgets/482.js +2 -0
  91. package/dist/widgets/482.js.map +1 -0
  92. package/dist/widgets/485.js +2 -0
  93. package/dist/widgets/485.js.map +1 -0
  94. package/dist/widgets/527.js +2 -0
  95. package/dist/widgets/527.js.map +1 -0
  96. package/dist/widgets/628.js +2 -0
  97. package/dist/widgets/628.js.map +1 -0
  98. package/dist/widgets/694.js +2 -0
  99. package/dist/widgets/694.js.map +1 -0
  100. package/dist/widgets/712.js +2 -0
  101. package/dist/widgets/712.js.map +1 -0
  102. package/dist/widgets/866.js +2 -0
  103. package/dist/widgets/866.js.map +1 -0
  104. package/dist/widgets/915.js +39 -0
  105. package/dist/widgets/915.js.map +1 -0
  106. package/dist/widgets/957.js +10 -0
  107. package/dist/widgets/957.js.map +1 -0
  108. package/dist/widgets/983.js +2 -0
  109. package/dist/widgets/983.js.map +1 -0
  110. package/dist/widgets/@mf-types.d.ts +3 -0
  111. package/dist/widgets/@mf-types.zip +0 -0
  112. package/dist/widgets/__federation_expose_CommitOverview.js +2 -0
  113. package/dist/widgets/__federation_expose_CommitOverview.js.map +1 -0
  114. package/dist/widgets/mf-manifest.json +260 -0
  115. package/dist/widgets/mf-stats.json +302 -0
  116. package/dist/widgets/remoteEntry.js +7 -0
  117. package/dist/widgets/remoteEntry.js.map +1 -0
  118. package/package.json +95 -0
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # @kb-labs/plugin-template-cli
2
+
3
+ Reference CLI/REST/Studio plugin package for KB Labs Plugin Template.
4
+
5
+ ## Vision & Purpose
6
+
7
+ **@kb-labs/plugin-template-cli** is the canonical example plugin package used by `@kb-labs/plugin-template`.
8
+ It shows how to implement a plugin that exposes:
9
+
10
+ - a **CLI command** (Hello),
11
+ - a **REST handler**, and
12
+ - a **Studio widget**,
13
+
14
+ all driven by a single manifest and contracts package.
15
+
16
+ ## Package Status
17
+
18
+ - **Version**: 0.1.0
19
+ - **Stage**: Stable (template)
20
+ - **Status**: Reference Implementation ✅
21
+
22
+ ## Architecture
23
+
24
+ ### High-Level Overview
25
+
26
+ ```
27
+ plugin-cli
28
+
29
+ ├──► contracts (from @kb-labs/plugin-template-contracts)
30
+ ├──► shared (constants/helpers)
31
+ ├──► domain (Greeting entity and invariants)
32
+ ├──► application (use-cases: create greeting, etc.)
33
+ ├──► cli (Hello command wiring)
34
+ ├──► rest (Hello REST handler + schema)
35
+ └──► studio (Hello Studio widget)
36
+ ```
37
+
38
+ ### Key Components
39
+
40
+ - `src/domain/`: `Greeting` entity and domain rules
41
+ - `src/application/`: use-cases that orchestrate domain logic
42
+ - `src/cli/commands/hello/*`: CLI command implementation
43
+ - `src/rest/handlers/hello-handler.ts`: REST handler bound to manifest
44
+ - `src/studio/widgets/hello-widget.tsx`: Studio widget implementation
45
+ - `src/manifest.v2.ts`: Plugin manifest v2 (CLI/REST/Studio wiring)
46
+
47
+ ## Features
48
+
49
+ - **Single-source manifest** for CLI/REST/Studio surfaces
50
+ - **Layered architecture** (shared → domain → application → interface)
51
+ - **Type-safe contracts** via `@kb-labs/plugin-template-contracts`
52
+ - **Hello-world flow** demonstrating end-to-end plugin wiring
53
+
54
+ ## Exports
55
+
56
+ From `src/index.ts`:
57
+
58
+ - `manifest`: Plugin Manifest V2
59
+ - All public surfaces:
60
+ - CLI command exports
61
+ - domain/application/shared re-exports
62
+
63
+ ## Dependencies
64
+
65
+ ### Runtime
66
+
67
+ - `@kb-labs/setup-operations`: reusable setup operations
68
+ - `@kb-labs/plugin-manifest`: manifest types and helpers
69
+ - `@kb-labs/plugin-template-contracts`: public contracts for this template plugin
70
+ - `@kb-labs/shared-cli-ui`: shared CLI UI helpers
71
+ - `react`, `react-dom`, `zod`
72
+
73
+ ### Development
74
+
75
+ - `@kb-labs/devkit`: shared TS/ESLint/Vitest/TSUP presets
76
+ - `typescript`, `tsup`, `vitest`, `rimraf`
77
+
78
+ ## Scripts
79
+
80
+ From `kb-labs-plugin-template` repo root:
81
+
82
+ ```bash
83
+ pnpm install
84
+ pnpm --filter @kb-labs/plugin-template-cli build
85
+ pnpm --filter @kb-labs/plugin-template-cli test
86
+ ```
87
+
88
+ To run sandboxes, see the root `README.md` (`pnpm sandbox:cli`, `sandbox:rest`, `sandbox:studio`).
89
+
90
+ ## Command Implementation
91
+
92
+ This template demonstrates **three different approaches** to implementing CLI commands:
93
+
94
+ 1. **High-level wrapper (`defineCommand`)** - Recommended for most cases
95
+ 2. **Low-level atomic tools** - For maximum control
96
+ 3. **Hybrid approach** - Combining both
97
+
98
+ See [`COMMAND_IMPLEMENTATION_GUIDE.md`](./COMMAND_IMPLEMENTATION_GUIDE.md) for detailed explanations and examples.
99
+
100
+ ### Quick Start
101
+
102
+ The `template:hello` command in `src/cli/commands/hello/run.ts` shows all three approaches with working code examples. The default implementation uses Approach 1 (`defineCommand`), which provides:
103
+
104
+ - ✅ Zero-boilerplate flag validation
105
+ - ✅ Automatic analytics integration
106
+ - ✅ Structured logging
107
+ - ✅ Error handling
108
+ - ✅ Timing tracking
109
+ - ✅ JSON output mode
110
+
111
+ ## Customising for Your Plugin
112
+
113
+ When using this as a starting point:
114
+
115
+ - Rename the package in `package.json` (e.g. `@kb-labs/my-plugin-cli`)
116
+ - Update manifest IDs and the contracts package
117
+ - Replace the Hello flow with your own domain, use-cases, and surfaces
118
+ - Choose the command implementation approach that fits your needs (see `COMMAND_IMPLEMENTATION_GUIDE.md`)
119
+
120
+
@@ -0,0 +1,22 @@
1
+ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
+
3
+ /**
4
+ * commit:apply command
5
+ * Apply current commit plan
6
+ */
7
+ type ApplyInput = {
8
+ force?: boolean;
9
+ json?: boolean;
10
+ scope?: string;
11
+ };
12
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, ApplyInput, {
13
+ commits: {
14
+ message: string;
15
+ id: string;
16
+ sha: string;
17
+ }[];
18
+ success: boolean;
19
+ errors: string[];
20
+ }>;
21
+
22
+ export { _default as default };
@@ -0,0 +1,132 @@
1
+ import { defineCommand, findRepoRoot, useConfig, useLoader } from '@kb-labs/sdk';
2
+ import { loadPlan, applyCommitPlan, saveToHistory, clearPlan } from '@kb-labs/commit-core';
3
+ import { resolveCommitConfig } from '@kb-labs/commit-contracts';
4
+ import * as path from 'path';
5
+
6
+ // src/cli/commands/apply.ts
7
+ function resolveScopePath(baseCwd, scopeId = "root", scopes) {
8
+ const scopeDef = scopes?.find((s) => s.id === scopeId);
9
+ const relativePath = scopeDef?.path ?? (scopeId === "root" ? "." : scopeId);
10
+ return relativePath === "." ? baseCwd : path.join(baseCwd, relativePath);
11
+ }
12
+
13
+ // src/cli/commands/apply.ts
14
+ var apply_default = defineCommand({
15
+ id: "commit:apply",
16
+ description: "Apply current commit plan",
17
+ handler: {
18
+ async execute(ctx, input) {
19
+ const startTime = Date.now();
20
+ const cwd = await findRepoRoot(ctx.cwd || process.cwd()) ?? process.cwd();
21
+ const scope = input.scope ?? "root";
22
+ const fileConfig = await useConfig();
23
+ const config = resolveCommitConfig(fileConfig ?? {});
24
+ const scopeCwd = resolveScopePath(cwd, scope, config.scope?.scopes);
25
+ const loadLoader = useLoader("Loading commit plan...");
26
+ loadLoader.start();
27
+ const plan = await loadPlan(cwd, scope);
28
+ if (!plan) {
29
+ loadLoader.fail("No commit plan found");
30
+ ctx.ui?.error?.("Run `kb commit:generate` first.");
31
+ return {
32
+ exitCode: 1
33
+ };
34
+ }
35
+ if (plan.commits.length === 0) {
36
+ loadLoader.stop();
37
+ ctx.ui?.warn?.("Commit plan is empty. Nothing to apply.");
38
+ return {
39
+ exitCode: 0,
40
+ result: {
41
+ success: true,
42
+ commits: [],
43
+ errors: []
44
+ },
45
+ meta: {
46
+ timing: Date.now() - startTime
47
+ }
48
+ };
49
+ }
50
+ loadLoader.succeed(`Loaded plan with ${plan.commits.length} commit(s)`);
51
+ const applyLoader = useLoader(`Applying ${plan.commits.length} commit(s)...`);
52
+ applyLoader.start();
53
+ const result = await applyCommitPlan(scopeCwd, plan, {
54
+ force: input.force
55
+ });
56
+ if (result.success) {
57
+ await saveToHistory(cwd, plan, result, scope);
58
+ await clearPlan(cwd, scope);
59
+ applyLoader.succeed(`Applied ${result.appliedCommits.length} commit(s) successfully`);
60
+ } else {
61
+ applyLoader.fail("Failed to apply commits");
62
+ }
63
+ const output = {
64
+ success: result.success,
65
+ commits: result.appliedCommits.map((c) => ({
66
+ id: c.groupId,
67
+ sha: c.sha,
68
+ message: c.message
69
+ })),
70
+ errors: result.errors
71
+ };
72
+ if (input.json) {
73
+ ctx.ui?.json?.(output);
74
+ } else {
75
+ if (result.success) {
76
+ const commitsItems = result.appliedCommits.map((commit) => {
77
+ return `${commit.sha.substring(0, 7)} ${commit.message}`;
78
+ });
79
+ const sections = [];
80
+ if (commitsItems.length > 0) {
81
+ sections.push({
82
+ header: "Applied Commits",
83
+ items: commitsItems
84
+ });
85
+ }
86
+ const summaryItems = [
87
+ `Total commits: ${result.appliedCommits.length}`,
88
+ "Status: \u2705 Success"
89
+ ];
90
+ sections.unshift({
91
+ header: "Summary",
92
+ items: summaryItems
93
+ });
94
+ const timing = Date.now() - startTime;
95
+ ctx.ui?.success?.("Commits applied successfully", {
96
+ title: "Apply Commit Plan",
97
+ sections,
98
+ timing
99
+ });
100
+ } else {
101
+ const errorItems = result.errors.map((error) => error);
102
+ const timing = Date.now() - startTime;
103
+ ctx.ui?.error?.("Failed to apply commits", {
104
+ title: "Apply Commit Plan",
105
+ sections: [
106
+ {
107
+ header: "Summary",
108
+ items: [`Total errors: ${result.errors.length}`]
109
+ },
110
+ {
111
+ header: "Errors",
112
+ items: errorItems
113
+ }
114
+ ],
115
+ timing
116
+ });
117
+ }
118
+ }
119
+ return {
120
+ exitCode: result.success ? 0 : 1,
121
+ result: output,
122
+ meta: {
123
+ timing: Date.now() - startTime
124
+ }
125
+ };
126
+ }
127
+ }
128
+ });
129
+
130
+ export { apply_default as default };
131
+ //# sourceMappingURL=apply.js.map
132
+ //# sourceMappingURL=apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/rest/handlers/scope-resolver.ts","../../../src/cli/commands/apply.ts"],"names":[],"mappings":"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","file":"apply.js","sourcesContent":["import * as path from 'node:path';\nimport type { CommitScope } from '@kb-labs/commit-contracts';\n\n/**\n * Resolves a scope id to an absolute filesystem path.\n *\n * Looks up the scope in the provided scopes array by id.\n * Falls back to treating the id as a relative path from baseCwd (legacy compat).\n *\n * @param baseCwd - Workspace root (ctx.cwd)\n * @param scopeId - Scope identifier, e.g. \"root\", \"public/kb-labs\"\n * @param scopes - Configured scopes from CommitPluginConfig.scope.scopes\n */\nexport function resolveScopePath(\n baseCwd: string,\n scopeId: string = 'root',\n scopes?: CommitScope[],\n): string {\n const scopeDef = scopes?.find((s) => s.id === scopeId);\n const relativePath = scopeDef?.path ?? (scopeId === 'root' ? '.' : scopeId);\n return relativePath === '.' ? baseCwd : path.join(baseCwd, relativePath);\n}\n","/**\n * commit:apply command\n * Apply current commit plan\n */\n\nimport { defineCommand, useLoader, useConfig, findRepoRoot, type PluginContextV3 } from '@kb-labs/sdk';\nimport {\n applyCommitPlan,\n loadPlan,\n saveToHistory,\n clearPlan,\n} from '@kb-labs/commit-core';\nimport type { ApplyOutput, CommitPluginConfig } from '@kb-labs/commit-contracts';\nimport { resolveCommitConfig } from '@kb-labs/commit-contracts';\nimport { resolveScopePath } from '../../rest/handlers/scope-resolver';\n\ntype ApplyInput = {\n force?: boolean;\n json?: boolean;\n scope?: string;\n};\n\ntype ApplyResult = {\n exitCode: number;\n result?: ApplyOutput;\n meta?: Record<string, unknown>;\n};\n\nexport default defineCommand({\n id: 'commit:apply',\n description: 'Apply current commit plan',\n\n handler: {\n async execute(ctx: PluginContextV3, input: ApplyInput): Promise<ApplyResult> {\n const startTime = Date.now();\n const cwd = (await findRepoRoot(ctx.cwd || process.cwd())) ?? process.cwd();\n\n const scope = input.scope ?? 'root';\n const fileConfig = await useConfig<Partial<CommitPluginConfig>>();\n const config = resolveCommitConfig(fileConfig ?? {});\n const scopeCwd = resolveScopePath(cwd, scope, config.scope?.scopes);\n\n // Load current plan\n const loadLoader = useLoader('Loading commit plan...');\n loadLoader.start();\n const plan = await loadPlan(cwd, scope);\n\n if (!plan) {\n loadLoader.fail('No commit plan found');\n ctx.ui?.error?.('Run `kb commit:generate` first.');\n return {\n exitCode: 1,\n };\n }\n\n if (plan.commits.length === 0) {\n loadLoader.stop();\n ctx.ui?.warn?.('Commit plan is empty. Nothing to apply.');\n return {\n exitCode: 0,\n result: {\n success: true,\n commits: [],\n errors: [],\n },\n meta: {\n timing: Date.now() - startTime,\n },\n };\n }\n loadLoader.succeed(`Loaded plan with ${plan.commits.length} commit(s)`);\n\n // Apply plan\n const applyLoader = useLoader(`Applying ${plan.commits.length} commit(s)...`);\n applyLoader.start();\n const result = await applyCommitPlan(scopeCwd, plan, {\n force: input.force,\n });\n\n // Save to history and clear current plan on success\n if (result.success) {\n await saveToHistory(cwd, plan, result, scope);\n await clearPlan(cwd, scope);\n applyLoader.succeed(`Applied ${result.appliedCommits.length} commit(s) successfully`);\n } else {\n applyLoader.fail('Failed to apply commits');\n }\n\n // Output\n const output: ApplyOutput = {\n success: result.success,\n commits: result.appliedCommits.map((c) => ({\n id: c.groupId,\n sha: c.sha,\n message: c.message,\n })),\n errors: result.errors,\n };\n\n if (input.json) {\n ctx.ui?.json?.(output);\n } else {\n if (result.success) {\n // Build commits section\n const commitsItems = result.appliedCommits.map((commit) => {\n return `${commit.sha.substring(0, 7)} ${commit.message}`;\n });\n\n const sections: Array<{ header?: string; items: string[] }> = [];\n\n if (commitsItems.length > 0) {\n sections.push({\n header: 'Applied Commits',\n items: commitsItems,\n });\n }\n\n const summaryItems: string[] = [\n `Total commits: ${result.appliedCommits.length}`,\n 'Status: ✅ Success',\n ];\n\n sections.unshift({\n header: 'Summary',\n items: summaryItems,\n });\n\n const timing = Date.now() - startTime;\n\n ctx.ui?.success?.('Commits applied successfully', {\n title: 'Apply Commit Plan',\n sections,\n timing,\n });\n } else {\n const errorItems = result.errors.map((error) => error);\n const timing = Date.now() - startTime;\n\n ctx.ui?.error?.('Failed to apply commits', {\n title: 'Apply Commit Plan',\n sections: [\n {\n header: 'Summary',\n items: [`Total errors: ${result.errors.length}`],\n },\n {\n header: 'Errors',\n items: errorItems,\n },\n ],\n timing,\n });\n }\n }\n\n return {\n exitCode: result.success ? 0 : 1,\n result: output,\n meta: {\n timing: Date.now() - startTime,\n },\n };\n },\n },\n});\n"]}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Shared command flags definitions
3
+ *
4
+ * DRY pattern: Define flags once, use in both manifest and command handlers.
5
+ */
6
+ /**
7
+ * Flags for commit:generate command
8
+ */
9
+ declare const generateFlags: {
10
+ readonly scope: {
11
+ readonly type: "string";
12
+ readonly description: "Filter by package name (@kb-labs/core), wildcard (@kb-labs/*), or path pattern (packages/**)";
13
+ readonly alias: "s";
14
+ };
15
+ readonly json: {
16
+ readonly type: "boolean";
17
+ readonly description: "Output JSON";
18
+ readonly default: false;
19
+ };
20
+ };
21
+ type GenerateFlags = typeof generateFlags;
22
+ /**
23
+ * Flags for commit:apply command
24
+ */
25
+ declare const applyFlags: {
26
+ readonly force: {
27
+ readonly type: "boolean";
28
+ readonly description: "Apply even if working tree changed";
29
+ readonly default: false;
30
+ readonly alias: "f";
31
+ };
32
+ readonly json: {
33
+ readonly type: "boolean";
34
+ readonly description: "Output JSON";
35
+ readonly default: false;
36
+ };
37
+ };
38
+ type ApplyFlags = typeof applyFlags;
39
+ /**
40
+ * Flags for commit:push command
41
+ */
42
+ declare const pushFlags: {
43
+ readonly force: {
44
+ readonly type: "boolean";
45
+ readonly description: "Force push (dangerous!)";
46
+ readonly default: false;
47
+ readonly alias: "f";
48
+ };
49
+ readonly json: {
50
+ readonly type: "boolean";
51
+ readonly description: "Output JSON";
52
+ readonly default: false;
53
+ };
54
+ };
55
+ type PushFlags = typeof pushFlags;
56
+ /**
57
+ * Flags for commit (run) command - combines generate + apply + optional push
58
+ */
59
+ declare const runFlags: {
60
+ readonly scope: {
61
+ readonly type: "string";
62
+ readonly description: "Filter by package name (@kb-labs/core), wildcard (@kb-labs/*), or path pattern (packages/**)";
63
+ readonly alias: "s";
64
+ };
65
+ readonly json: {
66
+ readonly type: "boolean";
67
+ readonly description: "Output JSON";
68
+ readonly default: false;
69
+ };
70
+ readonly 'dry-run': {
71
+ readonly type: "boolean";
72
+ readonly description: "Generate plan only, do not apply";
73
+ readonly default: false;
74
+ };
75
+ readonly 'with-push': {
76
+ readonly type: "boolean";
77
+ readonly description: "Push after apply";
78
+ readonly default: false;
79
+ };
80
+ };
81
+ type RunFlags = typeof runFlags;
82
+ /**
83
+ * Common json-only flags for simple commands
84
+ */
85
+ declare const jsonOnlyFlags: {
86
+ readonly json: {
87
+ readonly type: "boolean";
88
+ readonly description: "Output JSON";
89
+ readonly default: false;
90
+ };
91
+ };
92
+ type JsonOnlyFlags = typeof jsonOnlyFlags;
93
+ /**
94
+ * Empty flags for commands that take no arguments
95
+ */
96
+ declare const emptyFlags: {};
97
+ type EmptyFlags = typeof emptyFlags;
98
+
99
+ export { type ApplyFlags, type EmptyFlags, type GenerateFlags, type JsonOnlyFlags, type PushFlags, type RunFlags, applyFlags, emptyFlags, generateFlags, jsonOnlyFlags, pushFlags, runFlags };
@@ -0,0 +1,73 @@
1
+ // src/cli/commands/flags.ts
2
+ var generateFlags = {
3
+ scope: {
4
+ type: "string",
5
+ description: "Filter by package name (@kb-labs/core), wildcard (@kb-labs/*), or path pattern (packages/**)",
6
+ alias: "s"
7
+ },
8
+ json: {
9
+ type: "boolean",
10
+ description: "Output JSON",
11
+ default: false
12
+ }
13
+ };
14
+ var applyFlags = {
15
+ force: {
16
+ type: "boolean",
17
+ description: "Apply even if working tree changed",
18
+ default: false,
19
+ alias: "f"
20
+ },
21
+ json: {
22
+ type: "boolean",
23
+ description: "Output JSON",
24
+ default: false
25
+ }
26
+ };
27
+ var pushFlags = {
28
+ force: {
29
+ type: "boolean",
30
+ description: "Force push (dangerous!)",
31
+ default: false,
32
+ alias: "f"
33
+ },
34
+ json: {
35
+ type: "boolean",
36
+ description: "Output JSON",
37
+ default: false
38
+ }
39
+ };
40
+ var runFlags = {
41
+ scope: {
42
+ type: "string",
43
+ description: "Filter by package name (@kb-labs/core), wildcard (@kb-labs/*), or path pattern (packages/**)",
44
+ alias: "s"
45
+ },
46
+ json: {
47
+ type: "boolean",
48
+ description: "Output JSON",
49
+ default: false
50
+ },
51
+ "dry-run": {
52
+ type: "boolean",
53
+ description: "Generate plan only, do not apply",
54
+ default: false
55
+ },
56
+ "with-push": {
57
+ type: "boolean",
58
+ description: "Push after apply",
59
+ default: false
60
+ }
61
+ };
62
+ var jsonOnlyFlags = {
63
+ json: {
64
+ type: "boolean",
65
+ description: "Output JSON",
66
+ default: false
67
+ }
68
+ };
69
+ var emptyFlags = {};
70
+
71
+ export { applyFlags, emptyFlags, generateFlags, jsonOnlyFlags, pushFlags, runFlags };
72
+ //# sourceMappingURL=flags.js.map
73
+ //# sourceMappingURL=flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cli/commands/flags.ts"],"names":[],"mappings":";AASO,IAAM,aAAA,GAAgB;AAAA,EAC3B,KAAA,EAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,WAAA,EAAa,8FAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,aAAA;AAAA,IACb,OAAA,EAAS;AAAA;AAEb;AAOO,IAAM,UAAA,GAAa;AAAA,EACxB,KAAA,EAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,oCAAA;AAAA,IACb,OAAA,EAAS,KAAA;AAAA,IACT,KAAA,EAAO;AAAA,GACT;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,aAAA;AAAA,IACb,OAAA,EAAS;AAAA;AAEb;AAOO,IAAM,SAAA,GAAY;AAAA,EACvB,KAAA,EAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,yBAAA;AAAA,IACb,OAAA,EAAS,KAAA;AAAA,IACT,KAAA,EAAO;AAAA,GACT;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,aAAA;AAAA,IACb,OAAA,EAAS;AAAA;AAEb;AAOO,IAAM,QAAA,GAAW;AAAA,EACtB,KAAA,EAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,WAAA,EAAa,8FAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,aAAA;AAAA,IACb,OAAA,EAAS;AAAA,GACX;AAAA,EACA,SAAA,EAAW;AAAA,IACT,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,kCAAA;AAAA,IACb,OAAA,EAAS;AAAA,GACX;AAAA,EACA,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,kBAAA;AAAA,IACb,OAAA,EAAS;AAAA;AAEb;AAOO,IAAM,aAAA,GAAgB;AAAA,EAC3B,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,SAAA;AAAA,IACN,WAAA,EAAa,aAAA;AAAA,IACb,OAAA,EAAS;AAAA;AAEb;AAOO,IAAM,aAAa","file":"flags.js","sourcesContent":["/**\n * Shared command flags definitions\n *\n * DRY pattern: Define flags once, use in both manifest and command handlers.\n */\n\n/**\n * Flags for commit:generate command\n */\nexport const generateFlags = {\n scope: {\n type: 'string',\n description: 'Filter by package name (@kb-labs/core), wildcard (@kb-labs/*), or path pattern (packages/**)',\n alias: 's',\n },\n json: {\n type: 'boolean',\n description: 'Output JSON',\n default: false,\n },\n} as const;\n\nexport type GenerateFlags = typeof generateFlags;\n\n/**\n * Flags for commit:apply command\n */\nexport const applyFlags = {\n force: {\n type: 'boolean',\n description: 'Apply even if working tree changed',\n default: false,\n alias: 'f',\n },\n json: {\n type: 'boolean',\n description: 'Output JSON',\n default: false,\n },\n} as const;\n\nexport type ApplyFlags = typeof applyFlags;\n\n/**\n * Flags for commit:push command\n */\nexport const pushFlags = {\n force: {\n type: 'boolean',\n description: 'Force push (dangerous!)',\n default: false,\n alias: 'f',\n },\n json: {\n type: 'boolean',\n description: 'Output JSON',\n default: false,\n },\n} as const;\n\nexport type PushFlags = typeof pushFlags;\n\n/**\n * Flags for commit (run) command - combines generate + apply + optional push\n */\nexport const runFlags = {\n scope: {\n type: 'string',\n description: 'Filter by package name (@kb-labs/core), wildcard (@kb-labs/*), or path pattern (packages/**)',\n alias: 's',\n },\n json: {\n type: 'boolean',\n description: 'Output JSON',\n default: false,\n },\n 'dry-run': {\n type: 'boolean',\n description: 'Generate plan only, do not apply',\n default: false,\n },\n 'with-push': {\n type: 'boolean',\n description: 'Push after apply',\n default: false,\n },\n} as const;\n\nexport type RunFlags = typeof runFlags;\n\n/**\n * Common json-only flags for simple commands\n */\nexport const jsonOnlyFlags = {\n json: {\n type: 'boolean',\n description: 'Output JSON',\n default: false,\n },\n} as const;\n\nexport type JsonOnlyFlags = typeof jsonOnlyFlags;\n\n/**\n * Empty flags for commands that take no arguments\n */\nexport const emptyFlags = {} as const;\n\nexport type EmptyFlags = typeof emptyFlags;\n"]}
@@ -0,0 +1,45 @@
1
+ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
+
3
+ /**
4
+ * commit:generate command
5
+ * Generate commit plan from git changes
6
+ */
7
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, any, {
8
+ plan: {
9
+ schemaVersion: "1.0";
10
+ createdAt: string;
11
+ repoRoot: string;
12
+ gitStatus: {
13
+ staged: string[];
14
+ unstaged: string[];
15
+ untracked: string[];
16
+ };
17
+ commits: {
18
+ message: string;
19
+ type: "feat" | "fix" | "refactor" | "chore" | "docs" | "test" | "build" | "ci" | "perf";
20
+ id: string;
21
+ files: string[];
22
+ releaseHint: "none" | "patch" | "minor" | "major";
23
+ breaking: boolean;
24
+ scope?: string | undefined;
25
+ body?: string | undefined;
26
+ reasoning?: {
27
+ newBehavior: boolean;
28
+ fixesBug: boolean;
29
+ internalOnly: boolean;
30
+ explanation: string;
31
+ confidence: number;
32
+ } | undefined;
33
+ }[];
34
+ metadata: {
35
+ totalFiles: number;
36
+ totalCommits: number;
37
+ llmUsed: boolean;
38
+ tokensUsed?: number | undefined;
39
+ escalated?: boolean | undefined;
40
+ };
41
+ };
42
+ planPath: string;
43
+ }>;
44
+
45
+ export { _default as default };
@@ -0,0 +1,149 @@
1
+ import { defineCommand, useLLM, findRepoRoot, useConfig, useLoader, displayArtifacts } from '@kb-labs/sdk';
2
+ import { stat } from 'fs/promises';
3
+ import { getGitStatus, hasChanges, generateCommitPlan, savePlan, getCurrentPlanPath } from '@kb-labs/commit-core';
4
+ import { commitEnv, resolveCommitConfig } from '@kb-labs/commit-contracts';
5
+ import * as path from 'path';
6
+
7
+ // src/cli/commands/generate.ts
8
+ function resolveScopePath(baseCwd, scopeId = "root", scopes) {
9
+ const scopeDef = scopes?.find((s) => s.id === scopeId);
10
+ const relativePath = scopeDef?.path ?? (scopeId === "root" ? "." : scopeId);
11
+ return relativePath === "." ? baseCwd : path.join(baseCwd, relativePath);
12
+ }
13
+
14
+ // src/cli/commands/generate.ts
15
+ var generate_default = defineCommand({
16
+ id: "commit:generate",
17
+ description: "Generate commit plan from git changes",
18
+ handler: {
19
+ async execute(ctx, input) {
20
+ const startTime = Date.now();
21
+ const llm = useLLM();
22
+ const cwd = await findRepoRoot(ctx.cwd || process.cwd()) ?? process.cwd();
23
+ const fileConfig = await useConfig();
24
+ const env = commitEnv.parse(ctx.runtime);
25
+ const config = resolveCommitConfig(fileConfig ?? {}, env);
26
+ const flags = input.flags ?? input;
27
+ const effectiveScope = flags.scope ?? config.scope?.default ?? "root";
28
+ const scopeCwd = resolveScopePath(cwd, effectiveScope, config.scope?.scopes);
29
+ const allowSecrets = flags["allow-secrets"] ?? false;
30
+ const autoConfirm = flags.yes ?? false;
31
+ const statusLoader = useLoader("Checking git status...");
32
+ statusLoader.start();
33
+ const status = await getGitStatus(scopeCwd);
34
+ if (!hasChanges(status)) {
35
+ statusLoader.stop();
36
+ ctx.ui?.warn?.("No changes to commit");
37
+ return {
38
+ exitCode: 1
39
+ };
40
+ }
41
+ statusLoader.succeed("Found changes to commit");
42
+ const analyzeLoader = useLoader("Analyzing changes...");
43
+ analyzeLoader.start();
44
+ const llmComplete = llm && config.llm.enabled ? async (prompt, options) => {
45
+ const result = await llm.complete(prompt, {
46
+ ...options,
47
+ temperature: options?.temperature ?? config.llm.temperature,
48
+ maxTokens: options?.maxTokens ?? config.llm.maxTokens
49
+ });
50
+ return {
51
+ content: result.content,
52
+ tokensUsed: result.usage ? result.usage.promptTokens + result.usage.completionTokens : void 0
53
+ };
54
+ } : void 0;
55
+ const plan = await generateCommitPlan({
56
+ cwd: scopeCwd,
57
+ llmComplete,
58
+ config,
59
+ allowSecrets,
60
+ autoConfirm,
61
+ onProgress: (message) => analyzeLoader.update({ text: message })
62
+ });
63
+ const saveLoader = useLoader("Saving plan...");
64
+ saveLoader.start();
65
+ await savePlan(cwd, plan, effectiveScope);
66
+ const planPath = getCurrentPlanPath(cwd, effectiveScope);
67
+ saveLoader.succeed("Plan saved");
68
+ analyzeLoader.succeed(`Generated commit plan with ${plan.commits.length} commit(s)`);
69
+ const output = {
70
+ plan,
71
+ planPath
72
+ };
73
+ if (input.json) {
74
+ ctx.ui?.json?.(output);
75
+ } else {
76
+ const commitsItems = plan.commits.map((commit) => {
77
+ const scope = commit.scope ? `(${commit.scope})` : "";
78
+ return `${commit.type}${scope}: ${commit.message} [${commit.files.length} file(s)]`;
79
+ });
80
+ const artifacts = [];
81
+ try {
82
+ const planStats = await stat(planPath);
83
+ artifacts.push({
84
+ name: "Commit Plan",
85
+ path: planPath,
86
+ size: planStats.size,
87
+ modified: planStats.mtime,
88
+ description: "Generated commit plan in JSON format"
89
+ });
90
+ } catch {
91
+ }
92
+ const sections = [];
93
+ if (commitsItems.length > 0) {
94
+ sections.push({
95
+ header: "Commits",
96
+ items: commitsItems
97
+ });
98
+ }
99
+ if (artifacts.length > 0) {
100
+ const artifactsLines = displayArtifacts(artifacts, {
101
+ showSize: true,
102
+ showTime: true,
103
+ showDescription: true,
104
+ maxItems: 10,
105
+ title: ""
106
+ });
107
+ sections.push({
108
+ header: "Artifacts",
109
+ items: artifactsLines
110
+ });
111
+ }
112
+ const summaryItems = [
113
+ `Files: ${plan.metadata.totalFiles}`,
114
+ `Commits: ${plan.metadata.totalCommits}`
115
+ ];
116
+ if (plan.metadata.llmUsed) {
117
+ const llmPhase = plan.metadata.escalated ? "Phase 2 (with diff)" : "Phase 1";
118
+ summaryItems.push(`LLM: ${llmPhase}`);
119
+ if (plan.metadata.tokensUsed) {
120
+ summaryItems.push(`Tokens: ${plan.metadata.tokensUsed}`);
121
+ }
122
+ } else {
123
+ summaryItems.push("Generator: Heuristics");
124
+ }
125
+ sections.unshift({
126
+ header: "Summary",
127
+ items: summaryItems
128
+ });
129
+ const timing = Date.now() - startTime;
130
+ ctx.ui?.success?.("Plan generated and saved", {
131
+ title: "Generate Commit Plan",
132
+ sections,
133
+ timing
134
+ });
135
+ }
136
+ return {
137
+ exitCode: 0,
138
+ result: output,
139
+ meta: {
140
+ timing: Date.now() - startTime
141
+ }
142
+ };
143
+ }
144
+ }
145
+ });
146
+
147
+ export { generate_default as default };
148
+ //# sourceMappingURL=generate.js.map
149
+ //# sourceMappingURL=generate.js.map