@imix-js/taproot 0.2.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 (124) hide show
  1. package/README.md +88 -0
  2. package/dist/adapters/index.d.ts +20 -0
  3. package/dist/adapters/index.js +452 -0
  4. package/dist/adapters/index.js.map +1 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +40 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/acceptance-check.d.ts +26 -0
  9. package/dist/commands/acceptance-check.js +213 -0
  10. package/dist/commands/acceptance-check.js.map +1 -0
  11. package/dist/commands/check-orphans.d.ts +8 -0
  12. package/dist/commands/check-orphans.js +157 -0
  13. package/dist/commands/check-orphans.js.map +1 -0
  14. package/dist/commands/commithook.d.ts +15 -0
  15. package/dist/commands/commithook.js +389 -0
  16. package/dist/commands/commithook.js.map +1 -0
  17. package/dist/commands/coverage.d.ts +41 -0
  18. package/dist/commands/coverage.js +390 -0
  19. package/dist/commands/coverage.js.map +1 -0
  20. package/dist/commands/dod.d.ts +13 -0
  21. package/dist/commands/dod.js +141 -0
  22. package/dist/commands/dod.js.map +1 -0
  23. package/dist/commands/init.d.ts +14 -0
  24. package/dist/commands/init.js +378 -0
  25. package/dist/commands/init.js.map +1 -0
  26. package/dist/commands/link-commits.d.ts +12 -0
  27. package/dist/commands/link-commits.js +126 -0
  28. package/dist/commands/link-commits.js.map +1 -0
  29. package/dist/commands/overview.d.ts +6 -0
  30. package/dist/commands/overview.js +192 -0
  31. package/dist/commands/overview.js.map +1 -0
  32. package/dist/commands/plan.d.ts +23 -0
  33. package/dist/commands/plan.js +167 -0
  34. package/dist/commands/plan.js.map +1 -0
  35. package/dist/commands/sync-check.d.ts +8 -0
  36. package/dist/commands/sync-check.js +118 -0
  37. package/dist/commands/sync-check.js.map +1 -0
  38. package/dist/commands/update.d.ts +7 -0
  39. package/dist/commands/update.js +309 -0
  40. package/dist/commands/update.js.map +1 -0
  41. package/dist/commands/validate-format.d.ts +8 -0
  42. package/dist/commands/validate-format.js +93 -0
  43. package/dist/commands/validate-format.js.map +1 -0
  44. package/dist/commands/validate-structure.d.ts +8 -0
  45. package/dist/commands/validate-structure.js +29 -0
  46. package/dist/commands/validate-structure.js.map +1 -0
  47. package/dist/core/config.d.ts +6 -0
  48. package/dist/core/config.js +86 -0
  49. package/dist/core/config.js.map +1 -0
  50. package/dist/core/configuration.d.ts +7 -0
  51. package/dist/core/configuration.js +112 -0
  52. package/dist/core/configuration.js.map +1 -0
  53. package/dist/core/dod-runner.d.ts +20 -0
  54. package/dist/core/dod-runner.js +233 -0
  55. package/dist/core/dod-runner.js.map +1 -0
  56. package/dist/core/dor-runner.d.ts +18 -0
  57. package/dist/core/dor-runner.js +156 -0
  58. package/dist/core/dor-runner.js.map +1 -0
  59. package/dist/core/fs-walker.d.ts +5 -0
  60. package/dist/core/fs-walker.js +74 -0
  61. package/dist/core/fs-walker.js.map +1 -0
  62. package/dist/core/git.d.ts +24 -0
  63. package/dist/core/git.js +76 -0
  64. package/dist/core/git.js.map +1 -0
  65. package/dist/core/impl-reader.d.ts +8 -0
  66. package/dist/core/impl-reader.js +39 -0
  67. package/dist/core/impl-reader.js.map +1 -0
  68. package/dist/core/language.d.ts +39 -0
  69. package/dist/core/language.js +159 -0
  70. package/dist/core/language.js.map +1 -0
  71. package/dist/core/markdown-parser.d.ts +3 -0
  72. package/dist/core/markdown-parser.js +37 -0
  73. package/dist/core/markdown-parser.js.map +1 -0
  74. package/dist/core/reporter.d.ts +3 -0
  75. package/dist/core/reporter.js +33 -0
  76. package/dist/core/reporter.js.map +1 -0
  77. package/dist/templates/index.d.ts +4 -0
  78. package/dist/templates/index.js +126 -0
  79. package/dist/templates/index.js.map +1 -0
  80. package/dist/validators/format-rules.d.ts +10 -0
  81. package/dist/validators/format-rules.js +238 -0
  82. package/dist/validators/format-rules.js.map +1 -0
  83. package/dist/validators/structure-rules.d.ts +10 -0
  84. package/dist/validators/structure-rules.js +94 -0
  85. package/dist/validators/structure-rules.js.map +1 -0
  86. package/dist/validators/types.d.ts +68 -0
  87. package/dist/validators/types.js +2 -0
  88. package/dist/validators/types.js.map +1 -0
  89. package/docs/agents.md +88 -0
  90. package/docs/architecture.md +53 -0
  91. package/docs/cli.md +226 -0
  92. package/docs/concepts.md +268 -0
  93. package/docs/configuration.md +255 -0
  94. package/docs/demo.svg +111 -0
  95. package/docs/patterns.md +118 -0
  96. package/docs/security.md +95 -0
  97. package/docs/workflows.md +151 -0
  98. package/languages/de.json +20 -0
  99. package/languages/en.json +20 -0
  100. package/languages/es.json +20 -0
  101. package/languages/fr.json +20 -0
  102. package/languages/ja.json +20 -0
  103. package/languages/pt.json +20 -0
  104. package/package.json +54 -0
  105. package/skills/analyse-change.md +101 -0
  106. package/skills/behaviour.md +179 -0
  107. package/skills/bug.md +70 -0
  108. package/skills/commit.md +99 -0
  109. package/skills/decompose.md +101 -0
  110. package/skills/discover.md +392 -0
  111. package/skills/grill-me.md +65 -0
  112. package/skills/guide.md +118 -0
  113. package/skills/implement.md +149 -0
  114. package/skills/ineed.md +147 -0
  115. package/skills/intent.md +104 -0
  116. package/skills/plan.md +63 -0
  117. package/skills/promote.md +69 -0
  118. package/skills/refine.md +78 -0
  119. package/skills/research.md +122 -0
  120. package/skills/review-all.md +92 -0
  121. package/skills/review.md +80 -0
  122. package/skills/status.md +103 -0
  123. package/skills/sweep.md +89 -0
  124. package/skills/trace.md +151 -0
