habit-hooks 0.1.0-beta.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 (192) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +233 -0
  3. package/dist/baseline/commands.d.ts +12 -0
  4. package/dist/baseline/commands.js +131 -0
  5. package/dist/baseline/commands.js.map +1 -0
  6. package/dist/baseline/file-hash.d.ts +2 -0
  7. package/dist/baseline/file-hash.js +25 -0
  8. package/dist/baseline/file-hash.js.map +1 -0
  9. package/dist/baseline/filter.d.ts +8 -0
  10. package/dist/baseline/filter.js +31 -0
  11. package/dist/baseline/filter.js.map +1 -0
  12. package/dist/baseline/store.d.ts +18 -0
  13. package/dist/baseline/store.js +106 -0
  14. package/dist/baseline/store.js.map +1 -0
  15. package/dist/checks/comment-check.d.ts +3 -0
  16. package/dist/checks/comment-check.js +83 -0
  17. package/dist/checks/comment-check.js.map +1 -0
  18. package/dist/checks/eslint-wrap.d.ts +2 -0
  19. package/dist/checks/eslint-wrap.js +104 -0
  20. package/dist/checks/eslint-wrap.js.map +1 -0
  21. package/dist/checks/jscpd-wrap.d.ts +6 -0
  22. package/dist/checks/jscpd-wrap.js +158 -0
  23. package/dist/checks/jscpd-wrap.js.map +1 -0
  24. package/dist/checks/knip-resolve.d.ts +4 -0
  25. package/dist/checks/knip-resolve.js +49 -0
  26. package/dist/checks/knip-resolve.js.map +1 -0
  27. package/dist/checks/knip-schema.d.ts +32 -0
  28. package/dist/checks/knip-schema.js +24 -0
  29. package/dist/checks/knip-schema.js.map +1 -0
  30. package/dist/checks/knip-wrap.d.ts +4 -0
  31. package/dist/checks/knip-wrap.js +127 -0
  32. package/dist/checks/knip-wrap.js.map +1 -0
  33. package/dist/cli/baseline-commands.d.ts +2 -0
  34. package/dist/cli/baseline-commands.js +61 -0
  35. package/dist/cli/baseline-commands.js.map +1 -0
  36. package/dist/cli/emit.d.ts +7 -0
  37. package/dist/cli/emit.js +8 -0
  38. package/dist/cli/emit.js.map +1 -0
  39. package/dist/cli/init/detect.d.ts +8 -0
  40. package/dist/cli/init/detect.js +20 -0
  41. package/dist/cli/init/detect.js.map +1 -0
  42. package/dist/cli/init/git-hook.d.ts +6 -0
  43. package/dist/cli/init/git-hook.js +48 -0
  44. package/dist/cli/init/git-hook.js.map +1 -0
  45. package/dist/cli/init/install-commands.d.ts +6 -0
  46. package/dist/cli/init/install-commands.js +55 -0
  47. package/dist/cli/init/install-commands.js.map +1 -0
  48. package/dist/cli/init/package-scripts.d.ts +6 -0
  49. package/dist/cli/init/package-scripts.js +55 -0
  50. package/dist/cli/init/package-scripts.js.map +1 -0
  51. package/dist/cli/init/prompts.d.ts +9 -0
  52. package/dist/cli/init/prompts.js +33 -0
  53. package/dist/cli/init/prompts.js.map +1 -0
  54. package/dist/cli/init/reporters.d.ts +11 -0
  55. package/dist/cli/init/reporters.js +40 -0
  56. package/dist/cli/init/reporters.js.map +1 -0
  57. package/dist/cli/init/run.d.ts +12 -0
  58. package/dist/cli/init/run.js +159 -0
  59. package/dist/cli/init/run.js.map +1 -0
  60. package/dist/cli/init/scaffold-baseline.d.ts +4 -0
  61. package/dist/cli/init/scaffold-baseline.js +11 -0
  62. package/dist/cli/init/scaffold-baseline.js.map +1 -0
  63. package/dist/cli/init/scaffold-config.d.ts +13 -0
  64. package/dist/cli/init/scaffold-config.js +42 -0
  65. package/dist/cli/init/scaffold-config.js.map +1 -0
  66. package/dist/cli/init/scaffold-eslint-config.d.ts +2 -0
  67. package/dist/cli/init/scaffold-eslint-config.js +12 -0
  68. package/dist/cli/init/scaffold-eslint-config.js.map +1 -0
  69. package/dist/cli/init/scaffold-jscpd-config.d.ts +2 -0
  70. package/dist/cli/init/scaffold-jscpd-config.js +12 -0
  71. package/dist/cli/init/scaffold-jscpd-config.js.map +1 -0
  72. package/dist/cli/init/scaffold-knip-config.d.ts +2 -0
  73. package/dist/cli/init/scaffold-knip-config.js +12 -0
  74. package/dist/cli/init/scaffold-knip-config.js.map +1 -0
  75. package/dist/cli/init/skill.d.ts +7 -0
  76. package/dist/cli/init/skill.js +36 -0
  77. package/dist/cli/init/skill.js.map +1 -0
  78. package/dist/cli/init/snippet.d.ts +1 -0
  79. package/dist/cli/init/snippet.js +18 -0
  80. package/dist/cli/init/snippet.js.map +1 -0
  81. package/dist/cli/init/templates/eslint-config.d.ts +2 -0
  82. package/dist/cli/init/templates/eslint-config.js +35 -0
  83. package/dist/cli/init/templates/eslint-config.js.map +1 -0
  84. package/dist/cli/init/templates/jscpd-config.d.ts +2 -0
  85. package/dist/cli/init/templates/jscpd-config.js +9 -0
  86. package/dist/cli/init/templates/jscpd-config.js.map +1 -0
  87. package/dist/cli/init/templates/knip-config.d.ts +2 -0
  88. package/dist/cli/init/templates/knip-config.js +8 -0
  89. package/dist/cli/init/templates/knip-config.js.map +1 -0
  90. package/dist/cli/init-command.d.ts +2 -0
  91. package/dist/cli/init-command.js +33 -0
  92. package/dist/cli/init-command.js.map +1 -0
  93. package/dist/cli.d.ts +2 -0
  94. package/dist/cli.js +101 -0
  95. package/dist/cli.js.map +1 -0
  96. package/dist/config/defaults.d.ts +4 -0
  97. package/dist/config/defaults.js +172 -0
  98. package/dist/config/defaults.js.map +1 -0
  99. package/dist/config/jiti-loader.d.ts +1 -0
  100. package/dist/config/jiti-loader.js +13 -0
  101. package/dist/config/jiti-loader.js.map +1 -0
  102. package/dist/config/load.d.ts +8 -0
  103. package/dist/config/load.js +53 -0
  104. package/dist/config/load.js.map +1 -0
  105. package/dist/config/merge.d.ts +3 -0
  106. package/dist/config/merge.js +90 -0
  107. package/dist/config/merge.js.map +1 -0
  108. package/dist/config/schema.d.ts +32 -0
  109. package/dist/config/schema.js +4 -0
  110. package/dist/config/schema.js.map +1 -0
  111. package/dist/config/validate.d.ts +2 -0
  112. package/dist/config/validate.js +128 -0
  113. package/dist/config/validate.js.map +1 -0
  114. package/dist/detect/package-json.d.ts +1 -0
  115. package/dist/detect/package-json.js +15 -0
  116. package/dist/detect/package-json.js.map +1 -0
  117. package/dist/detect/tool.d.ts +10 -0
  118. package/dist/detect/tool.js +73 -0
  119. package/dist/detect/tool.js.map +1 -0
  120. package/dist/eslint-runner.d.ts +7 -0
  121. package/dist/eslint-runner.js +34 -0
  122. package/dist/eslint-runner.js.map +1 -0
  123. package/dist/git/exec.d.ts +8 -0
  124. package/dist/git/exec.js +48 -0
  125. package/dist/git/exec.js.map +1 -0
  126. package/dist/git/resolve-scope.d.ts +15 -0
  127. package/dist/git/resolve-scope.js +89 -0
  128. package/dist/git/resolve-scope.js.map +1 -0
  129. package/dist/git/scope.d.ts +7 -0
  130. package/dist/git/scope.js +58 -0
  131. package/dist/git/scope.js.map +1 -0
  132. package/dist/index.d.ts +1 -0
  133. package/dist/index.js +2 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/prompts/loader.d.ts +6 -0
  136. package/dist/prompts/loader.js +27 -0
  137. package/dist/prompts/loader.js.map +1 -0
  138. package/dist/prompts/packaged-dir.d.ts +1 -0
  139. package/dist/prompts/packaged-dir.js +10 -0
  140. package/dist/prompts/packaged-dir.js.map +1 -0
  141. package/dist/prompts/registry.d.ts +3 -0
  142. package/dist/prompts/registry.js +68 -0
  143. package/dist/prompts/registry.js.map +1 -0
  144. package/dist/reporter.d.ts +7 -0
  145. package/dist/reporter.js +114 -0
  146. package/dist/reporter.js.map +1 -0
  147. package/dist/rules/registry.d.ts +3 -0
  148. package/dist/rules/registry.js +37 -0
  149. package/dist/rules/registry.js.map +1 -0
  150. package/dist/runner.d.ts +15 -0
  151. package/dist/runner.js +151 -0
  152. package/dist/runner.js.map +1 -0
  153. package/dist/types.d.ts +41 -0
  154. package/dist/types.js +2 -0
  155. package/dist/types.js.map +1 -0
  156. package/dist/wrap/notices.d.ts +13 -0
  157. package/dist/wrap/notices.js +29 -0
  158. package/dist/wrap/notices.js.map +1 -0
  159. package/dist/wrap/resolve.d.ts +5 -0
  160. package/dist/wrap/resolve.js +9 -0
  161. package/dist/wrap/resolve.js.map +1 -0
  162. package/dist/wrap/run.d.ts +15 -0
  163. package/dist/wrap/run.js +26 -0
  164. package/dist/wrap/run.js.map +1 -0
  165. package/dist/wrap/shell.d.ts +14 -0
  166. package/dist/wrap/shell.js +44 -0
  167. package/dist/wrap/shell.js.map +1 -0
  168. package/package.json +46 -0
  169. package/src/prompts/comment-non-essential.md +7 -0
  170. package/src/prompts/eslint-boundaries-dependencies.md +9 -0
  171. package/src/prompts/eslint-complexity.md +9 -0
  172. package/src/prompts/eslint-eqeqeq.md +3 -0
  173. package/src/prompts/eslint-fatal.md +7 -0
  174. package/src/prompts/eslint-max-lines-per-function.md +9 -0
  175. package/src/prompts/eslint-max-lines.md +9 -0
  176. package/src/prompts/eslint-max-params.md +9 -0
  177. package/src/prompts/eslint-no-duplicate-imports.md +1 -0
  178. package/src/prompts/eslint-no-unused-vars.md +3 -0
  179. package/src/prompts/eslint-no-var.md +1 -0
  180. package/src/prompts/eslint-no-warning-comments.md +3 -0
  181. package/src/prompts/eslint-prefer-const.md +3 -0
  182. package/src/prompts/eslint-typescript-eslint-no-explicit-any.md +3 -0
  183. package/src/prompts/eslint-typescript-eslint-no-inferrable-types.md +3 -0
  184. package/src/prompts/eslint-typescript-eslint-no-non-null-assertion.md +3 -0
  185. package/src/prompts/jscpd-duplication.md +9 -0
  186. package/src/prompts/knip-classMembers.md +7 -0
  187. package/src/prompts/knip-dependencies.md +9 -0
  188. package/src/prompts/knip-exports.md +9 -0
  189. package/src/prompts/knip-files.md +9 -0
  190. package/src/prompts/knip-types.md +9 -0
  191. package/src/prompts/uncoached.md +3 -0
  192. package/src/skills/habit-hooks-review/SKILL.md +108 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knip-wrap.js","sourceRoot":"","sources":["../../src/checks/knip-wrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerBaselineCommands(program: Command): void;
@@ -0,0 +1,61 @@
1
+ import { baselineForget, baselineGenerate, baselinePrune, baselineSnooze, baselineStatus, } from '../baseline/commands.js';
2
+ import { emit } from './emit.js';
3
+ async function runAction(action) {
4
+ try {
5
+ emit(await action());
6
+ }
7
+ catch (error) {
8
+ const message = error instanceof Error ? error.message : String(error);
9
+ process.stderr.write(`habit-hooks: ${message}\n`);
10
+ process.exitCode = 2;
11
+ }
12
+ }
13
+ function attachGenerate(baseline) {
14
+ baseline
15
+ .command('generate')
16
+ .description('record currently-violating files as snoozed')
17
+ .action(async () => {
18
+ await runAction(() => baselineGenerate(process.cwd()));
19
+ });
20
+ }
21
+ function attachStatus(baseline) {
22
+ baseline
23
+ .command('status')
24
+ .description('list snoozed files and their freshness')
25
+ .action(async () => {
26
+ await runAction(() => baselineStatus(process.cwd()));
27
+ });
28
+ }
29
+ function attachSnooze(baseline) {
30
+ baseline
31
+ .command('snooze <files...>')
32
+ .description('snooze the given tracked files')
33
+ .action(async (files) => {
34
+ await runAction(() => baselineSnooze(process.cwd(), files));
35
+ });
36
+ }
37
+ function attachForget(baseline) {
38
+ baseline
39
+ .command('forget <files...>')
40
+ .description('remove baseline entries for the given files')
41
+ .action(async (files) => {
42
+ await runAction(() => baselineForget(process.cwd(), files));
43
+ });
44
+ }
45
+ function attachPrune(baseline) {
46
+ baseline
47
+ .command('prune')
48
+ .description('remove stale entries (missing files or resolved violations)')
49
+ .action(async () => {
50
+ await runAction(() => baselinePrune(process.cwd()));
51
+ });
52
+ }
53
+ export function registerBaselineCommands(program) {
54
+ const baseline = program.command('baseline').description('manage the snooze baseline');
55
+ attachGenerate(baseline);
56
+ attachStatus(baseline);
57
+ attachSnooze(baseline);
58
+ attachForget(baseline);
59
+ attachPrune(baseline);
60
+ }
61
+ //# sourceMappingURL=baseline-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline-commands.js","sourceRoot":"","sources":["../../src/cli/baseline-commands.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,GAEf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,KAAK,UAAU,SAAS,CAAC,MAAoD;IAC3E,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,OAAO,IAAI,CAAC,CAAC;QAClD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,QAAiB;IACvC,QAAQ;SACL,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,YAAY,CAAC,QAAiB;IACrC,QAAQ;SACL,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,wCAAwC,CAAC;SACrD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,YAAY,CAAC,QAAiB;IACrC,QAAQ;SACL,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,gCAAgC,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;QAChC,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,YAAY,CAAC,QAAiB;IACrC,QAAQ;SACL,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;QAChC,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,WAAW,CAAC,QAAiB;IACpC,QAAQ;SACL,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;IACvF,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,WAAW,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,7 @@
1
+ interface CommandOutput {
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ }
6
+ export declare function emit(result: CommandOutput): void;
7
+ export {};
@@ -0,0 +1,8 @@
1
+ export function emit(result) {
2
+ if (result.stdout.length > 0)
3
+ process.stdout.write(result.stdout);
4
+ if (result.stderr.length > 0)
5
+ process.stderr.write(result.stderr);
6
+ process.exitCode = result.exitCode;
7
+ }
8
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../../src/cli/emit.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,IAAI,CAAC,MAAqB;IACxC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AACrC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type ToolName } from '../../detect/tool.js';
2
+ export type { ToolName };
3
+ export interface ToolState {
4
+ installed: boolean;
5
+ configured: boolean;
6
+ }
7
+ type ToolStateMatrix = Record<ToolName, ToolState>;
8
+ export declare function detectToolStates(cwd: string): ToolStateMatrix;
@@ -0,0 +1,20 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { detectTool, TOOL_CONFIG_FILENAMES, TOOL_PACKAGE_JSON_KEYS, } from '../../detect/tool.js';
4
+ import { hasPackageJsonKey } from '../../detect/package-json.js';
5
+ const TOOLS = ['eslint', 'knip', 'jscpd'];
6
+ function hasConfigFile(cwd, tool) {
7
+ if (TOOL_CONFIG_FILENAMES[tool].some((name) => existsSync(join(cwd, name))))
8
+ return true;
9
+ return hasPackageJsonKey(cwd, TOOL_PACKAGE_JSON_KEYS[tool]);
10
+ }
11
+ function stateFor(cwd, tool) {
12
+ return { installed: detectTool(cwd, tool) !== null, configured: hasConfigFile(cwd, tool) };
13
+ }
14
+ export function detectToolStates(cwd) {
15
+ const matrix = {};
16
+ for (const tool of TOOLS)
17
+ matrix[tool] = stateFor(cwd, tool);
18
+ return matrix;
19
+ }
20
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../../src/cli/init/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAWjE,MAAM,KAAK,GAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,SAAS,aAAa,CAAC,GAAW,EAAE,IAAc;IAChD,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACzF,OAAO,iBAAiB,CAAC,GAAG,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,IAAc;IAC3C,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,UAAU,EAAE,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7D,OAAO,MAAyB,CAAC;AACnC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type HookAction = 'installed' | 'conflict' | 'no-git' | 'kept';
2
+ export interface HookResult {
3
+ action: HookAction;
4
+ path?: string;
5
+ }
6
+ export declare function installPreCommitHook(cwd: string): HookResult;
@@ -0,0 +1,48 @@
1
+ import { chmodSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { detectPackageManager, runScriptCommand } from './install-commands.js';
4
+ function hookBodyFor(cwd) {
5
+ const command = runScriptCommand(detectPackageManager(cwd), 'habit-hooks');
6
+ return `#!/usr/bin/env sh\n${command}\n`;
7
+ }
8
+ function dependsOnHusky(cwd) {
9
+ const pkgPath = join(cwd, 'package.json');
10
+ if (!existsSync(pkgPath))
11
+ return false;
12
+ if (!existsSync(join(cwd, '.husky')))
13
+ return false;
14
+ const raw = readFileSync(pkgPath, 'utf8');
15
+ return raw.includes('"husky"');
16
+ }
17
+ function huskyHookPath(cwd) {
18
+ return join(cwd, '.husky', 'pre-commit');
19
+ }
20
+ function nativeHookPath(cwd) {
21
+ return join(cwd, '.git', 'hooks', 'pre-commit');
22
+ }
23
+ function writeHook(path, body) {
24
+ writeFileSync(path, body);
25
+ chmodSync(path, 0o755);
26
+ return { action: 'installed', path };
27
+ }
28
+ function bodyMatches(content) {
29
+ return content.includes(' run habit-hooks');
30
+ }
31
+ function installAt(path, body) {
32
+ if (existsSync(path)) {
33
+ const existing = readFileSync(path, 'utf8');
34
+ if (bodyMatches(existing))
35
+ return { action: 'kept', path };
36
+ return { action: 'conflict', path };
37
+ }
38
+ return writeHook(path, body);
39
+ }
40
+ export function installPreCommitHook(cwd) {
41
+ const body = hookBodyFor(cwd);
42
+ if (dependsOnHusky(cwd))
43
+ return installAt(huskyHookPath(cwd), body);
44
+ if (!existsSync(join(cwd, '.git')))
45
+ return { action: 'no-git' };
46
+ return installAt(nativeHookPath(cwd), body);
47
+ }
48
+ //# sourceMappingURL=git-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-hook.js","sourceRoot":"","sources":["../../../src/cli/init/git-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAS/E,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,OAAO,GAAG,gBAAgB,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC;IAC3E,OAAO,sBAAsB,OAAO,IAAI,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,OAAO,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IAC3C,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1B,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IAC3C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,WAAW,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC3D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,cAAc,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IACpE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAChE,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,6 @@
1
+ type PackageManager = 'pnpm' | 'yarn' | 'bun' | 'npm';
2
+ export declare function detectPackageManager(cwd: string): PackageManager;
3
+ export declare function buildInstallCommand(pm: PackageManager, packages: string[]): string;
4
+ export declare function runScriptCommand(pm: PackageManager, script: string): string;
5
+ export declare function packagesFor(tool: 'eslint' | 'knip' | 'jscpd'): string[];
6
+ export {};
@@ -0,0 +1,55 @@
1
+ import { existsSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const LOCKFILES = {
4
+ pnpm: ['pnpm-lock.yaml'],
5
+ yarn: ['yarn.lock'],
6
+ bun: ['bun.lock', 'bun.lockb'],
7
+ };
8
+ function lockfileHitsFor(cwd, pm) {
9
+ const hits = [];
10
+ for (const file of LOCKFILES[pm]) {
11
+ const path = join(cwd, file);
12
+ if (existsSync(path))
13
+ hits.push({ pm, path, mtimeMs: statSync(path).mtimeMs });
14
+ }
15
+ return hits;
16
+ }
17
+ function findAllLockfileHits(cwd) {
18
+ const all = [];
19
+ for (const pm of Object.keys(LOCKFILES)) {
20
+ all.push(...lockfileHitsFor(cwd, pm));
21
+ }
22
+ return all;
23
+ }
24
+ function pickNewest(hits) {
25
+ const sorted = [...hits].sort((a, b) => b.mtimeMs - a.mtimeMs);
26
+ const newest = sorted[0];
27
+ if (newest === undefined)
28
+ throw new Error('pickNewest requires at least one hit');
29
+ return newest;
30
+ }
31
+ export function detectPackageManager(cwd) {
32
+ const hits = findAllLockfileHits(cwd);
33
+ if (hits.length === 0)
34
+ return 'npm';
35
+ return pickNewest(hits).pm;
36
+ }
37
+ const ADD_FLAGS = {
38
+ pnpm: ['add', '-D'],
39
+ yarn: ['add', '-D'],
40
+ bun: ['add', '-d'],
41
+ npm: ['install', '--save-dev'],
42
+ };
43
+ export function buildInstallCommand(pm, packages) {
44
+ return [pm, ...ADD_FLAGS[pm], ...packages].join(' ');
45
+ }
46
+ export function runScriptCommand(pm, script) {
47
+ return `${pm} run ${script}`;
48
+ }
49
+ const ESLINT_PACKAGES = ['eslint', '@eslint/js', 'typescript-eslint'];
50
+ export function packagesFor(tool) {
51
+ if (tool === 'eslint')
52
+ return ESLINT_PACKAGES;
53
+ return [tool];
54
+ }
55
+ //# sourceMappingURL=install-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-commands.js","sourceRoot":"","sources":["../../../src/cli/init/install-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAMjC,MAAM,SAAS,GAA0C;IACvD,IAAI,EAAE,CAAC,gBAAgB,CAAC;IACxB,IAAI,EAAE,CAAC,WAAW,CAAC;IACnB,GAAG,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC;CAC/B,CAAC;AAQF,SAAS,eAAe,CAAC,GAAW,EAAE,EAAc;IAClD,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACtC,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAiB,EAAE,CAAC;QACxD,GAAG,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,IAAmB;IACrC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAClF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,SAAS,GAAqC;IAClD,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IACnB,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IACnB,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IAClB,GAAG,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC;CAC/B,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,EAAkB,EAAE,QAAkB;IACxE,OAAO,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAkB,EAAE,MAAc;IACjE,OAAO,GAAG,EAAE,QAAQ,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC;AAEtE,MAAM,UAAU,WAAW,CAAC,IAAiC;IAC3D,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,eAAe,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface ScriptResult {
2
+ action: 'added' | 'kept' | 'conflict' | 'no-package-json';
3
+ before?: string;
4
+ }
5
+ export declare function addHabitHooksScript(cwd: string): ScriptResult;
6
+ export declare function addCiScript(cwd: string): ScriptResult;
@@ -0,0 +1,55 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const HABIT_HOOKS_SCRIPT = 'habit-hooks';
4
+ const HABIT_HOOKS_COMMAND = 'habit-hooks';
5
+ const CI_SCRIPT = 'ci';
6
+ const CI_CANDIDATES = ['lint', 'test', 'build', HABIT_HOOKS_SCRIPT];
7
+ function readPackageJson(cwd) {
8
+ const path = join(cwd, 'package.json');
9
+ if (!existsSync(path))
10
+ return null;
11
+ const raw = readFileSync(path, 'utf8');
12
+ return { path, data: JSON.parse(raw) };
13
+ }
14
+ function writePackageJson(path, data) {
15
+ writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`);
16
+ }
17
+ function ensureScripts(data) {
18
+ if (!data.scripts)
19
+ data.scripts = {};
20
+ return data.scripts;
21
+ }
22
+ export function addHabitHooksScript(cwd) {
23
+ const pkg = readPackageJson(cwd);
24
+ if (pkg === null)
25
+ return { action: 'no-package-json' };
26
+ const scripts = ensureScripts(pkg.data);
27
+ const existing = scripts[HABIT_HOOKS_SCRIPT];
28
+ if (existing === HABIT_HOOKS_COMMAND)
29
+ return { action: 'kept', before: existing };
30
+ if (existing !== undefined)
31
+ return { action: 'conflict', before: existing };
32
+ scripts[HABIT_HOOKS_SCRIPT] = HABIT_HOOKS_COMMAND;
33
+ writePackageJson(pkg.path, pkg.data);
34
+ return { action: 'added' };
35
+ }
36
+ function buildCiCommand(scripts) {
37
+ const present = CI_CANDIDATES.filter((name) => scripts[name] !== undefined);
38
+ return present.map((name) => `npm run ${name}`).join(' && ');
39
+ }
40
+ export function addCiScript(cwd) {
41
+ const pkg = readPackageJson(cwd);
42
+ if (pkg === null)
43
+ return { action: 'no-package-json' };
44
+ const scripts = ensureScripts(pkg.data);
45
+ const desired = buildCiCommand(scripts);
46
+ const existing = scripts[CI_SCRIPT];
47
+ if (existing === desired)
48
+ return { action: 'kept', before: existing };
49
+ if (existing !== undefined)
50
+ return { action: 'conflict', before: existing };
51
+ scripts[CI_SCRIPT] = desired;
52
+ writePackageJson(pkg.path, pkg.data);
53
+ return { action: 'added' };
54
+ }
55
+ //# sourceMappingURL=package-scripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-scripts.js","sourceRoot":"","sources":["../../../src/cli/init/package-scripts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface PromptOptions {
2
+ defaultYes: boolean;
3
+ }
4
+ export interface Prompter {
5
+ ask(_question: string, _opts: PromptOptions): Promise<boolean>;
6
+ close(): void;
7
+ }
8
+ export declare function makeInteractivePrompter(): Prompter;
9
+ export declare function makeAutoPrompter(defaultYesForAll: boolean): Prompter;
@@ -0,0 +1,33 @@
1
+ import readline from 'node:readline';
2
+ function suffix(defaultYes) {
3
+ return defaultYes ? '[Y/n]' : '[y/N]';
4
+ }
5
+ function interpret(answer, defaultYes) {
6
+ const trimmed = answer.trim().toLowerCase();
7
+ if (trimmed.length === 0)
8
+ return defaultYes;
9
+ return trimmed === 'y' || trimmed === 'yes';
10
+ }
11
+ function askVia(rl, question, opts) {
12
+ return new Promise((resolve) => {
13
+ rl.question(`${question} ${suffix(opts.defaultYes)} `, (answer) => {
14
+ resolve(interpret(answer, opts.defaultYes));
15
+ });
16
+ });
17
+ }
18
+ export function makeInteractivePrompter() {
19
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
20
+ return {
21
+ ask: (q, opts) => askVia(rl, q, opts),
22
+ close: () => rl.close(),
23
+ };
24
+ }
25
+ export function makeAutoPrompter(defaultYesForAll) {
26
+ return {
27
+ ask(_question, opts) {
28
+ return Promise.resolve(defaultYesForAll ? true : opts.defaultYes);
29
+ },
30
+ close() { },
31
+ };
32
+ }
33
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/cli/init/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,eAAe,CAAC;AAWrC,SAAS,MAAM,CAAC,UAAmB;IACjC,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACxC,CAAC;AAED,SAAS,SAAS,CAAC,MAAc,EAAE,UAAmB;IACpD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC5C,OAAO,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,KAAK,CAAC;AAC9C,CAAC;AAED,SAAS,MAAM,CAAC,EAAsB,EAAE,QAAgB,EAAE,IAAmB;IAC3E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE;YAChE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,OAAO;QACL,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC;QACrC,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,gBAAyB;IACxD,OAAO;QACL,GAAG,CAAC,SAAS,EAAE,IAAI;YACjB,OAAO,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpE,CAAC;QACD,KAAK,KAAI,CAAC;KACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { HookResult } from './git-hook.js';
2
+ import type { ScriptResult } from './package-scripts.js';
3
+ import type { SkillResult } from './skill.js';
4
+ export interface Lines {
5
+ out: string[];
6
+ err: string[];
7
+ exit: number;
8
+ }
9
+ export declare function reportScriptResult(name: string, result: ScriptResult, lines: Lines): void;
10
+ export declare function reportHookResult(result: HookResult, lines: Lines): void;
11
+ export declare function reportSkillResult(result: SkillResult, lines: Lines): void;
@@ -0,0 +1,40 @@
1
+ function emitConflict(lines, message) {
2
+ lines.err.push(`habit-hooks: ${message}\n`);
3
+ lines.exit = 2;
4
+ }
5
+ export function reportScriptResult(name, result, lines) {
6
+ if (result.action === 'added')
7
+ lines.out.push(`added '${name}' to package.json scripts\n`);
8
+ else if (result.action === 'kept')
9
+ lines.out.push(`'${name}' already set as desired in package.json\n`);
10
+ else if (result.action === 'no-package-json')
11
+ lines.out.push(`skipped '${name}': no package.json in cwd\n`);
12
+ else if (result.action === 'conflict') {
13
+ emitConflict(lines, `refusing to replace '${name}' script (currently: ${result.before ?? '<unknown>'})`);
14
+ }
15
+ }
16
+ export function reportHookResult(result, lines) {
17
+ if (result.action === 'installed')
18
+ lines.out.push(`installed pre-commit hook at ${result.path}\n`);
19
+ else if (result.action === 'kept')
20
+ lines.out.push(`pre-commit hook already installed at ${result.path}\n`);
21
+ else if (result.action === 'conflict') {
22
+ lines.out.push(`pre-commit hook already exists at ${result.path} — left untouched\n`);
23
+ }
24
+ else if (result.action === 'no-git') {
25
+ lines.out.push(`skipped pre-commit hook: no .git directory in cwd\n`);
26
+ }
27
+ }
28
+ export function reportSkillResult(result, lines) {
29
+ if (result.action === 'installed')
30
+ lines.out.push(`installed reviewer skill at ${result.target}\n`);
31
+ else if (result.action === 'kept')
32
+ lines.out.push(`reviewer skill already at ${result.target}\n`);
33
+ else if (result.action === 'conflict') {
34
+ lines.out.push(`reviewer skill already exists at ${result.target} — left untouched\n`);
35
+ }
36
+ else if (result.action === 'source-missing') {
37
+ lines.err.push(`habit-hooks: could not find packaged SKILL.md — skipping\n`);
38
+ }
39
+ }
40
+ //# sourceMappingURL=reporters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporters.js","sourceRoot":"","sources":["../../../src/cli/init/reporters.ts"],"names":[],"mappings":"AAUA,SAAS,YAAY,CAAC,KAAY,EAAE,OAAe;IACjD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,OAAO,IAAI,CAAC,CAAC;IAC5C,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,MAAoB,EAAE,KAAY;IACjF,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,6BAA6B,CAAC,CAAC;SACtF,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,4CAA4C,CAAC,CAAC;SACnG,IAAI,MAAM,CAAC,MAAM,KAAK,iBAAiB;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,6BAA6B,CAAC,CAAC;SACvG,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACtC,YAAY,CAAC,KAAK,EAAE,wBAAwB,IAAI,wBAAwB,MAAM,CAAC,MAAM,IAAI,WAAW,GAAG,CAAC,CAAC;IAC3G,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,KAAY;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;SAC9F,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,wCAAwC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;SACtG,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,qCAAqC,MAAM,CAAC,IAAI,qBAAqB,CAAC,CAAC;IACxF,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAmB,EAAE,KAAY;IACjE,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;SAC/F,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,6BAA6B,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;SAC7F,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,oCAAoC,MAAM,CAAC,MAAM,qBAAqB,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;QAC9C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Prompter } from './prompts.js';
2
+ interface InitOptions {
3
+ prompter: Prompter;
4
+ dryRun?: boolean;
5
+ }
6
+ interface InitResult {
7
+ stdout: string;
8
+ stderr: string;
9
+ exitCode: number;
10
+ }
11
+ export declare function runInit(cwd: string, opts: InitOptions): Promise<InitResult>;
12
+ export {};
@@ -0,0 +1,159 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { scaffoldConfig } from './scaffold-config.js';
4
+ import { scaffoldBaseline } from './scaffold-baseline.js';
5
+ import { scaffoldEslintConfig } from './scaffold-eslint-config.js';
6
+ import { scaffoldKnipConfig } from './scaffold-knip-config.js';
7
+ import { scaffoldJscpdConfig } from './scaffold-jscpd-config.js';
8
+ import { detectToolStates } from './detect.js';
9
+ import { buildInstallCommand, detectPackageManager, packagesFor, } from './install-commands.js';
10
+ import { addCiScript, addHabitHooksScript } from './package-scripts.js';
11
+ import { installPreCommitHook } from './git-hook.js';
12
+ import { installReviewerSkill } from './skill.js';
13
+ import { AGENT_SNIPPET } from './snippet.js';
14
+ import { reportHookResult, reportScriptResult, reportSkillResult, } from './reporters.js';
15
+ function noteScaffold(ctx, result, label) {
16
+ if (result.created)
17
+ ctx.lines.out.push(`wrote ${result.path}\n`);
18
+ else
19
+ ctx.lines.out.push(`${label} already present at ${result.path}\n`);
20
+ }
21
+ function dryRunPath(ctx, filename, label) {
22
+ const path = join(ctx.cwd, filename);
23
+ if (existsSync(path))
24
+ ctx.lines.out.push(`${label} already present at ${path}\n`);
25
+ else
26
+ ctx.lines.out.push(`[dry-run] would write ${path}\n`);
27
+ }
28
+ const SCAFFOLDERS = {
29
+ eslint: scaffoldEslintConfig,
30
+ knip: scaffoldKnipConfig,
31
+ jscpd: scaffoldJscpdConfig,
32
+ };
33
+ const DEFAULT_FILENAMES = {
34
+ eslint: 'eslint.config.js',
35
+ knip: 'knip.json',
36
+ jscpd: '.jscpd.json',
37
+ };
38
+ const KNIP_STARTER_NOTE = 'knip.json written with starter entry points. Edit `entry` in knip.json to match your project.\n';
39
+ function noteKnipStarter(ctx, result) {
40
+ if (result.created)
41
+ ctx.lines.out.push(KNIP_STARTER_NOTE);
42
+ }
43
+ function scaffoldFor(ctx, tool) {
44
+ if (ctx.dryRun) {
45
+ dryRunPath(ctx, DEFAULT_FILENAMES[tool], `${tool} config`);
46
+ return;
47
+ }
48
+ const result = SCAFFOLDERS[tool](ctx.cwd);
49
+ noteScaffold(ctx, result, `${tool} config`);
50
+ if (tool === 'knip')
51
+ noteKnipStarter(ctx, result);
52
+ }
53
+ function noteToolPresent(ctx, tool) {
54
+ ctx.lines.out.push(`${tool} already installed and configured\n`);
55
+ }
56
+ function noteConfigured(ctx, tool) {
57
+ ctx.lines.out.push(`${tool} config already present (binary missing)\n`);
58
+ }
59
+ function handleTool(ctx, tool, state) {
60
+ if (state.installed && state.configured) {
61
+ noteToolPresent(ctx, tool);
62
+ return;
63
+ }
64
+ if (state.configured)
65
+ noteConfigured(ctx, tool);
66
+ else
67
+ scaffoldFor(ctx, tool);
68
+ }
69
+ function collectMissingTools(matrix) {
70
+ return Object.keys(matrix).filter((t) => !matrix[t].installed);
71
+ }
72
+ function printInstallCommand(ctx, missing) {
73
+ if (missing.length === 0)
74
+ return;
75
+ const packages = missing.flatMap((t) => packagesFor(t));
76
+ const command = buildInstallCommand(detectPackageManager(ctx.cwd), packages);
77
+ ctx.lines.out.push(`\nTo install missing tools, run:\n ${command}\n`);
78
+ }
79
+ function runToolSteps(ctx) {
80
+ const matrix = detectToolStates(ctx.cwd);
81
+ for (const tool of Object.keys(matrix)) {
82
+ handleTool(ctx, tool, matrix[tool]);
83
+ }
84
+ printInstallCommand(ctx, collectMissingTools(matrix));
85
+ }
86
+ function writeConfigStep(ctx) {
87
+ if (ctx.dryRun) {
88
+ dryRunPath(ctx, 'habit-hooks.config.js', 'habit-hooks config');
89
+ return;
90
+ }
91
+ noteScaffold(ctx, scaffoldConfig(ctx.cwd), 'habit-hooks config');
92
+ }
93
+ function writeBaselineStep(ctx) {
94
+ if (ctx.dryRun) {
95
+ dryRunPath(ctx, '.habit-hooks-baseline.json', 'baseline');
96
+ return;
97
+ }
98
+ const result = scaffoldBaseline(ctx.cwd);
99
+ if (result.created)
100
+ ctx.lines.out.push(`wrote ${result.path}\n`);
101
+ else
102
+ ctx.lines.out.push(`baseline already present at ${result.path}\n`);
103
+ }
104
+ async function maybeAddHabitHooksScript(ctx, prompter) {
105
+ if (ctx.dryRun)
106
+ return;
107
+ const yes = await prompter.ask("Add 'habit-hooks' to package.json scripts?", { defaultYes: true });
108
+ if (!yes)
109
+ return;
110
+ reportScriptResult('habit-hooks', addHabitHooksScript(ctx.cwd), ctx.lines);
111
+ }
112
+ async function maybeAddCiScript(ctx, prompter) {
113
+ if (ctx.dryRun)
114
+ return;
115
+ const yes = await prompter.ask("Wire 'npm run ci' as the full quality gate?", { defaultYes: true });
116
+ if (!yes)
117
+ return;
118
+ reportScriptResult('ci', addCiScript(ctx.cwd), ctx.lines);
119
+ }
120
+ async function maybeInstallHook(ctx, prompter) {
121
+ if (ctx.dryRun)
122
+ return;
123
+ const yes = await prompter.ask('Install a git pre-commit hook?', { defaultYes: false });
124
+ if (!yes)
125
+ return;
126
+ reportHookResult(installPreCommitHook(ctx.cwd), ctx.lines);
127
+ }
128
+ async function maybeInstallSkill(ctx, prompter) {
129
+ if (ctx.dryRun)
130
+ return;
131
+ const yes = await prompter.ask("Install the bundled 'habit-hooks-review' skill into ~/.claude/skills/?", { defaultYes: false });
132
+ if (!yes)
133
+ return;
134
+ reportSkillResult(installReviewerSkill(), ctx.lines);
135
+ }
136
+ function printSnippet(lines) {
137
+ lines.out.push('\n--- paste into CLAUDE.md / AGENTS.md ---\n');
138
+ lines.out.push(AGENT_SNIPPET);
139
+ lines.out.push('--- end snippet ---\n');
140
+ }
141
+ async function runPrompts(ctx, prompter) {
142
+ await maybeAddHabitHooksScript(ctx, prompter);
143
+ await maybeAddCiScript(ctx, prompter);
144
+ await maybeInstallHook(ctx, prompter);
145
+ await maybeInstallSkill(ctx, prompter);
146
+ }
147
+ function toResult(lines) {
148
+ return { stdout: lines.out.join(''), stderr: lines.err.join(''), exitCode: lines.exit };
149
+ }
150
+ export async function runInit(cwd, opts) {
151
+ const ctx = { cwd, lines: { out: [], err: [], exit: 0 }, dryRun: opts.dryRun === true };
152
+ runToolSteps(ctx);
153
+ writeConfigStep(ctx);
154
+ writeBaselineStep(ctx);
155
+ await runPrompts(ctx, opts.prompter);
156
+ printSnippet(ctx.lines);
157
+ return toResult(ctx.lines);
158
+ }
159
+ //# sourceMappingURL=run.js.map