@@ -0,0 +1,213 @@
1
+ import { readFileSync, readdirSync, statSync, existsSync } from 'fs';
2
+ import { join, resolve } from 'path';
3
+ import { loadConfig } from '../core/config.js';
4
+ import { walkHierarchy, flattenTree } from '../core/fs-walker.js';
5
+ import { parseMarkdown } from '../core/markdown-parser.js';
6
+ const DEFAULT_TEST_DIRS = ['test', 'tests', 'spec'];
7
+ const AC_ID_IN_SPEC = /^\*\*AC-(\d+):/gm;
8
+ const DEPRECATED_AC_LINE = /^~~\*\*AC-\d+.*$/gm;
9
+ const AC_ID_IN_TEST = /AC-(\d+)/g;
10
+ export function registerAcceptanceCheck(program) {
11
+ program
12
+ .command('acceptance-check')
13
+ .description('Verify acceptance criteria coverage: every AC-N in specs must appear in a test file')
14
+ .option('--path <path>', 'Root path to collect criteria from (overrides config)')
15
+ .option('--tests <dir>', 'Test directory to scan (repeatable; defaults to test/, tests/, spec/)', collect, [])
16
+ .option('--format <fmt>', 'Output format: text or json (default: text)')
17
+ .action(async (options) => {
18
+ const cwd = process.cwd();
19
+ const { config, configDir } = loadConfig(cwd);
20
+ const rootPath = options.path
21
+ ? resolve(options.path)
22
+ : config.root.startsWith('/') ? config.root : resolve(configDir, config.root);
23
+ const testDirs = options.tests.length > 0
24
+ ? options.tests.map(d => resolve(d))
25
+ : DEFAULT_TEST_DIRS.map(d => resolve(cwd, d)).filter(existsSync);
26
+ if (testDirs.length === 0) {
27
+ process.stderr.write('No test directory found — checked test/, tests/, spec/. Use --tests <dir> to specify.\n');
28
+ process.exitCode = 1;
29
+ return;
30
+ }
31
+ const report = runAcceptanceCheck(rootPath, testDirs);
32
+ if (options.format === 'json') {
33
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
34
+ }
35
+ else {
36
+ printReport(report);
37
+ }
38
+ if (report.uncovered.length > 0 || report.orphaned.length > 0) {
39
+ process.exitCode = 1;
40
+ }
41
+ });
42
+ }
43
+ function collect(val, acc) {
44
+ acc.push(val);
45
+ return acc;
46
+ }
47
+ export function runAcceptanceCheck(rootPath, testDirs) {
48
+ const specCriteria = collectCriteria(rootPath);
49
+ const testRefs = scanTestFiles(testDirs);
50
+ const missingSections = collectMissingSections(rootPath);
51
+ const specIds = new Set(specCriteria.map(c => c.id));
52
+ const testIds = new Set(testRefs.map(t => t.id));
53
+ const covered = [...specIds].filter(id => testIds.has(id));
54
+ const uncovered = specCriteria.filter(c => !testIds.has(c.id));
55
+ const orphaned = testRefs.filter(t => !specIds.has(t.id));
56
+ return { specCriteria, covered, uncovered, orphaned, missingSections };
57
+ }
58
+ /** Walk the hierarchy and extract AC-N IDs from ## Acceptance Criteria sections. */
59
+ export function collectCriteria(rootPath) {
60
+ if (!existsSync(rootPath))
61
+ return [];
62
+ const tree = walkHierarchy(rootPath);
63
+ const nodes = flattenTree(tree).filter(n => n.marker === 'behaviour');
64
+ const refs = [];
65
+ for (const node of nodes) {
66
+ const filePath = join(node.absolutePath, 'usecase.md');
67
+ let content;
68
+ try {
69
+ content = readFileSync(filePath, 'utf-8');
70
+ }
71
+ catch {
72
+ continue;
73
+ }
74
+ const doc = parseMarkdown(filePath, content);
75
+ const acSection = doc.sections.get('acceptance criteria');
76
+ if (!acSection)
77
+ continue;
78
+ // Strip deprecated criteria lines (~~**AC-N: ...) before matching
79
+ const body = acSection.rawBody.replace(DEPRECATED_AC_LINE, '');
80
+ AC_ID_IN_SPEC.lastIndex = 0;
81
+ let m;
82
+ while ((m = AC_ID_IN_SPEC.exec(body)) !== null) {
83
+ refs.push({ id: `AC-${m[1]}`, usecasePath: filePath });
84
+ }
85
+ }
86
+ return refs;
87
+ }
88
+ /** Collect usecase.md files that have impl children but no ## Acceptance Criteria section. */
89
+ export function collectMissingSections(rootPath) {
90
+ if (!existsSync(rootPath))
91
+ return [];
92
+ const tree = walkHierarchy(rootPath);
93
+ const nodes = flattenTree(tree).filter(n => n.marker === 'behaviour');
94
+ const missing = [];
95
+ for (const node of nodes) {
96
+ const hasImpl = node.children.some(c => c.marker === 'impl');
97
+ if (!hasImpl)
98
+ continue;
99
+ const filePath = join(node.absolutePath, 'usecase.md');
100
+ let content;
101
+ try {
102
+ content = readFileSync(filePath, 'utf-8');
103
+ }
104
+ catch {
105
+ continue;
106
+ }
107
+ const doc = parseMarkdown(filePath, content);
108
+ if (!doc.sections.has('acceptance criteria')) {
109
+ missing.push(filePath);
110
+ }
111
+ }
112
+ return missing;
113
+ }
114
+ /** Walk test directories and collect all AC-N references with file+line. */
115
+ export function scanTestFiles(testDirs) {
116
+ const refs = [];
117
+ for (const dir of testDirs) {
118
+ if (existsSync(dir))
119
+ walkTestDir(dir, refs);
120
+ }
121
+ return refs;
122
+ }
123
+ function walkTestDir(dir, refs) {
124
+ let entries;
125
+ try {
126
+ entries = readdirSync(dir);
127
+ }
128
+ catch {
129
+ return;
130
+ }
131
+ for (const entry of entries) {
132
+ const full = join(dir, entry);
133
+ try {
134
+ if (statSync(full).isDirectory()) {
135
+ walkTestDir(full, refs);
136
+ }
137
+ else if (isTestFile(entry)) {
138
+ scanFile(full, refs);
139
+ }
140
+ }
141
+ catch {
142
+ // skip unreadable entries
143
+ }
144
+ }
145
+ }
146
+ function isTestFile(name) {
147
+ return /\.(test|spec)\.[jt]sx?$/.test(name) || /\.(test|spec)\.py$/.test(name);
148
+ }
149
+ function scanFile(filePath, refs) {
150
+ let content;
151
+ try {
152
+ content = readFileSync(filePath, 'utf-8');
153
+ }
154
+ catch {
155
+ return;
156
+ }
157
+ const lines = content.split('\n');
158
+ for (let i = 0; i < lines.length; i++) {
159
+ const line = lines[i] ?? '';
160
+ AC_ID_IN_TEST.lastIndex = 0;
161
+ let m;
162
+ while ((m = AC_ID_IN_TEST.exec(line)) !== null) {
163
+ if (m[1])
164
+ refs.push({ id: `AC-${m[1]}`, file: filePath, line: i + 1 });
165
+ }
166
+ }
167
+ }
168
+ function printReport(report) {
169
+ const behaviourCount = new Set(report.specCriteria.map(c => c.usecasePath)).size;
170
+ const totalSpec = report.specCriteria.length;
171
+ if (report.uncovered.length === 0 && report.orphaned.length === 0 && report.missingSections.length === 0) {
172
+ process.stdout.write(`✓ ${totalSpec} criteria covered across ${behaviourCount} behaviours\n`);
173
+ return;
174
+ }
175
+ if (report.covered.length > 0) {
176
+ process.stdout.write(`✓ ${report.covered.length} criteria covered\n\n`);
177
+ }
178
+ if (report.uncovered.length > 0) {
179
+ process.stdout.write(`✗ Uncovered criteria (defined in spec, missing from tests):\n`);
180
+ for (const c of report.uncovered) {
181
+ process.stdout.write(` ${c.id} ${c.usecasePath}\n`);
182
+ }
183
+ process.stdout.write('\n');
184
+ }
185
+ if (report.orphaned.length > 0) {
186
+ const seen = new Set();
187
+ process.stdout.write(`✗ Orphaned references (in tests, not defined in any spec):\n`);
188
+ for (const t of report.orphaned) {
189
+ const key = `${t.id}:${t.file}:${t.line}`;
190
+ if (seen.has(key))
191
+ continue;
192
+ seen.add(key);
193
+ process.stdout.write(` ${t.id} ${t.file}:${t.line}\n`);
194
+ }
195
+ process.stdout.write('\n');
196
+ }
197
+ if (report.missingSections.length > 0) {
198
+ process.stdout.write(`⚠ Missing ## Acceptance Criteria sections:\n`);
199
+ for (const p of report.missingSections) {
200
+ process.stdout.write(` ${p}\n`);
201
+ }
202
+ process.stdout.write('\n');
203
+ }
204
+ const parts = [];
205
+ if (report.uncovered.length > 0)
206
+ parts.push(`${report.uncovered.length} uncovered`);
207
+ if (report.orphaned.length > 0)
208
+ parts.push(`${report.orphaned.length} orphaned`);
209
+ if (report.missingSections.length > 0)
210
+ parts.push(`${report.missingSections.length} missing section`);
211
+ process.stdout.write(parts.join(', ') + '\n');
212
+ }
213
+ //# sourceMappingURL=acceptance-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptance-check.js","sourceRoot":"","sources":["../../src/commands/acceptance-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Command } from 'commander';
2
+ import type { Violation } from '../validators/types.js';
3
+ export declare function registerCheckOrphans(program: Command): void;
4
+ export declare function runCheckOrphans(options: {
5
+ path?: string;
6
+ includeUnimplemented?: boolean;
7
+ cwd?: string;
8
+ }): Promise<Violation[]>;
@@ -0,0 +1,157 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { join, resolve, dirname } from 'path';
3
+ import { loadConfig } from '../core/config.js';
4
+ import { walkHierarchy, flattenTree } from '../core/fs-walker.js';
5
+ import { parseMarkdown } from '../core/markdown-parser.js';
6
+ import { parseImplData } from '../core/impl-reader.js';
7
+ import { commitExists, isGitRepo, getRepoRoot } from '../core/git.js';
8
+ import { renderViolations, exitCode } from '../core/reporter.js';
9
+ export function registerCheckOrphans(program) {
10
+ program
11
+ .command('check-orphans')
12
+ .description('Find disconnected nodes and broken references in the hierarchy')
13
+ .option('--path <path>', 'Root path (overrides config)')
14
+ .option('--include-unimplemented', 'Also report behaviours with no implementations')
15
+ .action(async (options) => {
16
+ const violations = await runCheckOrphans({
17
+ path: options.path,
18
+ includeUnimplemented: options.includeUnimplemented ?? false,
19
+ });
20
+ process.stdout.write(renderViolations(violations));
21
+ process.exit(exitCode(violations));
22
+ });
23
+ }
24
+ export async function runCheckOrphans(options) {
25
+ const { config, configDir } = loadConfig(options.cwd);
26
+ const rootPath = options.path ? resolve(options.path) : config.root;
27
+ const cwd = options.cwd ?? process.cwd();
28
+ const repoRoot = isGitRepo(cwd) ? (getRepoRoot(cwd) ?? cwd) : null;
29
+ const tree = walkHierarchy(rootPath);
30
+ const nodes = flattenTree(tree);
31
+ const violations = [];
32
+ for (const node of nodes) {
33
+ if (node.marker === 'impl') {
34
+ violations.push(...checkImplReferences(node, repoRoot));
35
+ }
36
+ if (node.marker === 'behaviour' && options.includeUnimplemented) {
37
+ violations.push(...checkUnimplementedBehaviour(node));
38
+ }
39
+ }
40
+ return violations;
41
+ }
42
+ function checkImplReferences(node, repoRoot) {
43
+ const filePath = join(node.absolutePath, 'impl.md');
44
+ let content;
45
+ try {
46
+ content = readFileSync(filePath, 'utf-8');
47
+ }
48
+ catch {
49
+ return [{
50
+ type: 'error',
51
+ filePath,
52
+ code: 'UNREADABLE_IMPL',
53
+ message: `Could not read impl.md`,
54
+ }];
55
+ }
56
+ const doc = parseMarkdown(filePath, content);
57
+ const data = parseImplData(doc);
58
+ const violations = [];
59
+ // Skip all reference checks for deferred impls
60
+ const statusSection = doc.sections.get('status');
61
+ const stateMatch = statusSection ? /\*\*State:\*\*\s*(\S+)/.exec(statusSection.rawBody) : null;
62
+ if (stateMatch?.[1]?.trim() === 'deferred')
63
+ return [];
64
+ // Check behaviour reference
65
+ if (data.behaviourRef) {
66
+ const resolvedRef = resolve(dirname(filePath), data.behaviourRef);
67
+ if (!existsSync(resolvedRef)) {
68
+ const behaviourSection = doc.sections.get('behaviour');
69
+ violations.push({
70
+ type: 'error',
71
+ filePath,
72
+ line: behaviourSection?.startLine,
73
+ code: 'BROKEN_BEHAVIOUR_REF',
74
+ message: `Behaviour reference "${data.behaviourRef}" does not exist`,
75
+ });
76
+ }
77
+ }
78
+ // Check source files exist
79
+ for (const srcFile of data.sourceFiles) {
80
+ const resolved = resolveProjectPath(srcFile, repoRoot, node.absolutePath);
81
+ if (resolved && !existsSync(resolved)) {
82
+ violations.push({
83
+ type: 'error',
84
+ filePath,
85
+ code: 'MISSING_SOURCE_FILE',
86
+ message: `Source file "${srcFile}" does not exist on disk`,
87
+ });
88
+ }
89
+ }
90
+ // Check test files exist
91
+ for (const testFile of data.testFiles) {
92
+ const resolved = resolveProjectPath(testFile, repoRoot, node.absolutePath);
93
+ if (resolved && !existsSync(resolved)) {
94
+ violations.push({
95
+ type: 'warning',
96
+ filePath,
97
+ code: 'MISSING_TEST_FILE',
98
+ message: `Test file "${testFile}" does not exist on disk`,
99
+ });
100
+ }
101
+ }
102
+ // Check commit hashes exist in git history
103
+ if (repoRoot) {
104
+ for (const hash of data.commits) {
105
+ if (!commitExists(hash, repoRoot)) {
106
+ violations.push({
107
+ type: 'warning',
108
+ filePath,
109
+ code: 'COMMIT_NOT_FOUND',
110
+ message: `Commit "${hash}" does not exist in git history`,
111
+ });
112
+ }
113
+ }
114
+ }
115
+ return violations;
116
+ }
117
+ function readBehaviourState(node) {
118
+ try {
119
+ const content = readFileSync(join(node.absolutePath, 'usecase.md'), 'utf-8');
120
+ const doc = parseMarkdown(join(node.absolutePath, 'usecase.md'), content);
121
+ const match = /\*\*State:\*\*\s*(\S+)/.exec(doc.sections.get('status')?.rawBody ?? '');
122
+ return match?.[1]?.trim() ?? 'unknown';
123
+ }
124
+ catch {
125
+ return 'unknown';
126
+ }
127
+ }
128
+ function checkUnimplementedBehaviour(node) {
129
+ const hasImplChild = node.children.some(c => c.marker === 'impl');
130
+ if (hasImplChild)
131
+ return [];
132
+ if (readBehaviourState(node) === 'deferred')
133
+ return [];
134
+ return [{
135
+ type: 'warning',
136
+ filePath: join(node.absolutePath, 'usecase.md'),
137
+ code: 'UNIMPLEMENTED_BEHAVIOUR',
138
+ message: `Behaviour "${node.name}" has no implementation folders`,
139
+ }];
140
+ }
141
+ /**
142
+ * Try to resolve a project-relative path.
143
+ * Paths starting with src/, test/, etc. are resolved from repo root.
144
+ * Relative paths (../foo) are resolved from the impl folder.
145
+ */
146
+ /**
147
+ * Try to resolve a project-relative path.
148
+ * Relative paths (../foo, ./foo) resolve from the impl folder.
149
+ * Other paths (src/foo.ts) resolve from repo root, falling back to cwd.
150
+ */
151
+ function resolveProjectPath(filePath, repoRoot, implDir) {
152
+ if (filePath.startsWith('./') || filePath.startsWith('../')) {
153
+ return resolve(implDir, filePath);
154
+ }
155
+ return resolve(repoRoot ?? process.cwd(), filePath);
156
+ }
157
+ //# sourceMappingURL=check-orphans.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-orphans.js","sourceRoot":"","sources":["../../src/commands/check-orphans.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Command } from 'commander';
2
+ import { type LanguagePack } from '../core/language.js';
3
+ /** Walk all impl.md files on disk and build a map of source file path → impl.md path. */
4
+ export declare function buildSourceToImplMap(cwd: string): Map<string, string>;
5
+ export interface SpecFailure {
6
+ file: string;
7
+ message: string;
8
+ hint: string;
9
+ }
10
+ export declare function checkUsecaseQuality(filePath: string, content: string, pack?: LanguagePack | null): SpecFailure[];
11
+ export declare function checkIntentQuality(filePath: string, content: string, pack?: LanguagePack | null): SpecFailure[];
12
+ export declare function runCommithook(options: {
13
+ cwd: string;
14
+ }): Promise<number>;
15
+ export declare function registerCommithook(program: Command): void;